AWS CDKでデプロイはせずにStepFunctionsのワークフロー定義(Amazon States Language)を生成

この記事はLOCAL Students Advent Calendar 2021の11日目の記事です。 adventar.org

AWS CDKを使えば、Step Functionsのワークフローをtypescriptなどのコードから生成してデプロイすることができます。 ここではデプロイはせずに、AWS CDKからStepFunctionsのワークフロー定義 (Amazon States Language) を生成してみます。

AWS CDKのテストコードを見てみる

AWS CDKはこちらのレポジトリで管理されています。 github.com

StepFunctionsの定義を行う@aws-cdk/aws-stepfunctionsパッケージのディレクトリを見てみると、ワークフロー定義の生成に関するテストがありました。やったね。

aws-cdk/states-language.test.ts at d9285cb75745028ede8c36afcee34f7a53d27993 · aws/aws-cdk · GitHub

chainはCDKでStepFunctionsを定義するときによくみるdefinitionですね。 render(chain)chainからワークフロー定義を生成しているようです。

 test('A single task is a State Machine', () => {
    // GIVEN
    const stack = new cdk.Stack();

    // WHEN
    const chain = new stepfunctions.Pass(stack, 'Some State');

    // THEN
    expect(render(chain)).toStrictEqual({
      StartAt: 'Some State',
      States: {
        'Some State': { Type: 'Pass', End: true },
      },
    });
  }),

render()は同じファイルで以下のように定義されています。

function render(sm: stepfunctions.IChainable) {
  return new cdk.Stack().resolve(new stepfunctions.StateGraph(sm.startState, 'Test Graph').toGraphJson());
}

これを使えばいけそうですね。

ワークフロー定義を生成

結局は以下のようなシンプルなtypescriptでワークフロー定義を生成できました。

import * as cdk from '@aws-cdk/core';
import * as sfn from '@aws-cdk/aws-stepfunctions';

function render(sm: sfn.IChainable) {
  return new cdk.Stack().resolve(new sfn.StateGraph(sm.startState, 'Graph').toGraphJson());
}

const stack = new cdk.Stack();
const definition = new sfn.Pass(stack, 'Pass State');

console.log(JSON.stringify(render(definition), null, '  '))
$ tsc app.ts 
$ node app.js
{
  "StartAt": "Pass State",
  "States": {
    "Pass State": {
      "Type": "Pass",
      "End": true
    }
  }
}

もう少し複雑なワークフロー定義も生成してみます。

import * as cdk from '@aws-cdk/core';
import * as sfn from '@aws-cdk/aws-stepfunctions';

function render(sm: sfn.IChainable) {
  return new cdk.Stack().resolve(new sfn.StateGraph(sm.startState, 'Graph').toGraphJson());
}

const stack = new cdk.Stack();
const pass = new sfn.Pass(stack, 'Pass State');
const succeed = new sfn.Succeed(stack, 'Succeed State');
const fail = new sfn.Fail(stack, 'Fail State');
const parallel = new sfn.Parallel(stack, 'Parallel State')
    .branch(succeed)
    .branch(fail);
const definition = pass.next(parallel);

console.log(JSON.stringify(render(definition), null, '  '))
$ tsc app.ts 
$ node app.js
{
  "StartAt": "Pass State",
  "States": {
    "Pass State": {
      "Type": "Pass",
      "Next": "Parallel State"
    },
    "Parallel State": {
      "Type": "Parallel",
      "End": true,
      "Branches": [
        {
          "StartAt": "Succeed State",
          "States": {
            "Succeed State": {
              "Type": "Succeed"
            }
          }
        },
        {
          "StartAt": "Fail State",
          "States": {
            "Fail State": {
              "Type": "Fail"
            }
          }
        }
      ]
    }
  }
}

AWS CDKからワークフロー定義を生成できました!

おわりに

デプロイするわけではなくAmazon States Languageのワークフロー定義を簡単にいくつか生成したい、というニッチな状況になり、こんなことをやってみました。 使えるものをなんでも使う精神でやっていきたいものです。