AWS Step Functions の YAML ツールサポートを SAM で試す

## はじめに
2021/3/4 一部のツールで AWS Step Functions のステートマシン定義に YAML を使用できるようになりました🎉

https://aws.amazon.com/jp/about-aws/whats-new/2021/03/aws-step-functions-adds-tooling-support-for-yaml/

一部のツール という点に注意いただきたいのですが、現時点で YAML による定義を使用可能なのは
AWS Toolkit for Visual Studio Code と AWS CloudFormation (AWS SAM を含む) のみとなっています。
例えばマネジメントコンソールをの場合は引き続き JSON 形式を使用する必要があり、
Step Functions として完全に YAML をサポートしたということではないようです。

**Definition format support**
https://docs.aws.amazon.com/step-functions/latest/dg/development-options.html#development-options-format

以前投稿した以下の記事のステートマシン定義を YAML に書き換えて動作を確認しました。

https://qiita.com/hayao_k/items/c69b0f0a33f1b07498bb

## やってみる
### 作業前提
AWS SAM CLI のバージョンは v1.20.0 を使用しました。

```shell-session
$ sam --version
SAM CLI, version 1.20.0
```

ステートマシンの定義ファイル とSAM テンプレートを sam-app ディレクトリ配下に作成していきます。

```
sam-app
├── putitem.asl.yaml
└── template.yaml
```

### ステートマシンの定義
YAML で書いていきます。DynamoDB とのサービス統合を使用します。
Input で受け取った内容をそのままテーブルに保存するステートマシンです。
Resource と TableName をプレースホルダ変数としています。

```putitem.asl.yaml
# コメント行は無視される
StartAt: PutDynamoDB
States:
  PutDynamoDB:
    Type: Task
    Resource: "${DDBPutItem}"
    Parameters:
      TableName: "${DDBTable}"
      Item:
        id:
          S.$: "$.id"
        message:
          S.$: "$.message"
    End: true

```

YAML のコメント行は作成されるリソースの定義に引き継がれないことに注意してください。
必要な場合は JSON 利用時と同様、ステートマシン内で定義可能な Comment プロパティを使用します。

### SAM テンプレート

DefinitionUri プロパティで先ほど作成したステートマシンの定義ファイルを指定します。
DefinitionSubstitutions プロパティを使用することで、デプロイ時に取得した値を
先ほどのステートマシン定義に注入しています。

またステートマシンを実行するための API Gateway および受け取ったデータを保存するための
DynamoDB テーブルも合わせて定義しています。

```template.yaml
AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Description: >
  sam-app
  Sample SAM Template for Step Functions

Resources:
  PutDynamoDBStateMachine:
    Type: AWS::Serverless::StateMachine
    Properties:
      DefinitionUri: putitem.asl.yaml
      DefinitionSubstitutions:
        DDBPutItem: !Sub arn:${AWS::Partition}:states:::dynamodb:putItem
        DDBTable: !Ref Table
      Events:
        HttpRequest:
          Type: Api
          Properties:
            Method: POST
            Path: /request
      Policies:
        - DynamoDBWritePolicy:
            TableName: !Ref Table

  Table:
    Type: AWS::Serverless::SimpleTable
    Properties:
      PrimaryKey:
        Name: id
        Type: String
      ProvisionedThroughput:
        ReadCapacityUnits: 1
        WriteCapacityUnits: 1
```

ステートマシン定義は Definition プロパティで SAM テンプレート内にインラインで定義することもできます。

<details><summary>インラインでの定義例 (クリックで展開します)</summary><div>

```template.yaml
AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Description: >
  sam-app
  Sample SAM Template for Step Functions

Resources:
  PutDynamoDBStateMachine:
    Type: AWS::Serverless::StateMachine
    Properties:
      Definition:
        StartAt: PutDynamoDB
        States:
          PutDynamoDB:
            Type: Task
            Resource: "${DDBPutItem}"
            Parameters:
              TableName: "${DDBTable}"
              Item:
                id:
                  S.$: "$.id"
                message:
                  S.$: "$.message"
            End: true
      DefinitionSubstitutions:
        DDBPutItem: !Sub arn:${AWS::Partition}:states:::dynamodb:putItem
        DDBTable: !Ref Table
      Events:
        HttpRequest:
          Type: Api
          Properties:
            Method: POST
            Path: /request
      Policies:
        - DynamoDBWritePolicy:
            TableName: !Ref Table

  Table:
    Type: AWS::Serverless::SimpleTable
    Properties:
      PrimaryKey:
        Name: id
        Type: String
      ProvisionedThroughput:
        ReadCapacityUnits: 1
        WriteCapacityUnits: 1
```

</div></details>

### デプロイ
sam deploy コマンドを実行します。

```shell-session
$ cd sap-app
$ sam deploy --guided
```

変更セットを確認してデプロイします。
問題なく YAML のステートマシン定義が読み込めているようです！

```shell-session
CloudFormation stack changeset
-------------------------------------------------------------------------------------------------
Operation                LogicalResourceId        ResourceType             Replacement
-------------------------------------------------------------------------------------------------
+ Add                    PutDynamoDBStateMachin   AWS::IAM::Role           N/A
                         eHttpRequestRole
+ Add                    PutDynamoDBStateMachin   AWS::IAM::Role           N/A
                         eRole
+ Add                    PutDynamoDBStateMachin   AWS::StepFunctions::St   N/A
                         e                        ateMachine
+ Add                    ServerlessRestApiDeplo   AWS::ApiGateway::Deplo   N/A
                         ymenta4c0d5c32b          yment
+ Add                    ServerlessRestApiProdS   AWS::ApiGateway::Stage   N/A
                         tage
+ Add                    ServerlessRestApi        AWS::ApiGateway::RestA   N/A
                                                  pi
+ Add                    Table                    AWS::DynamoDB::Table     N/A
-------------------------------------------------------------------------------------------------
```

デプロイ完了後、API Gateway に Post し、ステートマシンを実行できることも確認できました。

```
$ curl -X POST -d '{"input": "{\"id\": \"1\",\"message\": \"Hello YAML!\"}","name": "FromAPI","stateMachineArn": "arn:aws:states:ap-northeast-1:123456789012:stateMachine:PutDynamoDBStateMachine-xxxxxxxxxxxx"}' https://yyyyyyyyyy.execute-api.ap-northeast-1.amazonaws.com/Prod/request
{"executionArn":"arn:aws:states:ap-northeast-1:123456789012:execution:PutDynamoDBStateMachine-xxxxxxxxxxxx:FromAPI","startDate":1.615220845994E9}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125105/0801d61d-e793-f419-e179-30050ca6abb4.png)


以上です。
参考になれば幸いです。