🌟
AWS SAMでStep Functionsワークフローを外部定義する
はじめに
AWS::StepFunctions::StateMachine
リソースを使用して、Step FunctionsのワークフローをSAMテンプレート内に直接インラインで記述していましたが、AWS::Serverless::StateMachine
リソースを用いて、SAMテンプレートの外でワークフローを定義するように変更しました。この変更に関する手順を本記事にまとめました。なお、テンプレートはAWSの公式ドキュメントを参考にしつつ、一部を変更しています。
対応前のテンプレート
tempalte.yaml
AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Description: "An example template with an IAM role for a Lambda state machine."
Resources:
LambdaExecutionRole:
Type: "AWS::IAM::Role"
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service: lambda.amazonaws.com
Action: "sts:AssumeRole"
MyLambdaFunction:
Type: "AWS::Lambda::Function"
Properties:
Handler: "index.handler"
Role: !GetAtt [ LambdaExecutionRole, Arn ]
Code:
ZipFile: |
exports.handler = (event, context, callback) => {
callback(null, "Hello World!");
};
Runtime: "nodejs18.x"
Timeout: "25"
StatesExecutionRole:
Type: "AWS::IAM::Role"
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Principal:
Service:
- !Sub states.${AWS::Region}.amazonaws.com
Action: "sts:AssumeRole"
Path: "/"
Policies:
- PolicyName: StatesExecutionPolicy
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- "lambda:InvokeFunction"
Resource: "*"
MyStateMachine:
Type: "AWS::StepFunctions::StateMachine"
Properties:
DefinitionString:
!Sub
- |-
{
"Comment": "A Hello World example using an AWS Lambda function",
"StartAt": "HelloWorld",
"States": {
"HelloWorld": {
"Type": "Task",
"Resource": "${lambdaArn}",
"End": true
}
}
}
- {lambdaArn: !GetAtt [ MyLambdaFunction, Arn ]}
RoleArn: !GetAtt [ StatesExecutionRole, Arn ]
対応後のテンプレート
tempalte.yaml
AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Description: "An example template with an IAM role for a Lambda state machine."
Resources:
LambdaExecutionRole:
Type: "AWS::IAM::Role"
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service: lambda.amazonaws.com
Action: "sts:AssumeRole"
MyLambdaFunction:
Type: "AWS::Lambda::Function"
Properties:
Handler: "index.handler"
Role: !GetAtt [ LambdaExecutionRole, Arn ]
Code:
ZipFile: |
exports.handler = (event, context, callback) => {
callback(null, "Hello World!");
};
Runtime: "nodejs18.x"
Timeout: "25"
StatesExecutionRole:
Type: "AWS::IAM::Role"
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Principal:
Service:
- !Sub states.${AWS::Region}.amazonaws.com
Action: "sts:AssumeRole"
Path: "/"
Policies:
- PolicyName: StatesExecutionPolicy
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- "lambda:InvokeFunction"
Resource: "*"
MyStateMachine:
Type: "AWS::Serverless::StateMachine"
Properties:
DefinitionUri: statemachine/helloWorld.asl.json
DefinitionSubstitutions:
lambdaArn: !GetAtt [MyLambdaFunction, Arn]
Role: !GetAtt [ StatesExecutionRole, Arn ]
具体的な対応内容
- リソースタイプを
AWS::StepFunctions::StateMachine
からAWS::Serverless::StateMachine
に変更しました。
(対応前)
MyStateMachine:
Type: "AWS::StepFunctions::StateMachine"
(対応後)
MyStateMachine:
Type: "AWS::Serverless::StateMachine"
- プロパティ
DefinitionString
を使用してワークフローをテンプレート内に直接インラインで記述していましたが、これをDefinitionUri
に変更し、ASLで記述されたファイルのS3のURIまたはローカルファイルパスを指定するように変更しました。なお、今回の変更ではローカルファイルパスを使用しました。
(対応前)
MyStateMachine:
Type: "AWS::StepFunctions::StateMachine"
Properties:
DefinitionString:
!Sub
- |-
{
"Comment": "A Hello World example using an AWS Lambda function",
"StartAt": "HelloWorld",
"States": {
"HelloWorld": {
"Type": "Task",
"Resource": "${lambdaArn}",
"End": true
}
}
}
(対応後)
MyStateMachine:
Type: "AWS::Serverless::StateMachine"
Properties:
DefinitionUri: statemachine/helloWorld.asl.json
ワークフローの定義内容
statemachine/helloWorld.asl.json
{
"Comment": "A Hello World example using an AWS Lambda function",
"StartAt": "HelloWorld",
"States": {
"HelloWorld": {
"Type": "Task",
"Resource": "${lambdaArn}",
"End": true
}
}
}
- 外部で定義されたワークフロー内のプレースホルダー変数に値を挿入するために、プロパティ
DefinitionSubstitutions
を使用して、文字列対文字列のマップ形式でマッピングを指定しています。
(対応前)
MyStateMachine:
Type: "AWS::StepFunctions::StateMachine"
Properties:
DefinitionString:
!Sub
- |-
{
<--省略-->
}
- {lambdaArn: !GetAtt [ MyLambdaFunction, Arn ]}
(対応後)
- プロパティ
RoleArn
をRole
に変更する。
(対応前)
MyStateMachine:
Type: "AWS::StepFunctions::StateMachine"
Properties:
<--省略-->
RoleArn: !GetAtt [ StatesExecutionRole, Arn ]
(対応後)
MyStateMachine:
Type: "AWS::Serverless::StateMachine"
Properties:
<--省略-->
Role: !GetAtt [ StatesExecutionRole, Arn ]
おわりに
リソースタイプの変更に伴い、プロパティの名称が変更される場合や互換性のないものがあるため、変更内容を確認するためには公式ドキュメントを参照する必要があります。また、sam deploy
を実行する際には、互換性のないプロパティが定義されている場合にはエラーが発生し、その詳細はエラーメッセージで確認できます。
Discussion