AWS Step Functions でワークフローを構築しているときに AWS Step Functions の実行時に渡すインプットの一部をファイルとして Amazon S3 に保存したいという場面があったりする❗️実際に最近あった \( 'ω')/
もちろん AWS Lambda 関数を追加すれば柔軟で自由度高くワークフローを拡張できるけど,比較的シンプルな処理であれば無理に AWS Lambda 関数を増やすのではなく,AWS Step Functions の「AWS SDK 統合」を活用する方が良かったりする.ちなみにシンプルな処理であれば AWS Lambda 関数は不要というベストプラクティスは「直接統合 (Direct Integrations)」という表現で AWS Well-Architected Framework Serverless Applications Lensに載っている👌
ワークフロー
今回は動作確認のために AWS SDK 統合 s3:PutObject
のみを設定する.
そして,アップロードする Amazon S3 バケットのオブジェクトキーは AWS Step Functions の実行名とインプットとして渡す name
を組み合わせるため,AWS Step Functions の組み込み関数 States.Format
と AWS Step Functions のコンテキストオブジェクト $$.Execution.Name
を設定する.
今回は AWS CDK でワークフローを実装した.
import{ Stack, StackProps, aws_s3, aws_stepfunctions, aws_stepfunctions_tasks, }from'aws-cdk-lib'import{ Construct }from'constructs'exportclass SandboxCdkStepfunctionsPutObjectStack extends Stack {constructor(scope:Construct, id:string, props?:StackProps) {super(scope, id, props) const bucket = new aws_s3.Bucket(this, 'Bucket', {bucketName: 'kakakakakku-sandbox-stepfunctions-put-object', }) const putObjectTask = new aws_stepfunctions_tasks.CallAwsService(this, 'PutObjectTask', {service: 's3', action: 'putObject', parameters: {'Bucket': bucket.bucketName, 'Key.$': `States.Format('{}/{}', $$.Execution.Name, $.name)`, 'Body.$': '$.body', 'ContentType': 'application/json', }, iamResources: ['*'], }) new aws_stepfunctions.StateMachine(this, 'SandboxCdkStepfunctions', {stateMachineName: 'sandbox-cdk-stepfunctions-put-object', definitionBody: aws_stepfunctions.DefinitionBody.fromChainable(putObjectTask), }) }}
最終的にデプロイされたワークフロー定義は以下👌
{"StartAt": "PutObjectTask", "States": {"PutObjectTask": {"End": true, "Type": "Task", "Resource": "arn:aws:states:::aws-sdk:s3:putObject", "Parameters": {"Bucket": "kakakakakku-sandbox-stepfunctions-put-object", "Key.$": "States.Format('{}/{}', $$.Execution.Name, $.name)", "Body.$": "$.body", "ContentType": "application/json" }}}}
動作確認
2種類のインプットを準備して,ワークフローを実行する❗️
{"name": "sandbox001.json", "body": {"title": "title001", "body": "body001" }}
{"name": "sandbox002.json", "body": {"title": "title002", "body": "body002" }}
すると,期待通りに Amazon S3 バケットにオブジェクトが追加されている👌
$ aws s3api list-objects --bucket kakakakakku-sandbox-stepfunctions-put-object | jq -r'.Contents[].Key' f32ea288-3103-4c8a-9b65-6c57298420f8/sandbox002.json f5f16907-279b-447a-9e1c-eddc44ea78e3/sandbox001.json
そして f5f16907-279b-447a-9e1c-eddc44ea78e3/sandbox001.json
を開くと,期待通りにインプットの body
に指定した JSON になっていた👌
{"title":"title001","body":"body001"}