AWS CDKで既存のASLファイルを使ってStep Functionsをデプロイする

2022.10.04

「AWS CDKで既存のASLファイルを使ってStepFunctionsをデプロイしたい」

「既存のASLファイルを活かしつつAWS CDKでStep Functionsをデプロイしたいけど、L2 ConstructのStateMachineではファイルを渡せなさそう。」

ということがあり、少し調べたのでブログにします。

結論: L1 Construct(CfnStateMachine)を使えばできる。

// 結論部分の抜き出し
// コード全文はブログ中にあります
    const file = fs.readFileSync('./step-functions/HelloWorld.asl.json')
    new stepfunctions.CfnStateMachine(this, 'HelloWorldStateMachine', {
      definitionString: file.toString(),
      stateMachineName: 'HelloWorld-CDK',
      roleArn: role.roleArn
    })

やってみた

今回は以下のワークフローをJSONでエクスポートして、エクスポートしたファイルをCDKで使ってデプロイします。

Workflow StudioでASLファイルをJSONでエクスポート

まずはASLファイルをJSONでエクスポートします。

以下のファイルをダウンロードできました。

HelloWorld.asl.json

{
  "Comment": "A Hello World example of the Amazon States Language using Pass states",
  "StartAt": "Hello",
  "States": {
    "Hello": {
      "Type": "Pass",
      "Next": "World"
    },
    "World": {
      "Type": "Pass",
      "Result": "World",
      "End": true
    }
  }
}

CDKを書いてデプロイ

ディレクトリ構成は以下です。 ダウンロードしたjsonファイルは、step-functionsディレクトリを作ってその下に置きました。

ディレクトリ構成

├── README.md
├── bin
│   └── index.ts
├── cdk.json
├── cdk.out
│   └── 省略...
├── jest.config.js
├── lib
│   └── StepFunctionStack.ts
├── node_modules
│   └── 省略...
├── package-lock.json
├── package.json
├── step-functions
│   └── HelloWorld.asl.json # ダウンロードしたjsonファイル
├── test
│   └── cdk-stepfunctions-asl.test.ts
└── tsconfig.json

bin/index.ts

#!/usr/bin/env node
import 'source-map-support/register';
import * as cdk from 'aws-cdk-lib';
import { StepfunctionsStack } from '../lib/StepFunctionsStack';

const app = new cdk.App();
new StepfunctionsStack(app, 'StepfunctionsStack', {});

lib/StepFunctionsStack.ts

import * as cdk from 'aws-cdk-lib'
import * as iam from 'aws-cdk-lib/aws-iam'
import * as stepfunctions from 'aws-cdk-lib/aws-stepfunctions'
import * as fs from 'fs'
import { Construct } from 'constructs'

export class StepfunctionsStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props)

    const file = fs.readFileSync('./step-functions/HelloWorld.asl.json')

    //  ステートマシン作成にIAM Role必須のため、今回の検証ではポリシーは不要
    const role = new iam.Role(this, "StepFunctionsRole", {
      assumedBy: new iam.ServicePrincipal('states.amazonaws.com')
    })

    new stepfunctions.CfnStateMachine(this, 'HelloWorldStateMachine', {
      definitionString: file.toString(),
      stateMachineName: 'HelloWorld-CDK',
      roleArn: role.roleArn
    })
  }
}

コード用意したらCDKデプロイします。

npm run cdk deploy

マネジメントコンソールから、指定したJSONファイルの内容のステートマシンが作成できたことを確認できました。

おまけ: Escape Hatch

L2 Constructを使いつつ、JSONファイルを渡したいパターンもあるかと思います。

そういった場合は、以下のように書くことで実現できます。

CDKのドキュメントで言うところのEscape Hatchです。

lib/StepFunctionsStack

import * as cdk from 'aws-cdk-lib'
import * as iam from 'aws-cdk-lib/aws-iam'
import * as stepfunctions from 'aws-cdk-lib/aws-stepfunctions'
import * as fs from 'fs'
import { Construct } from 'constructs'

export class StepfunctionsStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props)

    const file = fs.readFileSync('./step-functions/HelloWorld.asl.json')

    //  ステートマシン作成にIAM Role必須のため、今回の検証ではポリシーは不要
    const role = new iam.Role(this, "StepFunctionsRole", {
      assumedBy: new iam.ServicePrincipal('states.amazonaws.com')
    })

    // new stepfunctions.CfnStateMachine(this, 'HelloWorldStateMachine', {
    //   definitionString: file.toString(),
    //   stateMachineName: 'HelloWorld-CDK',
    //   roleArn: role.roleArn
    // })

    // Escape Hatch
    const statemachine = new stepfunctions.StateMachine(this, "HelloWorldMachineL2Construct", {
      definition: new stepfunctions.Pass(this, 'StartState'),
      role,
      stateMachineName: "HelloWorld-CDK-L2"
    });
    const cfnStatemachine = statemachine.node.defaultChild as stepfunctions.CfnStateMachine;

    cfnStatemachine.definitionString = file.toString();
  }
}

おわりに

Step Functionsで既存のASLファイルを使って、CDKでデプロイする方法でした。

L1 Constructの使用やEscape Hatchは似たような問題の時にも役に立つと思います。

このブログが誰かの参考になったら幸いです。

以上、AWS事業本部の佐藤(@chari7311)でした。

参考