Amazon API Gateway Deployment with CloudFormation: Difference between revisions
No edit summary |
|||
(31 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 54: | Line 60: | ||
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= | |||
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: | |||
==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: | |||
<syntaxhighlight lang='yaml'> | |||
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 | |||
</syntaxhighlight> | |||
==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= | |||
* [[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
- 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
- Amazon API Gateway Resource Types Reference
Internal
Overview
Resource Types
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
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
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:
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:
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:
- 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:
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