AWS CDKで作成したAWS Step Functions State MachineのASL定義をjqコマンドで取得する
こんにちは、CX事業本部 IoT事業部の若槻です。
AWS Step Functions Localを使いたい場合、テスト対象のState MachineのASL(Amazon States Language)定義を取得する必要があります。
そこで今回は、AWS CDKでAWS Step Functionsの開発を行っている場合に、State MachineのASL定義をjqコマンドで取得する方法を確認してみました。
結論
次のコマンドを実行すれば取得できます。
$ stackName=<stackName> $ stateMachineName=<stateMachineName> $ jq --arg stateMachineName "$stateMachineName" \ '.Resources[] | select(.Properties.StateMachineName == $stateMachineName)' \ cdk.out/${stackName}.template.json | \ jq -r .Properties.DefinitionString | jq .
やってみた
CDK SynthやCDK DeployによるBuildを行うと、StackのCloudFormation Templateがcdk.out/<stackName>.template.json
に作成されます。
例えば次のStackの場合。
import { Construct } from 'constructs'; import { aws_stepfunctions, Stack, StackProps } from 'aws-cdk-lib'; export class AwsAppStack extends Stack { constructor(scope: Construct, id: string, props: StackProps) { super(scope, id, props); // StateMachine1 new aws_stepfunctions.StateMachine(this, 'stateMachine1', { stateMachineName: 'stateMachine1', definition: new aws_stepfunctions.Pass(this, 'pass1'), }); // StateMachine2 new aws_stepfunctions.StateMachine(this, 'stateMachine2', { stateMachineName: 'stateMachine2', definition: new aws_stepfunctions.Map(this, 'Map State', { itemsPath: aws_stepfunctions.JsonPath.stringAt('$.inputForMap'), }).iterator(new aws_stepfunctions.Pass(this, 'pass2')), }); } }
次のようなTemplate Fileが生成されます。
{ "Resources": { "stateMachine1Role7BF1589E": { "Type": "AWS::IAM::Role", "Properties": { "AssumeRolePolicyDocument": { "Statement": [ { "Action": "sts:AssumeRole", "Effect": "Allow", "Principal": { "Service": "states.ap-northeast-1.amazonaws.com" } } ], "Version": "2012-10-17" } }, "Metadata": { "aws:cdk:path": "AwsAppStack/stateMachine1/Role/Resource" } }, "stateMachine174B105B6": { "Type": "AWS::StepFunctions::StateMachine", "Properties": { "RoleArn": { "Fn::GetAtt": [ "stateMachine1Role7BF1589E", "Arn" ] }, "DefinitionString": "{\"StartAt\":\"pass1\",\"States\":{\"pass1\":{\"Type\":\"Pass\",\"End\":true}}}", "StateMachineName": "stateMachine1" }, "DependsOn": [ "stateMachine1Role7BF1589E" ], "Metadata": { "aws:cdk:path": "AwsAppStack/stateMachine1/Resource" } }, "stateMachine2Role1C82D998": { "Type": "AWS::IAM::Role", "Properties": { "AssumeRolePolicyDocument": { "Statement": [ { "Action": "sts:AssumeRole", "Effect": "Allow", "Principal": { "Service": "states.ap-northeast-1.amazonaws.com" } } ], "Version": "2012-10-17" } }, "Metadata": { "aws:cdk:path": "AwsAppStack/stateMachine2/Role/Resource" } }, "stateMachine23B5C198F": { "Type": "AWS::StepFunctions::StateMachine", "Properties": { "RoleArn": { "Fn::GetAtt": [ "stateMachine2Role1C82D998", "Arn" ] }, "DefinitionString": "{\"StartAt\":\"Map State\",\"States\":{\"Map State\":{\"Type\":\"Map\",\"End\":true,\"Iterator\":{\"StartAt\":\"pass2\",\"States\":{\"pass2\":{\"Type\":\"Pass\",\"End\":true}}},\"ItemsPath\":\"$.inputForMap\"}}}", "StateMachineName": "stateMachine2" }, "DependsOn": [ "stateMachine2Role1C82D998" ], "Metadata": { "aws:cdk:path": "AwsAppStack/stateMachine2/Resource" } }, "CDKMetadata": { "Type": "AWS::CDK::Metadata", "Properties": { "Analytics": "v2:deflate64:H4sIAAAAAAAA/1WJzQrCMBCEn6X3ZLU9CJ49F6Q+gKzpFrc/m9JN9BDy7sZ6Ega+mfkaaM5QV/hW6/rJzvyAdAvoJlOue9JA6xDFBfaikK6oaooO1KJ7spC5DPK3W1yzYVwgdX7e9Zc5743Ux81RNuJ7glEPr/oEJcdqVGa7RQm8EHQ/fgC550rrmwAAAA==" }, "Metadata": { "aws:cdk:path": "AwsAppStack/CDKMetadata/Default" } } }, "Parameters": { "BootstrapVersion": { "Type": "AWS::SSM::Parameter::Value<String>", "Default": "/cdk-bootstrap/hnb659fds/version", "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" } }, "Rules": { "CheckBootstrapVersion": { "Assertions": [ { "Assert": { "Fn::Not": [ { "Fn::Contains": [ [ "1", "2", "3", "4", "5" ], { "Ref": "BootstrapVersion" } ] } ] }, "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." } ] } } }
このうちState MachineのASL定義はハイライト部分(DefinitionString)となります。そして、Templateにおける各Resourceは、Logical IDをKeyとしたオブジェクトとなり、その配下にStateMachineNameとDefinitionStringがあります。
よって、指定の名前のStateMachineのリソースのオブジェクトを取得したい場合は、jqコマンドを次のように実行します。
$ stackName=AwsAppStack $ stateMachineName=stateMachine1 $ jq --arg stateMachineName "$stateMachineName" \ '.Resources[] | select(.Properties.StateMachineName == $stateMachineName)' \ cdk.out/${stackName}.template.json { "Type": "AWS::StepFunctions::StateMachine", "Properties": { "RoleArn": { "Fn::GetAtt": [ "stateMachine1Role7BF1589E", "Arn" ] }, "DefinitionString": "{\"StartAt\":\"pass1\",\"States\":{\"pass1\":{\"Type\":\"Pass\",\"End\":true}}}", "StateMachineName": "stateMachine1" }, "DependsOn": [ "stateMachine1Role7BF1589E" ], "Metadata": { "aws:cdk:path": "AwsAppStack/stateMachine1/Resource" } }
さらにASLのみを抽出したい場合は、さらにjqコマンドへのパイプを行います。
$ stackName=AwsAppStack $ stateMachineName=stateMachine1 $ jq --arg stateMachineName "$stateMachineName" \ '.Resources[] | select(.Properties.StateMachineName == $stateMachineName)' \ cdk.out/${stackName}.template.json | \ jq -r .Properties.DefinitionString | jq . { "StartAt": "pass1", "States": { "pass1": { "Type": "Pass", "End": true } } }
もう一つのStateMachineのASLも同様に取得できます。
$ stackName=AwsAppStack $ stateMachineName=stateMachine2 $ jq --arg stateMachineName "$stateMachineName" \ '.Resources[] | select(.Properties.StateMachineName == $stateMachineName)' \ cdk.out/${stackName}.template.json | \ jq -r .Properties.DefinitionString | jq . { "StartAt": "Map State", "States": { "Map State": { "Type": "Map", "End": true, "Iterator": { "StartAt": "pass2", "States": { "pass2": { "Type": "Pass", "End": true } } }, "ItemsPath": "$.inputForMap" } } }
おわりに
AWS CDKで作成したAWS Step Functions State MachineのASL定義をjqコマンドで取得する方法を確認してみました。
AWS CLIのstepfunctions describe-state-machineコマンドを使ってもASLを取得できなくは無いのでしょうが、AWS CDKの開発環境であればローカルにBuildがされるのであれば、せっかくならそっちから取得してしまえということでjqを使ってみました。
以上