こんにちは、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の場合。
lib/aws-app-stack.ts
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が生成されます。
cdk.out/AwsAppStack.template.json
{
"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コマンドを次のように実行します。
stateMachine1のオブジェクトを取得
$ 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コマンドへのパイプを行います。
stateMachine1のASLを取得
$ 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も同様に取得できます。
stateMachine2の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を使ってみました。
以上