---
AWSTemplateFormatVersion: '2010-09-09'

Description: Handel-created API Gateway application

Resources:
  LambdaRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: {{apiName}}
      Path: "/services/"
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: "Allow"
            Principal:
              Service:
              - "lambda.amazonaws.com"
            Action:
            - "sts:AssumeRole"
      {{#if permissionsBoundary}}
      PermissionsBoundary: {{permissionsBoundary}}
      {{/if}}
  LambdaPolicy:
    Type: AWS::IAM::Policy
    Properties:
      PolicyName: {{apiName}}
      Roles:
      - !Ref LambdaRole
      PolicyDocument:
        Version: "2012-10-17"
        Statement:
        {{#each policyStatements}}
        - Effect: {{Effect}}
          Action:
          {{#each Action}}
          - '{{{this}}}'
          {{/each}}
          Resource:
          {{#each Resource}}
          - '{{{this}}}'
          {{/each}}
        {{/each}}
  LambdaFunctionApiEventPermission:
    Type: AWS::Lambda::Permission
    Properties:
      Action: lambda:invokeFunction
      Principal: apigateway.amazonaws.com
      FunctionName:
        Ref: LambdaFunction
      SourceArn:
        Fn::Sub:
        - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/*/*/*
        - __ApiId__:
            Ref: ServerlessRestApi
  ServerlessRestApiDeployment:
    Type: AWS::ApiGateway::Deployment
    Properties:
      RestApiId:
        Ref: ServerlessRestApi
      Description: 'RestApi Deployment for {{apiName}}'
      StageName: {{stageName}}
  LambdaFunction:
    Type: AWS::Lambda::Function
    DependsOn:
    - LambdaPolicy # Explicitly required for VPC lambdas, otherwise policy isn't ready and attached before Lambda creation
    Properties:
      Code:
        S3Bucket: {{s3Bucket}}
        S3Key: {{s3Key}}
      Description: {{description}}
      FunctionName: {{apiName}}
      MemorySize: {{provisionedMemory}}
      {{#if environment_variables}}
      Environment:
        Variables:
          {{#each environment_variables}}
          {{@key}}: {{this}}
          {{/each}}
      {{/if}}
      Handler: {{handlerFunction}}
      Role: !GetAtt LambdaRole.Arn
      Timeout: {{functionTimeout}}
      {{#if vpc}}
      VpcConfig:
        SecurityGroupIds: 
        {{#each vpcSecurityGroupIds}}
        - {{this}}
        {{/each}}
        SubnetIds: 
        {{#each vpcSubnetIds}}
        - {{this}}
        {{/each}}
      {{/if}}
      Runtime: {{lambdaRuntime}}
      {{#if tags}}
      Tags:
      {{#each tags}}
      - Key: {{@key}}
        Value: {{this}}
      {{/each}}
      {{/if}}
  ServerlessRestApi:
    Type: AWS::ApiGateway::RestApi
    Properties:
      {{#if binaryMediaTypes}}
      BinaryMediaTypes:
      {{#each binaryMediaTypes}}
      - '{{{this}}}'
      {{/each}}
      {{/if}}
      Body:
        info:
          version: '1.0'
          title: {{apiName}}
          description: {{description}}
        paths:
          "/{proxy+}":
            x-amazon-apigateway-any-method:
              x-amazon-apigateway-integration:
                httpMethod: POST
                type: aws_proxy
                uri:
                  Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${LambdaFunction.Arn}/invocations
              responses: {}
        swagger: '2.0'

  {{#each customDomains}}
  CustomDomain{{logicalId name}}:
    Type: AWS::ApiGateway::DomainName
    Properties:
      CertificateArn: {{certificateArn}}
      DomainName: {{name}}
  CustomDomainBasePath{{logicalId name}}:
    Type: AWS::ApiGateway::BasePathMapping
    Properties:
      DomainName: !Ref CustomDomain{{logicalId name}}
      RestApiId: !Ref ServerlessRestApi
      Stage: {{../stageName}}
  CustomDomainDns{{logicalId name}}:
    Type: AWS::Route53::RecordSetGroup
    Properties:
      HostedZoneId: {{zoneId}}
      Comment: Handel-created DNS Records for {{name}}
      RecordSets:
      - Name: {{name}}
        Type: A
        AliasTarget:
          HostedZoneId: Z2FDTNDATAQYW2 # This is Cloudfront's zone
          DNSName: !GetAtt CustomDomain{{logicalId name}}.DistributionDomainName
      - Name: {{name}}
        Type: AAAA
        AliasTarget:
          HostedZoneId: Z2FDTNDATAQYW2 # This is Cloudfront's zone
          DNSName: !GetAtt CustomDomain{{logicalId name}}.DistributionDomainName
  {{/each}}

  {{#if warmup}}
  LambdaWarmupPermission:
    Type: "AWS::Lambda::Permission"
    Properties:
      Action: 'lambda:InvokeFunction'
      FunctionName: !Ref LambdaFunction
      Principal: events.amazonaws.com
      SourceArn: !GetAtt LambdaWarmupEvent.Arn

  LambdaWarmupEvent:
    Type: "AWS::Events::Rule"
    Properties:
      Description: "Handel-created warmup rule for {{apiName}}"
      Name: "{{apiName}}-warmup"
      ScheduleExpression: "{{warmup.schedule}}"
      State: ENABLED
      Targets:
      {{#unless warmup.httpPaths}}
        - Id: {{apiName}}
          Arn: !GetAtt LambdaFunction.Arn
      {{else}}
      {{#each warmup.httpPaths}}
        - Id: {{logicalId ../apiName}}{{logicalId path}}
          Arn: !GetAtt LambdaFunction.Arn
          Input:
            Fn::Sub: {{eventBody}}
      {{/each}}
      {{/unless}}
  {{/if}}

Outputs:
  LambdaArn:
    Value:
      Fn::GetAtt: LambdaFunction.Arn
  RestApiId:
    Value:
      Ref: ServerlessRestApi
  DeploymentId:
    Value:
      Ref: ServerlessRestApiDeployment
