Amazon API Gateway Deployment with CloudFormation

From NovaOrdis Knowledge Base
Jump to navigation Jump to search

External

Internal

Overview

Resource Types

AWS::ApiGateway::RestApi

AWS::ApiGateway::RestApi
Resources:
  Api:
    Type: AWS::ApiGateway::RestApi
    Properties:
      Name: 'experimental-api'
      Description: 'An experimental API, deployed programmatically'
      FailOnWarnings: true
      BodyS3Location:
        Bucket: 'ovidiu-experiments'
        Key: 'openapi-aws.json'

The "Name" property, if specified, overrides OpenAPI document title.

AWS::ApiGateway::Deployment

AWS::ApiGateway::Deployment
Resources:
 ApiDeployment:
   Type: AWS::ApiGateway::Deployment
   DependsOn: Api
   Properties:
     RestApiId: !Ref Api
     Description: 'something'

If StageName: is specified and the stage does not exist, it will be created.

AWS::ApiGateway::Stage

REST API Reference - Stage
AWS::ApiGateway::Stage
Resources:
  Stage:
    Type: AWS::ApiGateway::Stage
    DependsOn:
      - Api
      - ApiDeployment
    Properties:
      StageName: 'dev'
      RestApiId: !Ref Api
      DeploymentId: !Ref ApiDeployment

Execution Logging Configuration

Resources:
  Stage:
    Type: AWS::ApiGateway::Stage
    ...
    Properties:
      ...
      MethodSettings:
        - ResourcePath: '/*'
          HttpMethod: '*'
          LoggingLevel: 'INFO'

The above configuration turns on execution logging for all resource paths and all http methods. Individual configuration can be specified, for details see Stage Reference - methodSettings.

For more details on API Gateway execution logging see:

API Gateway CloudWatch Execution Logging

Access Logging Configuration

Resources:
  AccessLogGroup:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName: ...

  ...

  Stage:
    Type: AWS::ApiGateway::Stage
    ...
    Properties:
      ...
      AccessLogSetting:
        DestinationArn: !GetAtt AccessLogGroup.Arn
        Format: >-
          {"requestId":"$context.requestId", "ip": "$context.identity.sourceIp",
          "caller":"$context.identity.caller",
          "user":"$context.identity.user","requestTime":"$context.requestTime",
          "eventType":"$context.eventType","routeKey":"$context.routeKey",
          "status":"$context.status","connectionId":"$context.connectionId"}

For more details about access logging, see:

API Gateway CloudWatch Access Logging

AWS::ApiGateway::VpcLink

AWS::ApiGateway::VpcLink
Parameters:
  NetworkLoadBalancerArn:
   Type: String
   Default: arn:aws:elasticloadbalancing:us-west-2:777777777777:loadbalancer/net/some-nlb/1a49bf234253e5a0

Resources:
  VpcLink:
     Type: AWS::ApiGateway::VpcLink
     Properties:
       Name: 'blue'
       Description: 'Some description'
       TargetArns:
         - !Ref NetworkLoadBalancerArn

Note that if the load balancer is created as part of the same stack, !Ref NetworkLoadBalancer returns the ARN.

If an ALB ARN is used, the VpcLink creation will fail with a complain about the inconsistent load balancer ARN.

Idiosyncrasy

As per March 2019, an attempt to re-deploy a new version of an API, as expressed in a version of an Open API file, with CloudFormation, does not work as expected. CloudFormation AWS::ApiGateway::RestApi resource update, as described above, works fine: the new API content is deployed and visible in the console. One would expect that the AWS::ApiGateway::Deployment resource, declared above, would detect that the API changed and re-snapshot it. However, that does not happens. No new deployment is created. As consequence, the stage points to a stale deployment. Changing the description of a Deployment does not work either, the description will be updated on the current deployment, but the content of the API snapshot won't change.

On the same subject:

Possible solutions:

Add Deployments and Stages to the Template

Add a new AWS::ApiGateway::Deployment, with a different logical name, irrespective of whether we keep the old one or now:

Resources:
  Api:
    ...

  ApiDeployment:
    Type: AWS::ApiGateway::Deployment
    DependsOn: Api
    Properties:
      RestApiId: !Ref Api

  Stage:
    Type: AWS::ApiGateway::Stage
    DependsOn:
      - Api
      - ApiDeployment
    Properties:
      StageName: !Sub 'v0'
      RestApiId: !Ref Api
      DeploymentId: !Ref ApiDeployment

  ApiDeployment2:
    Type: AWS::ApiGateway::Deployment
    DependsOn: Api
    Properties:
      RestApiId: !Ref Api

  Stage2:
    Type: AWS::ApiGateway::Stage
    DependsOn:
      - Api
      - ApiDeployment2
    Properties:
      StageName: 'v2'
      RestApiId: !Ref Api
      DeploymentId: !Ref ApiDeployment2

Dynamically Change The Stack Template and Modify the API Deployment and Stage Logical IDs

Use timestamp or a counter.

Deploy API via CLI

Do not deploy the API and create the Stage with CloudFormation, but programmatically via CLI, from a follow up action.

Nested Stacks

Nested stacks, that describe new Deployment and stage.

Lambda-Backed Custom Resource

http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-custom-resources.html

Examples