SAM テンプレートでいろんなツールを構成しているなかで、なんかプルリク投げることが多くなってきたので、serverless-application-model と aws-sam-cli のソースコードの構成や設計、依存関係について気になったところを自分向けにメモ
ただ OSS のコードリーディングメモなので、いかなるときも GitHub リポジトリの現在の状況が正しいので、正確性は実際にリポジトリを参考に確認してください
あと自分は Python を今年の 3月9日から書き始め、まだ数ヶ月しかたってないので実際 Python についてはよく知らないけどだいたい Pycharm がおしえてくれるのでそれを信じてる
リポジトリの構造メモ
SAM CLI と SAM の関係性
- awslabs/serverless-application-model の成果物は pip の aws-sam-translator としてリリースされるようだ
- awslabs/aws-sam-cli 側にて該当 pip パッケージへの依存は
requirements/base.txt
で定義されており、バージョンアップ時に bump する形 - したがって流れとしては SAM 側の変更がまず develop に取り込まれ aws-sam-translator のリリース待ち状態となり、これがリリースされると SAM CLI 側で該当のパッケージへの依存がアップデートされ、最終的にそちらのリリース待ちとなるようだ
- dev 版の SAM CLI である
samdev
はここに書いてある手順で導入可能なので、新機能をいち早く使いたければこれを用いる - また、まだリリースされてない aws-sam-translator の機能を使いたい場合は、ここに書いてある手順にしたがう
SAM is made up of two components: SAM translator and SAM CLI.
SAM translator is a CloudFormation transform managed by AWS. For fixes to the SAM translator (maintained in this GitHub repository), you do not need to install/upgrade any software to pick up the latest deployed changes.
SAM CLI is a client-side tool that you install on your local client. It is maintained in a separate GitHub repository, and you do have to update it to pick up new features/fixes. You can find more information on how to install SAM CLI here:
(SAM Creates stage named “Stage” by default? · Issue #191 · awslabs/serverless-application-model)
input/output test とは
- aws-sam-translator は基本的に YAML を変換するだけのソフトウェア
- このリポジトリは README に書いてあるとおり、たくさんのテストにより、ふるまいの破壊的な変更を防いでいる
- input/output test とはその名のとおり、input の YAML が最終的にどのような CloudFormation テンプレートに翻訳されるのかをテストするものになる
- tests/translator 下の input, output にそれぞれ元の YAML と変換後の JSON を突っ込む
- output については正常系は aws-us-gov, aws-cn, その他の 3 つのファイルを追加する必要がある点に注意
ソースコードリーディングメモ
論理 ID のランダム生成は logical_id_generator
が行なっている
- API Gateway のステージ名が
_
を含んでいるとエラーになる問題 があり、その修正 pull request が丁寧でとても参考になる - pull request の Author は、変更が破壊的にならないように
_
を含んでいないステージ名のリソースに関してはこれまでと論理 ID の生成ロジックを変更しないように工夫をしている - ところで論理 ID には
_
を含んではいけないので、それが含まれるものにはsamtranslator.translator.logical_id_generator
を用いてランダムな ID を生成するという形をとっている- この issue に着手しようとして、この部分に悩んでいるうちに pull request が出ていてなるほどなーとなったのでメモ
Lambda のイベントトリガーと EventSource モデル
- Lambda 関数をトリガーするイベントソースの簡易的な記法をサポートするためのモデル群
- push 型, pull 型に分類され、それぞれ
samtranslator/model/eventsources/{pull,push}.py
に記述されている- push 型は Lambda を Invoke するパーミッションを与える必要があるため
Lambda::Permission
リソースを作成する基底クラスを継承している - pull 型は Lambda に EventSourceMapping を設定する必要があるため
Lambda::EventSourceMapping
リソースを作成し、関数のロールに各イベントソースからデータを取得するためのポリシーを追加してあげるような基底クラスを継承している
- push 型は Lambda を Invoke するパーミッションを与える必要があるため
aws-sam-cli & sam-translator 一般のハナシ
deploy 時のアレコレ
--parameter-overrides
でパラメタ指定
sam deploy --template-file packaged.yaml --stack-name $StackName --capabilities CAPABILITY_NAMED_IAM --profile $AWSProfile \
--parameter-overrides \
"Param1=Value1"
sam logs コマンド
sam logs – AWS Serverless Application Model 参照
sam logs [-n FUNCTION_NAME] [--stack-name STACK_NAME]
開発時のメモ
transform 動作の確認
ローカルの sam transformer を使ってテンプレートを変換するときの手順(開発ガイドに載ってる)
aws cloudformation package --template-file MY_TEMPLATE_PATH --output-template-file output-template.yaml --s3-bucket MY_S3_BUCKET
bin/sam-translate.py --template-file=output-template.yaml
aws cloudformation deploy --template-file cfn-template.json --capabilities CAPABILITY_NAMED_IAM --stack-name MY_STACK_NAME
関わった変更メモ
WIP
Custom Statements の組み込み関数対応
issue: Can not use Fn::if within CustomStatements: · Issue #1218 · awslabs/serverless-application-model
- Looks like this code isn’t taking intrinsic functions into account
- 英語表現: “take A into account” 「A を考慮する」というの知らなかったのでちょっと迷った
組み込み関数の一覧はドキュメントに書いてある: 組み込み関数リファレンス
- Fn::Base64
- Fn::Cidr
- 条件関数
- Fn::And
- Fn::Equals
- Fn::If
- Fn::Not
- Fn::Or
- Fn::FindInMap
- Fn::GetAtt
- Fn::GetAZs
- Fn::ImportValue
- Fn::Join
- Fn::Select
- Fn::Split
- Fn::Sub
- Fn::Transform
- Ref
内容的には If だけ対応すればよさそう?(確認する)
2019 年 11 月の contributions
SNS-SQS-Lambda オプションに既存のキューを指定できるようにした
pull request: feat: Add an existing SQS queue option to SNS event by 53ningen · Pull Request #1231 · awslabs/serverless-application-model
落ちてたテストなおした
pull request: fix: failed tests by 53ningen · Pull Request #1234 · awslabs/serverless-application-model
ドキュメントの誤りを修正
pull request: chore(docs): fix a cognito event source example by 53ningen · Pull Request #1233 · awslabs/serverless-application-model
2019 年 10 月の contributions
DynamoDBDStreamReadPolicy の修正
根本的に ARN とリソースの指定間違ってたっぽいので直した
変更内容はいつもの… って感じだ
typo 修正
pull request: chore: typo in swagger.py by 53ningen · Pull Request #1220 · awslabs/serverless-application-model
- swagger.py に関連する Issue に取り組んだ時に見つけたので、クソリプっぽいけど出しておいた
2019 年 8 月の contributions
SNS -> SQS -> Lambda 連携オプションの実装
pull request: feat: Add SQS option to SNS event by 53ningen · Pull Request #1065 · awslabs/serverless-application-model
- 個人的にとても欲しかった機能で issue が立っていたので自分で実装した
- SNS -> SQS -> Lambda の連携をサクッと行える変更を作成したが、SNS -> Lambda は push 型なのに対し、SNS -> SQS -> Lambda は Lambda のイベントソース的には pull 型にあたるため
push.py
内でpull.py
を import する必要があった - あるシンタックスに対して新規にリソースを生成する場合は
docs/internal
を更新する必要がある旨を指摘してもらった
ところで issue には SqsSubscription に object を突っ込めるようになっており、既存のキューなどを指定できるようになっている。この場合 SQS のポリシーで QueueUrl と QueueARN が必要なのだが、このあたりをどうすべきか悩んでしまったので一旦 boolean で受け付ける機能を pull request して、その後 issue で議論しようという方針に決めた(そのほうが差分が小さくなるし、大多数のひとは中間のキューを管理したくはないハズ)。
ApplicationId の null チェック漏れ修正
pull request: fix: make sure ApplicationId is not null by 53ningen · Pull Request #1062 · awslabs/serverless-application-model
- 簡単そうにみえて、なんか
serverless_app_plugin.py
は raise した例外の扱いが一般的なリソースと違うっぽい?- ちょっとこのあたり確認が必要そう
sam init で生成される Java のプロジェクトのメモリを明示的に指定
pull request: fix: Use explicit memory settings for Java cookie cutters by 53ningen · Pull Request #1340 · awslabs/aws-sam-cli
- aws-sam-cli 側への最初の pull request
- この作業によりテンプレートファイルのありかとこのリポジトリへの pull request の作法がわかりました
samcli/local/init/templates/
に各種テンプレがあります
SSMParameterReadPolicy に ssm:GetParametersByPath の許可を追加
- 単純なポリシーテンプレートの機能追加
2019 年 7 月の contributions
Lambda の SNS トリガーのソースとして異なるリージョンのトピックを指定できる機能を追加
- Lambda のイベントソースに関するオブジェクトは基本的に
samtranslator/model/eventsources/
にある - とくに SNS からの通知はプッシュイベントなので、
push.py
に定義されている - あとは、該当の Property を増やして、生成される CloudFormation テンプレートの内容に反映されるようにコードを書き換えるだけで機能追加は終了
- あとは良き感じにテストとドキュメントを更新
RekognitionFacesPolicy の不要なパラメータの除外
- ポリシーテンプレートの変更の仕組みは良き感じに JSON で定義できるようになっている
samtranslator/policy_templates_data/policy_templates.json
が変換の定義を行う JSON ファイル
- この手の変更は基本的には、前述の JSON の変更と input/output テストだけで良さそう
Lambda 関数のパスパラメータに対するパーミッション設定のバグを修正
- API Gateway のパスパラメータに対するパーミッションの設定がおかしい(けどなんか動いちゃってるやつ)を修正した
- 修正はめっちゃ単純でプロキシパスを replace しているところを、プロキシパス or パスパラメータを表現する正規表現でマッチしてリプレイスするようにしただけなので、あんまり面白くない
SimpleTable の PrimaryKey に Name or Type が指定されてないときの例外処理が抜けてる件について
- なおした
- 単純に to_cloudformation 内の該当箇所にて null チェック的なことして、アレだったら InvalidResourceException を投げるように追記しただけ
api_cognito_auth のサンプルが us-east-1 以外でちゃんと動かない件について
- package.json にスタック名とリージョンがハードコードされてた
- コミットメッセージ思いっきり間違っててスマンって感じだ
- cord ってなんだよ 紐かよ
- develop に取り込むタイミングでメンテナが正しい英語に直してくれました、世界平和 🌍
docstring がコピペだったので修正
pull reuqest: nits: docstring of PushEventReource classes may be incorrect · Issue #1017 · awslabs/serverless-application-model
- クソリプ的 pull request だけでみつけちゃったので一応なげといた