はじめに
AWS SAMにて、AWS CloudFormation Language Extensionsがサポートされるようになったとのことです。
試しに、Lambdaを複数作ってみました。
概要
- SAM CLI v1.16移行で利用可能
- 有効化するには、Transformセクションへの定義と、実行時にコマンドライン引数等での宣言が必要
- やってみた内容は以下
- ループしてLambdaを3つ作成
- イテレータで記載内容を変更
- 引数を利用
- 一つのループの中で、2つのリソースを作成
参考
やってみた
今回はCloudShell上で行います。
SAM CLI バージョン確認
SAM CLI v1.16未満の場合はバージョンを上げます。
~ $ sam --version
SAM CLI, version 1.156.0
~ $ pip install --upgrade aws-sam-cli
~ $ sam --version
SAM CLI, version 1.161.1
CloudShellの場合、再接続するたびにバージョンが元に戻ります。都度バージョンを挙げてください。
サンプル1:Lambda関数3つを作成
以前の記事を参考にします。
フォルダ構造は以下となります。
sample-sam
│ template.yaml
│
└─function
function.py
requirements.txt
3つのファイルは以下になります。
def lambda_handler(event, context):
print('sample function')
return {
'statusCode': 200,
'body': 'Hello from Lambda!'
}
function/requirements.txtは0バイトです。
テンプレートでFn::ForEachを使って、3つのLambda関数を作成します。
AWSTemplateFormatVersion: 2010-09-09
Transform:
- AWS::LanguageExtensions
- AWS::Serverless-2016-10-31
Resources:
FunctionRole:
Type: AWS::IAM::Role
Properties:
RoleName: "for-lambdafunction-loopsamtest"
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action:
- 'sts:AssumeRole'
Path: '/service-role/'
ManagedPolicyArns:
- 'arn:aws:iam::aws:policy/AWSLambdaExecute'
Fn::ForEach::Functions:
- Name
- [Prod, Test, Dev]
- ${Name}Func:
Type: AWS::Serverless::Function
Properties:
Role: !GetAtt FunctionRole.Arn
CodeUri: function/
Handler: function.lambda_handler
Runtime: python3.13
実行コマンドは以下になります。今回はコマンドにフラグ--language-extensionsを付与します。
sam build --language-extensions
sam validate --language-extensions
sam deploy --guided --language-extensions --capabilities CAPABILITY_NAMED_IAM
以下のような関数が作られました。
sample-sam $ aws lambda list-functions --query "Functions[?contains(FunctionName, 'sam-app-')].[FunctionName, Runtime]" --output table
-------------------------------------------------
| ListFunctions |
+--------------------------------+--------------+
| sam-app-DevFunc-EFeQuMQFSEsK | python3.13 |
| sam-app-ProdFunc-blxPm8SQ5bej | python3.13 |
| sam-app-TestFunc-5x8M47kYlATi | python3.13 |
+--------------------------------+--------------+
消すにはsam deleteになります。
サンプル2:CodeUriをループ
CodeUriにイテレータをいれ、環境ごとにコードを分けてみます。それに合わせてディレクトリ構造も変えます。
sample-sam
│ template.yaml
│
└─function
│ function.py
│ requirements.txt
│
├─dev
│ function.py
│ requirements.txt
│
├─prod
│ function.py
│ requirements.txt
│
└─test
function.py
requirements.txt
AWSTemplateFormatVersion: 2010-09-09
Transform:
- AWS::LanguageExtensions
- AWS::Serverless-2016-10-31
Resources:
FunctionRole:
Type: AWS::IAM::Role
Properties:
RoleName: "for-lambdafunction-loopsamtest"
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action:
- 'sts:AssumeRole'
Path: '/service-role/'
ManagedPolicyArns:
- 'arn:aws:iam::aws:policy/AWSLambdaExecute'
Fn::ForEach::Functions:
- Stage
- [Prod, Test, Dev]
- ${Stage}Func:
Type: AWS::Serverless::Function
Properties:
Role: !GetAtt FunctionRole.Arn
CodeUri: ./function/${Stage}
Handler: function.lambda_handler
Runtime: python3.13
サンプル3:引数を使う
カンマ区切りの文字列を指定して、ループを指定してみます。合わせて関数名を定義し、Outputセクションを加えてみます。
AWSTemplateFormatVersion: 2010-09-09
Transform:
- AWS::LanguageExtensions
- AWS::Serverless-2016-10-31
Parameters:
StageNames:
Type: CommaDelimitedList
Default: "Prod, Test, Dev"
Resources:
FunctionRole:
Type: AWS::IAM::Role
Properties:
RoleName: "for-lambdafunction-loopsamtest"
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action:
- 'sts:AssumeRole'
Path: '/service-role/'
ManagedPolicyArns:
- 'arn:aws:iam::aws:policy/AWSLambdaExecute'
Fn::ForEach::Functions:
- Stage
- !Ref StageNames
- ${Stage}Func:
Type: AWS::Serverless::Function
Properties:
FunctionName: !Sub Sample-${Stage}
Role: !GetAtt FunctionRole.Arn
CodeUri: ./function/${Stage}
Handler: function.lambda_handler
Runtime: python3.13
Outputs:
Fn::ForEach::FunctionArns:
- Stage
- !Ref StageNames
- ${Stage}FunctionArn:
Value: !GetAtt
- !Sub "${Stage}Func"
- Arn
結果が想定通りになっていることを確認します。
sample-sam $ aws lambda list-functions --query "Functions[?contains(FunctionName, 'Sample-')].[FunctionName, Runtime]" --output table
-------------------------------
| ListFunctions |
+--------------+--------------+
| Sample-Test | python3.13 |
| Sample-Dev | python3.13 |
| Sample-Prod | python3.13 |
+--------------+--------------+
sample-sam $ aws cloudformation describe-stacks --stack-name sam-app --query "Stacks[0].Outputs[*].[OutputKey, OutputValue, Description]" --output table
------------------------------------------------------------------------------------------------
| DescribeStacks |
+-----------------+-------------------------------------------------------------------+--------+
| DevFunctionArn | arn:aws:lambda:ap-northeast-1:123456789012:function:Sample-Dev | None |
| ProdFunctionArn| arn:aws:lambda:ap-northeast-1:123456789012:function:Sample-Prod | None |
| TestFunctionArn| arn:aws:lambda:ap-northeast-1:123456789012:function:Sample-Test | None |
+-----------------+-------------------------------------------------------------------+--------+
サンプル4:ループの中でロググループも作成
いつもLambda関数を作成する際はロググループも作成していますので、同じループの中でロググループも作成してみます。
AWSTemplateFormatVersion: 2010-09-09
Transform:
- AWS::LanguageExtensions
- AWS::Serverless-2016-10-31
Parameters:
StageNames:
Type: CommaDelimitedList
Default: "Prod, Test, Dev"
Resources:
FunctionRole:
Type: AWS::IAM::Role
Properties:
RoleName: "for-lambdafunction-loopsamtest"
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action:
- 'sts:AssumeRole'
Path: '/service-role/'
ManagedPolicyArns:
- 'arn:aws:iam::aws:policy/AWSLambdaExecute'
Fn::ForEach::Functions:
- Stage
- !Ref StageNames
- ${Stage}Func:
Type: AWS::Serverless::Function
Properties:
FunctionName: !Sub Sample-${Stage}
Role: !GetAtt FunctionRole.Arn
CodeUri: ./function/${Stage}
Handler: function.lambda_handler
Runtime: python3.13
${Stage}FuncLogGroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: !Sub /aws/lambda/Sample-${Stage}
RetentionInDays: 3653
Outputs:
Fn::ForEach::FunctionArns:
- Stage
- !Ref StageNames
- ${Stage}FunctionArn:
Value: !GetAtt
- !Sub "${Stage}Func"
- Arn
作成されていることを確認してみます。
sample-sam $ aws logs describe-log-groups --log-group-name-prefix "/aws/lambda/Sample" --query "logGroups[*].[logGroupName]" --output table
-----------------------------
| DescribeLogGroups |
+---------------------------+
| /aws/lambda/Sample-Dev |
| /aws/lambda/Sample-Prod |
| /aws/lambda/Sample-Test |
+---------------------------+
おわりに
今回はAWS SAMで使えるようになったCFnの拡張機能を試してみました。
SAMはLambda関数を作るのに便利なので、この機能が使えるようになり、さらに利便性が向上したと感じました。
この記事がどなたかのお役に立てれば幸いです。