constructor()

in lib/lambda-resources.ts [29:170]


  constructor(scope: cdk.Construct, id: string, props: LambdaResourcesProps) {
    super(scope, id, props);

    this.bucket = new s3.Bucket(this, inputBucketName, {
      bucketName: inputBucketName + `-${cdk.Aws.ACCOUNT_ID}-${cdk.Aws.REGION}`,
      removalPolicy: cdk.RemovalPolicy.DESTROY, //<==FOR DEMO ONLY===
      autoDeleteObjects: true, // <==DEMO ONLY - NOT RECOMMENDED IN PRODUCTION===
    });

    this.inputBucketOutput = new cdk.CfnOutput(
      this,
      `${prefix}-input-bucket-output`,
      {
        value: `https://s3.console.aws.amazon.com/s3/buckets/${this.bucket.bucketName}?region=${cdk.Aws.REGION}&tab=objects`,
      }
    );

    this.inputBucketName = new cdk.CfnOutput(
      this,
      `${prefix}-input-bucket-name`,
      {
        value: this.bucket.bucketName,
      }
    );

    // =====================================================================================
    // Building our native real-time inference AWS Lambda Function
    // =====================================================================================

    const sciPyMXNetLayer = new lambda.LayerVersion(
      this,
      `${prefix}-mxnet-layer`,
      {
        code: lambda.Code.fromAsset(
          path.join(__dirname, "../lambda_fn/realtime_inf/layers/layer.zip")
        ),
        compatibleRuntimes: [lambda.Runtime.PYTHON_3_6],
      }
    );

    const RealtimeFn = new lambda.Function(this, `${prefix}-realtime-Fn`, {
      runtime: lambda.Runtime.PYTHON_3_6,
      code: lambda.Code.fromAsset(
        path.join(__dirname, "../lambda_fn/realtime_inf/realtime_fn")
      ),
      handler: "index.lambda_handler",
      layers: [sciPyMXNetLayer],
      memorySize: 3072,
      timeout: cdk.Duration.seconds(30),
    });

    const apiRole = new iam.Role(this, "APIRole", {
      assumedBy: new iam.ServicePrincipal("apigateway.amazonaws.com"),
    });

    apiRole.addToPolicy(
      new iam.PolicyStatement({
        effect: iam.Effect.ALLOW,
        actions: ["lambda:InvokeFunction"],
        resources: [RealtimeFn.functionArn],
      })
    );

    // =====================================================================================
    // Building our AWS Batch Job Submitter AWS Lambda Function
    // =====================================================================================

    const batchJobDef = cdk.Fn.select(
      0,
      props.batchLambdaParam.stringListValue
    );
    const batchJobQ = cdk.Fn.select(1, props.batchLambdaParam.stringListValue);

    const batchJobSubmitter = new lambda.Function(this, "batchJobSubmitterFn", {
      code: lambda.Code.fromAsset("lambda_fn/batch_jobs_submitter"),
      runtime: lambda.Runtime.PYTHON_3_7,
      handler: "index.handler",
      timeout: cdk.Duration.seconds(30),
      memorySize: 1024,
      environment: {
        ["JOB_NAME"]: batchJobName,
        ["JOB_QUEUE"]: batchJobQ,
        ["JOB_DEFINITION"]: batchJobDef,
      },
    });

    batchJobSubmitter.addEventSource(
      new event_sources.S3EventSource(this.bucket, {
        events: [
          s3.EventType.OBJECT_CREATED_PUT,
          s3.EventType.OBJECT_CREATED_POST,
        ],
        filters: [{ prefix: "input/" }],
      })
    );
    this.bucket.grantRead(batchJobSubmitter);

    batchJobSubmitter.addToRolePolicy(props.batchJobSubmitterPolicy);

    // =====================================================================================
    // Building our API Gateway
    // =====================================================================================
    const predictInteration = new api.LambdaIntegration(RealtimeFn, {
      integrationResponses: [{ statusCode: "200" }],
      requestTemplates: { ["application/jpeg"]: `{"content": "$input.body"}` },
      contentHandling: api.ContentHandling.CONVERT_TO_TEXT,
      passthroughBehavior: api.PassthroughBehavior.WHEN_NO_TEMPLATES,
      proxy: false,
    });
    const apiLog = new cwlogs.LogGroup(this, `${prefix}-api-logs`, {
      removalPolicy: cdk.RemovalPolicy.DESTROY,
      retention: cwlogs.RetentionDays.ONE_MONTH,
      logGroupName: `${prefix}-realtime-api`,
    });

    const predictApi = new api.RestApi(this, `${prefix}-predict-api`, {
      binaryMediaTypes: ["application/jpeg"],
      endpointTypes: [api.EndpointType.REGIONAL],
      deployOptions: {
        loggingLevel: api.MethodLoggingLevel.ERROR,
        accessLogDestination: new api.LogGroupLogDestination(apiLog),
        accessLogFormat: api.AccessLogFormat.jsonWithStandardFields(),
      },
    });
    const resource = predictApi.root.addResource("predict");
    resource.addMethod("POST", predictInteration, {
      methodResponses: [
        {
          statusCode: "200",
          responseModels: { ["application/json"]: api.Model.EMPTY_MODEL },
        },
      ],
    });

    this.httpApiUrl = new cdk.CfnOutput(this, "httpApiUrl", {
      value: `${predictApi.url}`,
    });

    this.lambdaAppUrl = new cdk.CfnOutput(this, "LambdaAppURL", {
      value: `https://${cdk.Aws.REGION}.console.aws.amazon.com/lambda/home?region=${cdk.Aws.REGION}#/applications/${this.stackName}`,
    });
  }