Amazon API Gateway Deployment with CloudFormation: Difference between revisions

From NovaOrdis Knowledge Base
Jump to navigation Jump to search
 
(28 intermediate revisions by the same user not shown)
Line 3: Line 3:
* https://currentlyunnamed-theclassic.blogspot.com/2018/12/mastering-cloudformation-for-api.html
* https://currentlyunnamed-theclassic.blogspot.com/2018/12/mastering-cloudformation-for-api.html
* https://stackoverflow.com/questions/41423439/cloudformation-doesnt-deploy-to-api-gateway-stages-on-update
* https://stackoverflow.com/questions/41423439/cloudformation-doesnt-deploy-to-api-gateway-stages-on-update
* [https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-reference-apigateway.html Amazon API Gateway Resource Types Reference]


=Internal=
=Internal=
Line 27: Line 28:
         Bucket: 'ovidiu-experiments'
         Bucket: 'ovidiu-experiments'
         Key: 'openapi-aws.json'
         Key: 'openapi-aws.json'
The "Name" property, if specified, overrides OpenAPI document [[OpenAPI_Specification#title|title]].


==AWS::ApiGateway::Deployment==
==AWS::ApiGateway::Deployment==
Line 39: Line 42:
       RestApiId: !Ref Api
       RestApiId: !Ref Api
       Description: 'something'
       Description: 'something'
If StageName: is specified and the stage does not exist, it will be created.


==AWS::ApiGateway::Stage==
==AWS::ApiGateway::Stage==
{{External|[https://docs.aws.amazon.com/apigateway/api-reference/resource/stage REST API Reference - Stage]}}
{{External|[https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-stage.html AWS::ApiGateway::Stage]}}
{{External|[https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-stage.html AWS::ApiGateway::Stage]}}


Line 53: Line 59:
       RestApiId: !Ref Api
       RestApiId: !Ref Api
       DeploymentId: !Ref ApiDeployment
       DeploymentId: !Ref ApiDeployment
===Execution Logging Configuration===
<syntaxhighlight lang='yaml'>
Resources:
  Stage:
    Type: AWS::ApiGateway::Stage
    ...
    Properties:
      ...
      MethodSettings:
        - ResourcePath: '/*'
          HttpMethod: '*'
          LoggingLevel: 'INFO'
</syntaxhighlight>
The above configuration turns on execution logging for all resource paths and all http methods. Individual configuration can be specified, for details see [https://docs.aws.amazon.com/apigateway/api-reference/resource/stage/#methodSettings Stage Reference - methodSettings].
For more details on API Gateway execution logging see: {{Internal|Amazon_API_Gateway_Concepts#CloudWatch_Execution_Logging|API Gateway CloudWatch Execution Logging}}
===Access Logging Configuration===
<syntaxhighlight lang='yaml'>
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"}
</syntaxhighlight>
For more details about access logging, see: {{Internal|Amazon_API_Gateway_Concepts#CloudWatch_Access_Logging|API Gateway CloudWatch Access Logging}}


==AWS::ApiGateway::VpcLink==
==AWS::ApiGateway::VpcLink==
{{External|[https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-vpclink.html AWS::ApiGateway::VpcLink]}}
{{External|[https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-vpclink.html 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'
        [[Amazon_API_Gateway_Concepts#Target_Load_Balancer|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=
=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 [[#AWS::ApiGateway::RestApi|above]],  works fine: the new API content is deployed and visible in the console. One would expect that the AWS::ApiGateway::Deployment resource, declared [[#AWS::ApiGateway::Deployment|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.
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 [[#AWS::ApiGateway::RestApi|above]],  works fine: the new API content is deployed and visible in the console. One would expect that the AWS::ApiGateway::Deployment resource, declared [[#AWS::ApiGateway::Deployment|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:
* https://medium.com/@ngchiwang/aws-apigateway-deployment-not-update-3e04fcffe85b. This one did not work, the template modified as described triggered a validation error: "An error occurred (ValidationError) when calling the CreateStack operation: Template format error: Resource name ApiDeployment$timestamp is non alphanumeric."
* https://stackoverflow.com/questions/41423439/cloudformation-doesnt-deploy-to-api-gateway-stages-on-update


Possible solutions:
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:
Add a new AWS::ApiGateway::Deployment, with a different logical name, irrespective of whether we keep the old one or now:


<syntaxhighlight lang='yaml'>
<syntaxhighlight lang='yaml'>
Line 100: Line 175:
       - ApiDeployment2
       - ApiDeployment2
     Properties:
     Properties:
       StageName: !Sub 'v2'
       StageName: 'v2'
       RestApiId: !Ref Api
       RestApiId: !Ref Api
       DeploymentId: !Ref ApiDeployment2
       DeploymentId: !Ref ApiDeployment2
</syntaxhighlight>
</syntaxhighlight>


Timestamp
==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.
Nested stacks, that describe new Deployment and stage.


AWS CLI
==Lambda-Backed Custom Resource==
 
http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-custom-resources.html


=Organizatorium=
=Examples=


Simply changing the description of a Deployment does not triggers redeployment. Need a better mechanism.
* [[Amazon API Gateway Mock Integration built with CloudFormation|Example of API Gateway Mock Integration built with CloudFormation]]
* [[Amazon API Gateway HTTP Integration built with CloudFormation|Example of API Gateway HTTP Integration built with CloudFormation]]
* [[Amazon API Gateway Lambda Integration built with CloudFormation|Example of API Gateway Lambda Integration built with CloudFormation]]

Latest revision as of 17:53, 16 April 2019

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