---
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}}

  {{#each lambdasToCreate}}
  LambdaFunctionApiEventPermission{{@index}}:
    Type: AWS::Lambda::Permission
    Properties:
      Action: lambda:invokeFunction
      Principal: apigateway.amazonaws.com
      FunctionName:
        Ref: LambdaFunction{{@index}}
      SourceArn:
        Fn::Sub:
        - arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${__ApiId__}/*/*/*
        - __ApiId__:
            Ref: RestApi
  LambdaFunction{{@index}}:
    Type: AWS::Lambda::Function
    DependsOn:
    - LambdaPolicy # Explicitly required for VPC lambdas, otherwise policy isn't ready and attached before Lambda creation
    Properties:
      Code:
        S3Bucket: {{s3ArtifactInfo.Bucket}}
        S3Key: {{s3ArtifactInfo.Key}}
      Description: {{../description}}
      FunctionName: {{fullName}}
      MemorySize: {{provisionedMemory}}
      {{#if environmentVariables}}
      Environment:
        Variables:
          {{#each environmentVariables}}
          {{@key}}: {{this}}
          {{/each}}
      {{/if}}
      Handler: {{handler}}
      Role: !GetAtt LambdaRole.Arn
      Timeout: {{timeout}}
      {{#if ../vpc}}
      VpcConfig:
        SecurityGroupIds: 
        {{#each ../vpcSecurityGroupIds}}
        - {{this}}
        {{/each}}
        SubnetIds: 
        {{#each ../vpcSubnetIds}}
        - {{this}}
        {{/each}}
      {{/if}}
      Runtime: {{runtime}}
      {{#if ../tags}}
      Tags:
      {{#each ../tags}}
      - Key: {{@key}}
        Value: {{this}}
      {{/each}}
      {{/if}}

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

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

  {{/each}}
  Deployment{{deploymentIdSuffix}}:
    Type: AWS::ApiGateway::Deployment
    Properties:
      RestApiId:
        Ref: RestApi
      Description: 'Deployment for {{apiName}}'
      StageName: {{stageName}}
  RestApi:
    Type: AWS::ApiGateway::RestApi
    Properties:
      {{#if binaryMediaTypes}}
      BinaryMediaTypes:
      {{#each binaryMediaTypes}}
      - '{{{this}}}'
      {{/each}}
      {{/if}}
      Description: {{description}}
      Name: {{apiName}}
      BodyS3Location:
        Bucket: {{swaggerS3ArtifactInfo.Bucket}}
        Key: {{swaggerS3ArtifactInfo.Key}}

  {{#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 RestApi
      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}}


Outputs:
  RestApiId:
    Value:
      Ref: RestApi
  DeploymentId:
    Value:
      Ref: Deployment{{deploymentIdSuffix}}
