In this post, I'll let you know a new feature introduced in AWS CLI version 1.16.36. Actually, It's just a tiny improvement. But if you use AWS SAM every day in development (like me), it'll make you a little bit happy.
Swagger in AWS SAM
If you use Swagger with AWS SAM to provision Amazon API Gateway, you should use the AWS::Serverless::Api resource. There are two ways to specify Swagger files in the resource:
- Specifying a Swagger file in an S3 bucket by using the
- Writing an inline Swagger in AWS SAM templates by using the
I often choose the second. Because if you use the
DefinitionUri property with your Swagger file, AWS SAM treats the file as just a Swagger file, therefore you can't use Intrinsic Functions and Pseudo Parameters in the file. Because there are no specification such features in Swagger. For example, you can't refer to
Ref parameters with the
Fn::Sub function in Swagger so that you need to write hard-coded AWS Lambda's ARN which specified as an integration request in your Swagger file. In this case, if you divide AWS accounts into multiple environments (production, staging and etc), you may need a bunch of Swagger files for each environment. This is confusing. For these reasons, I prefer the second way rather than the first one.
But, when you write an inline Swagger in AWS SAM templates directly, it'll be very difficult to manage it. Because Swagger and AWS SAM templates are mixed. This is also confusing. To prevent the problem, some developers have hacked the AWS::Include transform. The solution is introduced in AWS SAM's sample project, you might have heard about it.
It's very easy to use. You just need to specify the
Fn::Transform in the
DefinitionBody property like the following:
ApiGatewayApi: Type: AWS::Serverless::Api Properties: StageName: Sample DefinitionBody: Fn::Transform: Name: AWS::Include Parameters: Location: s3://<path-to-s3-bucket>/swagger.yml
If you create a stack by using the file above, the Swagger file specified in the
Location property is inserted into the template. In other words, you can divide Swagger files with AWS SAM templates.
Well, what's the matter?
Please look at the
Location property in the sample code again. Its value is an S3 path. That is, you need to upload a Swagger file to the S3 path before you create a stack with the template.
Generally, when using AWS SAM, you'll follow the steps below:
- By using
aws cloudformation packagecommand, you create a deployment package, upload it to an S3 bucket, and produce a transformed AWS SAM template
- Creating (or updating) a stack with
aws cloudformation deploycommand
If you followed these steps, you needed to upload a Swagger file to an S3 bucket by yourself. Of course, it's not hard to archive this. You can just use
aws s3 cp command. But I was hoping AWS CLI would do it on my behalf. I don't add extra steps (if it's possible) in my deployment pipeline.
But, recently, the upload feature is introduced in AWS CLI version 1.16.36 as the PR is merged. Yeah!
I gave it a shot.
I'll demonstrate the feature to you in this chapter. I tested it in the latest AWS CLI in this time (1.16.37).
$ aws --version aws-cli/1.16.37 Python/3.6.5 Darwin/17.7.0 botocore/1.12.27
First, I changed the
Location property like this:
ApiGatewayApi: Type: AWS::Serverless::Api Properties: StageName: Sample DefinitionBody: Fn::Transform: Name: AWS::Include Parameters: Location: src/api/swagger.yml
I just specify a local directory path to the
Location property. Then, hit the
aws cloudformation package command:
$ aws cloudformation package \ --template-file sam.yml \ --s3-bucket <path-to-s3-bucket> \ --output-template-file template.yml Uploading to 256b8dbcba1d8ad7f1d4dadda741722d 2371 / 2371.0 (100.00%) Successfully packaged artifacts and wrote output template to file template.yml. Execute the following command to deploy the packaged template aws cloudformation deploy --template-file /path/to/template.yml --stack-name <YOUR STACK NAME>
The command seems to be working as I expected. Let's look at the uploaded object in the S3 bucket.
$ aws s3 cp s3://<path-to-s3-bucket>/256b8dbcba1d8ad7f1d4dadda741722d - | md5 256b8dbcba1d8ad7f1d4dadda741722d $ md5 src/api/swagger.yml MD5 (src/api/swagger.yml) = 256b8dbcba1d8ad7f1d4dadda741722d
There are no difference between the files. Next, check the transformed AWS SAM template.
ApiGateway: Properties: DefinitionBody: Fn::Transform: Name: AWS::Include Parameters: Location: s3://<path-to-s3-bucket>/256b8dbcba1d8ad7f1d4dadda741722d StageName: Sample Type: AWS::Serverless::Api
The value is changed. Its value is an S3 path like the first sample snippet. Therefore, you can deploy it the same as before.
$ aws cloudformation deploy \ --template-file template.yml \ --stack-name <your-stack-name> Waiting for changeset to be created.. Waiting for stack create/update to complete Successfully created/updated stack - <your-stack-name>
In this post, a tiny update in AWS CLI is discussed. I think it can be useful in many situations. I hope you find this post helpful.