constructor()

in cloud-infra-demo/lib/cloud-infra-demo-stack.ts [15:174]


  constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
    
    super(scope, id, props);
    
    const envName = this.node.tryGetContext("envName");
    if(!envName) {
      throw new Error('No environemnt name provided for stack');
    }
    /*********************************
     * LAMBDA FUNCTIONS DECLARATIONS
     * **********************************/
    
    const awsEnterpriseApplicationDemoLambda = new lambda.Function(this, 'awsEnterpriseApplicationDemo'+envName, {
      code: new lambda.AssetCode('../lambda/main.zip'),
      functionName: "awsEnterpriseApplicationDemo"+envName,
      handler: 'main',
      runtime: lambda.Runtime.GO_1_X,
      environment: {
        LAMBDA_ENV: envName
      }
    });

    /**********************
    * DYNAMO DB TABLE
    *************************/
   const table = new dynamodb.Table(this, 'Table', {
    tableName: "aws-crud-demo-config-" + envName,
    partitionKey: { name: 'code', type: dynamodb.AttributeType.STRING },
    sortKey: {name: 'itemType', type: dynamodb.AttributeType.STRING }
    });

    //grant lamda fnuction access to our dynamo table
   table.grantReadWriteData(awsEnterpriseApplicationDemoLambda);

  /**********************
   * API GATEWAY
   *************************/
  const api = new apigateway.RestApi(this, 'awsCrudDemo'+envName, {
    restApiName: 'awsCrudDemo'+envName,
    deployOptions: {
      loggingLevel: apigateway.MethodLoggingLevel.INFO,
      dataTraceEnabled: true
    }
  });

  const config = api.root.addResource('config',{
    defaultMethodOptions: {
      methodResponses: [
        {statusCode: "200"}
      ]
    }
  });

  addCorsOptions(config);
  config.addMethod('GET', buildConfigLambdaIntegration("listHotels"),methodOptions());
  config.addMethod('POST', buildConfigLambdaIntegration("saveHotel"),methodOptions());
  //config/{id}
  const configId = config.addResource('{id}');
  configId.addMethod('GET', buildConfigLambdaIntegration("getHotel"),methodOptions());
  addCorsOptions(configId);
  //config/{id}/rooms
  const configIdRooms= configId.addResource('rooms');
  addCorsOptions(configIdRooms);
  //config/{id}/rooms/type
  const configIdRoomsType= configIdRooms.addResource('type');
  addCorsOptions(configIdRoomsType);
  configIdRoomsType.addMethod('POST', buildConfigLambdaIntegration("addRoomType"),methodOptions());
  //config/{id}/rooms/type/{typecode}
  const configIdRoomsTypeTypeCode= configIdRoomsType.addResource('{typecode}');
  addCorsOptions(configIdRoomsTypeTypeCode);
  configIdRoomsTypeTypeCode.addMethod('DELETE', buildConfigLambdaIntegration("deleteRoomType",buildDeleteRoomTypeTpl("deleteRoomType")),methodOptions());

  /********************
   * Utilility methods
   * This is a set of reuable methods to create some standard configuration objects
   * to be used for the definition of API gateway enpoints (this includes CORS configuration,
   * Lambda integartion mapping template...)
   */

  function methodOptions(): apigateway.MethodOptions {
    return {
      methodResponses: [
        {statusCode: "200"}
      ]
    } 
  }

  function buildConfigLambdaIntegration(fnName : string, customBody?: string): any{
    return new apigateway.LambdaIntegration(awsEnterpriseApplicationDemoLambda,{
      proxy: false,
      requestTemplates: {
        'application/json': customBody || buildDefaultTpl(fnName)
      },
      integrationResponses : [{
        statusCode: "200"
      }]
    });
  }

  function buildDefaultTpl(functionName: string): string {
    return JSON.stringify({ 
      "userInfo" : buildUserInfoTpl(),
      "request" : "velocity1",
      "subFunction" : functionName,
      "id": "$input.params().path['id']"
    }).replace("\"velocity1\"","$input.json('$$')");
  }

  function buildUserInfoTpl(): any {
    return {
      "sub" : "$context.authorizer.claims.sub",
      "email" : "$context.authorizer.claims.email",
      "username" : "$context.authorizer.claims['cognito:username']"
    }
  }

  function buildDeleteRoomTypeTpl(functionName: string): string {
    return JSON.stringify({ 
      "userInfo" : buildUserInfoTpl(),
      "request" : {
        "code" : "$input.params().path['id']",
        "tags" : [
            {
                "code" : "$input.params().path['tagId']"
            }
        ]
    },
      "subFunction" : functionName
    });
  }

  function addCorsOptions(apiResource: apigateway.IResource) {
    apiResource.addMethod('OPTIONS', new apigateway.MockIntegration({
      integrationResponses: [{
        statusCode: '200',
        responseParameters: {
          'method.response.header.Access-Control-Allow-Headers': "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,X-Amz-User-Agent'",
          'method.response.header.Access-Control-Allow-Origin': "'*'",
          'method.response.header.Access-Control-Allow-Credentials': "'false'",
          'method.response.header.Access-Control-Allow-Methods': "'OPTIONS,GET,PUT,POST,DELETE'",
        },
      }],
      passthroughBehavior: apigateway.PassthroughBehavior.NEVER,
      requestTemplates: {
        "application/json": "{\"statusCode\": 200}"
      },
    }), {
      methodResponses: [{
        statusCode: '200',
        responseParameters: {
          'method.response.header.Access-Control-Allow-Headers': true,
          'method.response.header.Access-Control-Allow-Methods': true,
          'method.response.header.Access-Control-Allow-Credentials': true,
          'method.response.header.Access-Control-Allow-Origin': true,
        },  
      }]
    })
  }
    
  }