【问题标题】:AWS SAM, how to run a state machine from an api gateway call?AWS SAM,如何从 api 网关调用运行状态机?
【发布时间】:2020-05-28 21:11:18
【问题描述】:

我正在尝试为工作流设置状态机,但对于我的生活,我似乎无法让它工作,这是我的 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 端点,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 {};
}

【问题讨论】:

    标签: amazon-web-services serverless aws-sam aws-sam-cli


    【解决方案1】:

    从 Lambda 函数启动 step 函数是可行的,但我认为在您的情况下,使用 API Gateway 的 DefinitionBody 直接从 Api Gateway 启动它是一个更好的解决方案,如下所示:

      /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 中提交了一个工作示例,其中包含用于检查执行状态的附加方法。

    【讨论】:

    • 感谢您的回答,我最终使用了 CDK,因为手动编写 yaml 太复杂了
    猜你喜欢
    • 2020-01-03
    • 2020-04-14
    • 1970-01-01
    • 2021-01-01
    • 1970-01-01
    • 2017-11-04
    • 2020-06-22
    • 2019-08-11
    • 2020-04-22
    相关资源
    最近更新 更多