AWS SAM,如何从 api 网关调用 运行 状态机?

AWS SAM, how to run a state machine from an api gateway call?

我正在尝试为工作流设置状态机,但我似乎无法让它正常工作,这是我的 SAM 模板:

AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Description: >
  strest

  Sample SAM Template for strest

Globals:
  Function:
    Timeout: 3

Resources:
  PublicApi:
    Type: AWS::Serverless::Api
    Properties:
      StageName: Prod
      # TracingEnabled: true
      DefinitionBody:
        swagger: "2.0"
        info:
          version: "1.1"
          title: "StrestApi"
        schemes:
          - "http"
        paths:
          /start: # api gateway invokes lambda synchronously, which in turn invokes the stepfunction and waits for its final result
            get:
              produces:
                - "application/json"
              responses:
                "200":
                  description: "200 response"
                  schema:
                    $ref: "#/definitions/Empty"
                  headers:
                    Access-Control-Allow-Headers:
                    type: "string"

              security: []
              x-amazon-apigateway-integration:
                responses:
                  default:
                    statusCode: "200"
                    headers:
                      Access-Control-Allow-Headers:
                      type: "'*'"
                httpMethod: GET
                type: aws_proxy
                uri:
                  Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${StartFunction.Arn}/invocations

        definitions:
          Empty:
            type: "object"
            title: "Empty Schema"

  # Role which allows step functions to invoke lambda functions
  StatesExecutionRole:
    Type: "AWS::IAM::Role"
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: "Allow"
            Principal:
              Service:
                - !Sub states.${AWS::Region}.amazonaws.com
            Action: "sts:AssumeRole"
      Path: "/"
      Policies:
        - PolicyName: StatesExecutionPolicy
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Action:
                  - "lambda:InvokeFunction"
                Resource: "*"

  # LAMBDAS
  StartFunction:
    Type: AWS::Serverless::Function
    Properties:
      Description: Starts the state machine
      CodeUri: dist/
      Handler: start/start.handler
      Runtime: nodejs12.x
      Environment:
        Variables:
          STEP_FUNCTION_ARN: !Ref StepFunctionsStateMachine
      Policies:
        - Version: "2012-10-17"
          Statement:
            - Effect: "Allow" # step function permissions open for now
              Action:
                - states:*
              Resource: "*"
      Events:
        ExecSFNResource:
          Type: Api
          Properties:
            RestApiId: !Ref PublicApi
            Path: /start
            Method: GET

  ExecutorFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: dist/
      Handler: executor/executor.handler
      Runtime: nodejs12.x
      # Events:
      #   HelloWorld:
      #     Type: Api
      #     Properties:
      #       Path: /execute
      #       Method: get

  # State machine
  StepFunctionsStateMachine:
    Type: AWS::StepFunctions::StateMachine
    Properties:
      RoleArn: !GetAtt [StatesExecutionRole, Arn]
      DefinitionString: !Sub |-
        {
          "StartAt": "execute",
          "Comment": "State machine for executing the strest main loop",
          "States": {
            "execute": {
              "Type": "Task",
              "Resource": "${ExecutorFunction.Arn}",
              "Comment": "Run the Executor Lambda function",
              "End": true
            }
          }
        }

我通过 sam local start-apisam local start-lambda 启动服务。

  1. 使用这些命令启动 api 有什么不同吗?
  2. 在我粘贴的模板中,我使用 !Ref 获取状态机 ARN,但这不起作用,返回相同的字符串,如果我将其更改为 !GetAtt StepFunctionsStateMachine.Arn
  3. 更改 2. 然后我查询 /start 端点,启动 lambda 函数启动 运行,我得到状态机的 arn,但是当我尝试启动它时,我得到一个Service not valid in this context: lambda 错误(在标记 2 之后),这里是启动函数的代码:
import AWS from "aws-sdk";

export async function handler(event: any, context: any) {
  let stepFunctionArn = process.env.STEP_FUNCTION_ARN;

  console.log("marker0 stepFunctionArn", stepFunctionArn);

  let params = {
    stateMachineArn: stepFunctionArn!,
    name: "Execution lambda " + new Date().toString()
  };
  console.log("marker 1");

  let sf_client = new AWS.StepFunctions();
  console.log("marker 2");

  let res = await sf_client.startExecution(params).promise();

  console.log("marker 3", res);

  return {};
}

从 Lambda 函数启动步进函数是可行的,但我认为在您的情况下,使用 API 网关的 DefinitionBody 直接从 Api 网关启动它是更好的解决方案,例如这个:

  /workflow:
    post:
      x-amazon-apigateway-integration:
        credentials:
          Fn::GetAtt: [ ApiGatewayStepFunctionsRole, Arn ]
        uri:
          Fn::Sub: arn:aws:apigateway:${AWS::Region}:states:action/StartExecution
        httpMethod: POST
        type: aws
        responses:
          default:
            statusCode: 200
            responseTemplates:
              application/json: |
                '{ "executionId": "$input.json('executionArn').split(':').get(7) }'
        requestTemplates:
          application/json:
            Fn::Sub: |-
              {
                "input": "$util.escapeJavaScript($input.json('$'))",
                "name": "$context.requestId",
                "stateMachineArn": "${Workflow}"
              }
      summary: Start workflow instance
      responses:
        200:
          $ref: '#/components/responses/200Execution'
        403:
          $ref: '#/components/responses/Error'

我在 https://github.com/jvillane/aws-sam-step-functions-lambda/blob/master/openapi.yaml 中的 github 中提交了一个工作示例,其中包含用于检查执行状态的附加方法。