AWS CLIがAWS::Include transformをS3へアップロードできるようになりました
はじめに
こんにちは、knakayamaです。
このポストでは、AWS CLIのバージョン1.16.36で導入された新機能をご紹介したいと思います。実際のところとても小さな機能追加です。ただし、私のように毎日の開発の中でAWS SAMを使っているなら、きっと少しだけ幸せにしてくれると思います。
Swagger in AWS SAM
もしAmazon API GatewayをプロビジョニングするためにAWS SAMでSwaggerを使っているなら、AWS::Serverless::Apiリソースを利用しているでしょう。このリソースの中でSwaggerファイルを指定する方法は2つあります。
DefinitionUri
プロパティを使ってS3バケット内のSwaggerファイルを指定するDefinitionBody
プロパティを使ってAWS SAMテンプレート内にインラインSwaggerを記述する
私はよく2つ目の方法を選びます。なぜなら、もし DefinitionUri
プロパティをSwaggerファイルと共に使った場合、AWS SAMはそのファイルを単なるSwaggerファイルとして扱ってしまうため、Intrinsic FunctionsやPseudo ParametersがSwaggerの中で使えなくなってしまうからです。そういった仕様はSwaggerの中にないからですね。例えば、Swaggerの中の Fn::Sub
関数で AWS::AccountId
や Ref
パラメータを参照できないため統合リクエストとして指定されたAWS LambdaのARNをハードコーディングする必要があります。この場合、もしAWSアカウントを複数の環境(本番、ステージング、その他)で分割していると、各環境毎にたくさんのSwaggerファイルが必要になるでしょう。面倒ですね。こういった理由から、1番目より2番目の方法が好ましいと思っています。
ただし、AWS SAMテンプレートにインラインSwaggerを直接記述した場合、その管理がとても難しくなるでしょう。なぜならSwaggerとAWS SAMテンプレートが混ざってしまうためです。これもまた面倒ですね。この問題を防ぐために、AWS::Include transformをうまいこと利用する開発者もいます。この解決方法はAWS SAMのsample projectでも紹介されているため、もしかすると聞いたことがあるかもしれません。
使い方はとても簡単です。以下のように DefinitionBody
プロパティで Fn::Transform
を指定する必要があるだけです。
ApiGatewayApi: Type: AWS::Serverless::Api Properties: StageName: Sample DefinitionBody: Fn::Transform: Name: AWS::Include Parameters: Location: s3:///swagger.yml
もし上記ファイルからスタックを作成した場合、 Location
プロパティで指定されたSwaggerファイルがテンプレート内に挿入されます。つまり、SwaggerファイルとAWS SAMテンプレートを分割できるということです。
で、何が問題なの?
サンプルコードの Location
プロパティをもう一度見てください。値がS3のパスになっています。つまり、テンプレートからスタックを作る前にそのS3パスへSwaggerファイルをアップロードする必要があるということです。
一般的に、AWS SAMを使う場合は以下のステップに倣うと思います。
aws cloudformation package
コマンドを使って、デプロイメントパッケージを作成し、それをS3バケットにアップロード、変換されたAWS SAMテンプレートを生成するaws cloudformation deploy
コマンドでスタックを作成/更新する
もしこのステップに従っている場合、自分でS3バケットにSwaggerファイルをアップロードする必要がありました。もちろんこれを実現するのは難しいことではありません。単に aws s3 cp
コマンドを使えばいいだけです。ただ、私はAWS CLIが代わりにやって欲しいなと思っていました。デプロイパイプラインに余計なステップを可能なら加えたくありません。
しかし、最近このPRがマージされたため、AWS CLIバージョン1.16.36でこのアップロード機能が導入されました。めでたい。
やってみた
この章ではこの機能をデモしてみます。執筆時点の最新AWS CLIバージョン(1.16.37)でテストしています。
$ aws --version aws-cli/1.16.37 Python/3.6.5 Darwin/17.7.0 botocore/1.12.27
最初に、 Location
プロパティを以下のように変更しました。
ApiGatewayApi: Type: AWS::Serverless::Api Properties: StageName: Sample DefinitionBody: Fn::Transform: Name: AWS::Include Parameters: Location: src/api/swagger.yml
Location
プロパティにローカルディレクトリへのパスを指定しただけです。続いて、 aws cloudformation package
コマンドを実行します。
$ aws cloudformation package \ --template-file sam.yml \ --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
予想したとおりに動いているようです。S3バケットにアップロードされたオブジェクトを見てみましょう。
$ aws s3 cp s3:///256b8dbcba1d8ad7f1d4dadda741722d - | md5 256b8dbcba1d8ad7f1d4dadda741722d $ md5 src/api/swagger.yml MD5 (src/api/swagger.yml) = 256b8dbcba1d8ad7f1d4dadda741722d
両ファイルに違いはありません。次は変換されたAWS SAMテンプレートを見てみます。
ApiGateway: Properties: DefinitionBody: Fn::Transform: Name: AWS::Include Parameters: Location: s3:///256b8dbcba1d8ad7f1d4dadda741722d StageName: Sample Type: AWS::Serverless::Api
値が変わってますね。値が最初のサンプルスニペットのようにS3へのパスになっています。したがって、以前と同じようにデプロイ可能です。
$ aws cloudformation deploy \ --template-file template.yml \ --stack-name Waiting for changeset to be created.. Waiting for stack create/update to complete Successfully created/updated stack -
まとめ
いかがだったでしょうか?
このポストでは、AWS CLIの小さなアップデートをご紹介しました。私は多くの状況で便利なのではないかと思っています。このポストがお役に立てれば幸いです。