AWSTemplateFormatVersion: 2010-09-09 Parameters: ProjectName: Description: >- Used as a prefix for project resources. Can be up to 30 characters, lowercase letters (a-z) only. Type: String Default: demobookstore AllowedPattern: '^[a-z]{1,30}' ConstraintDescription: >- The ProjectName can be up to 30 characters, lowercase letters (a-z) only. Conditions: IADRegion: !Equals - !Ref 'AWS::Region' - us-east-1 Mappings: S3Buckets: us-east-1: Bucket: aws-devops-end-to-end-workshop-us-east-1 NeptuneDataBucket: aws-devops-end-to-end-workshop-neptune-us-east-1 us-west-2: Bucket: aws-devops-end-to-end-workshop-us-west-2 NeptuneDataBucket: aws-devops-end-to-end-workshop-neptune-us-west-2 eu-central-1: Bucket: aws-devops-end-to-end-workshop-eu-central-1 NeptuneDataBucket: aws-devops-end-to-end-workshop-neptune-eu-central-1 eu-west-1: Bucket: aws-devops-end-to-end-workshop-eu-west-1 NeptuneDataBucket: aws-devops-end-to-end-workshop-neptune-eu-west-1 Constants: AppKeys: SeedRepository: 'https://s3.amazonaws.com/aws-devops-end-to-end-workshop-us-east-1/bookstore-webapp.zip' S3Keys: GetBookCode: functions/GetBook.zip ListBooksCode: functions/ListBooks.zip Resources: FunctionGetBook: Type: 'AWS::Lambda::Function' Properties: FunctionName: !Sub '${ProjectName}-GetBook' Description: Get book by id Handler: index.handler MemorySize: 256 Runtime: nodejs12.x Role: !ImportValue 'Fn::Sub': '${ProjectName}-DynamoDbRoleARN' Timeout: 120 Environment: Variables: TABLE_NAME: !Sub '${ProjectName}-Books' Code: S3Bucket: !FindInMap - S3Buckets - !Ref 'AWS::Region' - Bucket S3Key: !FindInMap - Constants - S3Keys - GetBookCode Metadata: 'AWS::CloudFormation::Designer': id: 1ae22cac-5803-4077-a6fe-1a3ca1aedfc2 FunctionListBooks: Type: 'AWS::Lambda::Function' Properties: FunctionName: !Sub '${ProjectName}-ListBooks' Description: Get list of books by category Handler: index.handler MemorySize: 256 Runtime: nodejs12.x Role: !ImportValue 'Fn::Sub': '${ProjectName}-DynamoDbRoleARN' Timeout: 120 Environment: Variables: TABLE_NAME: !Sub '${ProjectName}-Books' Code: S3Bucket: !FindInMap - S3Buckets - !Ref 'AWS::Region' - Bucket S3Key: !FindInMap - Constants - S3Keys - ListBooksCode Metadata: 'AWS::CloudFormation::Designer': id: 8e306d11-6d48-49e0-8f69-760139c83447 FunctionGetBookPermissions: Type: 'AWS::Lambda::Permission' Properties: Action: 'lambda:InvokeFunction' FunctionName: !Ref FunctionGetBook Principal: apigateway.amazonaws.com SourceArn: !Join - '' - - 'arn:aws:execute-api:' - !Ref 'AWS::Region' - ':' - !Ref 'AWS::AccountId' - ':' - !ImportValue 'Fn::Sub': '${ProjectName}-AppApiRef' - /* Metadata: 'AWS::CloudFormation::Designer': id: 06a821b7-638e-471c-ab50-51710b73767c FunctionListBooksPermissions: Type: 'AWS::Lambda::Permission' Properties: Action: 'lambda:InvokeFunction' FunctionName: !Ref FunctionListBooks Principal: apigateway.amazonaws.com SourceArn: !Join - '' - - 'arn:aws:execute-api:' - !Ref 'AWS::Region' - ':' - !Ref 'AWS::AccountId' - ':' - !ImportValue 'Fn::Sub': '${ProjectName}-AppApiRef' - /* Metadata: 'AWS::CloudFormation::Designer': id: 06a821b7-638e-471c-ab50-51710b73767c BooksApiRequestGET: DependsOn: - FunctionListBooksPermissions Type: 'AWS::ApiGateway::Method' Properties: AuthorizationType: AWS_IAM HttpMethod: GET Integration: Type: AWS_PROXY IntegrationHttpMethod: POST Uri: !Join - '' - - 'arn:aws:apigateway:' - !Ref 'AWS::Region' - ':lambda:path/2015-03-31/functions/' - !GetAtt - FunctionListBooks - Arn - /invocations IntegrationResponses: - StatusCode: 200 RequestParameters: method.request.querystring.category: false ResourceId: !Ref BooksApiResource RestApiId: !ImportValue 'Fn::Sub': '${ProjectName}-AppApiRef' MethodResponses: - StatusCode: 200 ResponseModels: application/json: Empty Metadata: 'AWS::CloudFormation::Designer': id: 5a740957-6b64-4ddd-bd1d-3027df7fc6d5 BooksApiRequestOPTIONS: Type: 'AWS::ApiGateway::Method' Properties: ResourceId: !Ref BooksApiResource RestApiId: !ImportValue 'Fn::Sub': '${ProjectName}-AppApiRef' AuthorizationType: None HttpMethod: OPTIONS Integration: Type: MOCK IntegrationResponses: - ResponseParameters: method.response.header.Access-Control-Allow-Headers: >- 'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token' method.response.header.Access-Control-Allow-Methods: '''GET,POST,PUT,DELETE,OPTIONS,HEAD,PATCH''' method.response.header.Access-Control-Allow-Origin: '''*''' ResponseTemplates: application/json: '' StatusCode: '200' PassthroughBehavior: WHEN_NO_MATCH RequestTemplates: application/json: '{"statusCode": 200}' MethodResponses: - ResponseModels: application/json: Empty ResponseParameters: method.response.header.Access-Control-Allow-Headers: true method.response.header.Access-Control-Allow-Methods: true method.response.header.Access-Control-Allow-Origin: true StatusCode: '200' Metadata: 'AWS::CloudFormation::Designer': id: f0f16a94-104a-431f-8c87-930f56274955 BookItemApiRequestGET: DependsOn: FunctionGetBookPermissions Type: 'AWS::ApiGateway::Method' Properties: AuthorizationType: AWS_IAM HttpMethod: GET Integration: Type: AWS_PROXY IntegrationHttpMethod: POST Uri: !Join - '' - - 'arn:aws:apigateway:' - !Ref 'AWS::Region' - ':lambda:path/2015-03-31/functions/' - !GetAtt - FunctionGetBook - Arn - /invocations IntegrationResponses: - StatusCode: 200 ResponseTemplates: application/json: $input.json('$.body') RequestParameters: method.request.path.id: true ResourceId: !Ref BookItemApiResource RestApiId: !ImportValue 'Fn::Sub': '${ProjectName}-AppApiRef' MethodResponses: - StatusCode: 200 ResponseModels: application/json: Empty Metadata: 'AWS::CloudFormation::Designer': id: a311ee38-d902-4856-9f09-1d00d1bc8600 BookItemApiRequestOPTIONS: Type: 'AWS::ApiGateway::Method' Properties: ResourceId: !Ref BookItemApiResource RestApiId: !ImportValue 'Fn::Sub': '${ProjectName}-AppApiRef' AuthorizationType: None HttpMethod: OPTIONS Integration: Type: MOCK IntegrationResponses: - ResponseParameters: method.response.header.Access-Control-Allow-Headers: >- 'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token' method.response.header.Access-Control-Allow-Methods: '''GET,POST,PUT,DELETE,OPTIONS,HEAD,PATCH''' method.response.header.Access-Control-Allow-Origin: '''*''' ResponseTemplates: application/json: '' StatusCode: '200' PassthroughBehavior: WHEN_NO_MATCH RequestTemplates: application/json: '{"statusCode": 200}' MethodResponses: - ResponseModels: application/json: Empty ResponseParameters: method.response.header.Access-Control-Allow-Headers: true method.response.header.Access-Control-Allow-Methods: true method.response.header.Access-Control-Allow-Origin: true StatusCode: '200' Metadata: 'AWS::CloudFormation::Designer': id: c31e25ac-e338-4d21-9e4b-881a16e0a494 BooksApiResource: Type: 'AWS::ApiGateway::Resource' Properties: RestApiId: !ImportValue 'Fn::Sub': '${ProjectName}-AppApiRef' ParentId: !ImportValue 'Fn::Sub': '${ProjectName}-AppApiParentId' PathPart: books Metadata: 'AWS::CloudFormation::Designer': id: e0ffbcc7-5f62-43ac-b377-47ec80a5a71e BookItemApiResource: Type: 'AWS::ApiGateway::Resource' Properties: RestApiId: !ImportValue 'Fn::Sub': '${ProjectName}-AppApiRef' ParentId: !Ref BooksApiResource PathPart: '{id}' Metadata: 'AWS::CloudFormation::Designer': id: 25b4ecc5-9d47-49cb-b5c4-d03574eee62e APIDeployment: DependsOn: - BooksApiRequestGET - BooksApiRequestOPTIONS - BookItemApiRequestGET - BookItemApiRequestOPTIONS Type: 'AWS::ApiGateway::Deployment' DeletionPolicy: Retain Properties: Description: Prod deployment for API RestApiId: !ImportValue 'Fn::Sub': '${ProjectName}-AppApiRef' StageName: prod Metadata: 'AWS::CloudFormation::Designer': id: 278dda65-02c9-49fa-a19c-3dd7afd25683