constructor()

in packages/blueprints/gen-ai-chatbot/static-assets/chatbot-genai-cdk/lib/constructs/vectorstore.ts [37:171]


  constructor(scope: Construct, id: string, props: VectorStoreProps) {
    super(scope, id);

    const sg = new ec2.SecurityGroup(this, "ClusterSecurityGroup", {
      vpc: props.vpc,
      description: "RDSClusterSecurityGroup",
    });
    const cluster = new rds.DatabaseCluster(this, "Cluster", {
      engine: rds.DatabaseClusterEngine.auroraPostgres({
        version: rds.AuroraPostgresEngineVersion.VER_15_3,
      }),
      vpc: props.vpc,
      securityGroups: [sg],
      defaultDatabaseName: DB_NAME,
      enableDataApi: true,
      serverlessV2MinCapacity: 0.5,
      serverlessV2MaxCapacity: 5.0,
      writer: rds.ClusterInstance.serverlessV2("writer", {
        autoMinorVersionUpgrade: true,
        publiclyAccessible: false,
      }),
      storageEncrypted: true,
      removalPolicy: RemovalPolicy.SNAPSHOT,
      // readers: [
      //   rds.ClusterInstance.serverlessV2("reader", {
      //     autoMinorVersionUpgrade: false,
      //   }),
      // ],
    });
    cluster.addRotationSingleUser();

    const dbClusterIdentifier = cluster
      .secret!.secretValueFromJson("dbClusterIdentifier")
      .unsafeUnwrap()
      .toString();

    if (props.rdsSchedule.hasCron()) {
      const rdsSchedulerRole = new Role(this, "role-rds-scheduler", {
        assumedBy: new ServicePrincipal("scheduler.amazonaws.com"),
        description: "start and stop RDS",
      });

      rdsSchedulerRole.addToPolicy(
        new PolicyStatement({
          resources: ["*"],
          effect: Effect.ALLOW,
          actions: ["rds:startDBCluster", "rds:stopDBCluster"],
        })
      );

      new CfnSchedule(this, "StartRdsScheduler", {
        description: "Start RDS Instance",
        scheduleExpression: events.Schedule.cron(props.rdsSchedule.startCron)
          .expressionString,
        flexibleTimeWindow: { mode: "OFF" },
        target: {
          arn: "arn:aws:scheduler:::aws-sdk:rds:startDBCluster",
          roleArn: rdsSchedulerRole.roleArn,
          input: JSON.stringify({
            DbClusterIdentifier: dbClusterIdentifier,
          }),
        },
      });

      new CfnSchedule(this, "StopRdsScheduler", {
        description: "Stop RDS Instance",
        scheduleExpression: events.Schedule.cron(props.rdsSchedule.stopCron)
          .expressionString,
        flexibleTimeWindow: { mode: "OFF" },
        target: {
          arn: "arn:aws:scheduler:::aws-sdk:rds:stopDBCluster",
          roleArn: rdsSchedulerRole.roleArn,
          input: JSON.stringify({
            DbClusterIdentifier: dbClusterIdentifier,
          }),
        },
      });
    }

    const setupHandler = new NodejsFunction(this, "CustomResourceHandler", {
      vpc: props.vpc,
      runtime: lambda.Runtime.NODEJS_18_X,
      entry: path.join(
        __dirname,
        "../../custom-resources/setup-pgvector/index.js"
      ),
      handler: "handler",
      timeout: Duration.minutes(5),
      environment: {
        DB_CLUSTER_IDENTIFIER: dbClusterIdentifier,
        DB_SECRETS_ARN: cluster.secret!.secretFullArn!,
      },
    });
    cluster.secret!.grantRead(setupHandler);

    sg.connections.allowFrom(
      setupHandler,
      ec2.Port.tcp(cluster.clusterEndpoint.port)
    );

    const cr = new CustomResource(this, "CustomResourceSetup", {
      serviceToken: setupHandler.functionArn,
      resourceType: "Custom::SetupVectorStore",
      properties: {
        // Dummy property to trigger
        id: cluster.clusterEndpoint.hostname,
      },
    });
    cr.node.addDependency(cluster);

    NagSuppressions.addResourceSuppressions(
      cr,
      [
        {
          id: "AwsPrototyping-IAMNoManagedPolicies",
          reason: "Default Policy",
          appliesTo: [
            {
              regex:
                "/^Policy::arn:<AWS::Partition>:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole/",
            },
          ],
        },
        {
          id: "AwsPrototyping-CodeBuildProjectKMSEncryptedArtifacts",
          reason: "SociIndexBuild is dependencies package",
        },
      ],
      true
    );

    this.securityGroup = sg;
    this.cluster = cluster;
    this.secret = cluster.secret!;
  }