🔁

Step FunctionsでNextTokenを返すAPIをループ処理する

2024/10/31に公開

AWS Step Functionsで、レスポンスアイテム数に上限があってNextToken/Maker/ContinuationToken等を返すList/Describe APIの結果を全部ループして処理する方法です。

Mapステートで1レスポンス内のリストをループ処理し、さらにそれをループするようなステートマシンを作成します。

参考

こちらをパク参考にしました。

https://dev.to/stevensmiley/handling-paginated-api-responses-in-aws-step-functions-1emf

サンプル

IAM ListRoles APIで、アカウントに存在するロールをすべてリストして処理するサンプルです。

このAPIは、MaxItemsを超えるロールがまだ存在するときMarker(NextToken)を返します。続いて、その値をリクエストに含めてAPIを実行することで、残りのロール一覧を取得できます。それでもすべてのロールを取得できていない場合は、さらに別のMarkerを返します。

CloudFormationテンプレート

AWSTemplateFormatVersion: 2010-09-09

Resources:
  StateMachineRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service: states.amazonaws.com
            Action: sts:AssumeRole
      Policies:
        - PolicyName: StepFunctionsPolicy
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action:
                  - iam:ListRoles
                Resource: '*'

  StateMachine:
    Type: AWS::StepFunctions::StateMachine
    Properties:
      StateMachineName: !Sub ${AWS::StackName}-StateMachine
      StateMachineType: STANDARD
      RoleArn: !GetAtt StateMachineRole.Arn
      DefinitionString: |
        {
          "Comment": "Sample state machine handling paginated API responses",
          "StartAt": "ListRoles",
          "States": {
            "ListRoles": {
              "Type": "Task",
              "Parameters": {
                "MaxItems": 30
              },
              "Resource": "arn:aws:states:::aws-sdk:iam:listRoles",
              "Next": "ForEachRole"
            },
            "ForEachRole": {
              "Type": "Map",
              "ItemsPath": "$.Roles",
              "MaxConcurrency": 1,
              "ItemProcessor": {
                "ProcessorConfig": {
                  "Mode": "INLINE"
                },
                "StartAt": "DoSomething",
                "States": {
                  "DoSomething": {
                    "Type": "Pass",
                    "End": true
                  }
                }
              },
              "ResultPath": null,
              "Next": "IfNextTokenExists"
            },
            "IfNextTokenExists": {
              "Type": "Choice",
              "Choices": [
                {
                  "Variable": "$.Marker",
                  "IsPresent": true,
                  "Next": "ListMoreRoles"
                }
              ],
              "Default": "Success"
            },
            "ListMoreRoles": {
              "Type": "Task",
              "Parameters": {
                "MaxItems": 30,
                "Marker.$": "$.Marker"
              },
              "Resource": "arn:aws:states:::aws-sdk:iam:listRoles",
              "Next": "ForEachRole"
            },
            "Success": {
              "Type": "Succeed"
            }
          }
        }

解説(一部)

Mapステートで結果を棄てる("ResultPath": null)ことで、ListRolesステートの結果をIfNextTokenExistsステートに渡しています。ResultPathの使い方はStep Functions ワークフローで ResultPath を使用して状態出力を指定するをご参照ください。

ステートマシンのプロパティにはDefinitionを使いたかったのですが、そうすると"ResultPath": nullがエラーになってしまったため、DefinitionStringを使用しています。

Discussion