如何使用 serverless-step-functions 插件中的定义调​​用 AWS Step Function?

How to call an AWS Step Function using the definitions in the serverless-step-functions plugin?

我正在使用 Serverless Framework 来创建我的 Lambda 函数,并使用 serverless-step-functions 插件来定义我的步骤函数。

是否可以使用 serverless.yml 文件中定义的名称直接从 lambda 函数之一调用步进函数?

使用无服务器环境变量解决:

environment:
  MYFUNCTION_ARN: "arn:aws:states:${self:provider.region}:${self:provider.environment.AWS_ACCOUNT}:stateMachine:${self:service}-${self:provider.stage}-myFunction"

在函数中:

var params = {
  stateMachineArn: process.env.MYFUNCTION_ARN
};

我试图解决同样的问题,这个问题和自我回答非常有帮助。但是,我想添加另一个答案,其中包含更多详细信息和一个工作示例,以帮助未来的读者。


您可能需要两件事:

1- 启动状态机
2- 从状态机调用一个特定函数(通常用于测试目的)

下面的演示使用了这两种情况。

首先,我们需要配置 serverless.yml 文件来声明状态机、Lambda 函数和正确的 IAM 权限。

service: test-state-machine

provider:
  name: aws
  runtime: nodejs4.3
  region: us-east-1
  stage: dev
  environment:
    AWS_ACCOUNT: 1234567890 # use your own AWS ACCOUNT number here

    # define the ARN of the State Machine
    STEP_FUNCTION_ARN: "arn:aws:states:${self:provider.region}:${self:provider.environment.AWS_ACCOUNT}:stateMachine:${self:service}-${self:provider.stage}-lambdaStateMachine"

    # define the ARN of function step that we want to invoke
    FUNCTION_ARN: "arn:aws:lambda:${self:provider.region}:${self:provider.environment.AWS_ACCOUNT}:function:${self:service}-${self:provider.stage}-stateMachineFirstStep"  

functions:
  # define the Lambda function that will start the State Machine
  lambdaStartStateMachine: 
    handler: handler.lambdaStartStateMachine  
    role: stateMachine # we'll define later in this file

  # define the Lambda function that will execute an arbitrary step
  lambdaInvokeSpecificFuncFromStateMachine: 
    handler: handler.lambdaInvokeSpecificFuncFromStateMachine
    role: specificFunction # we'll define later in this file

  stateMachineFirstStep:
    handler: handler.stateMachineFirstStep

# define the State Machine
stepFunctions:
  stateMachines:
    lambdaStateMachine:
      Comment: "A Hello World example"
      StartAt: firstStep
      States: 
        firstStep: 
          Type: Task
          Resource: stateMachineFirstStep
          End: true    

# define the IAM permissions of our Lambda functions
resources:
  Resources:
    stateMachine:
      Type: AWS::IAM::Role
      Properties:
        RoleName: stateMachine
        AssumeRolePolicyDocument:
          Version: '2012-10-17'
          Statement:
            - Effect: Allow
              Principal:
                Service:
                  - lambda.amazonaws.com
              Action: sts:AssumeRole
        Policies:
          - PolicyName: stateMachine
            PolicyDocument:
              Version: '2012-10-17'
              Statement:
                - Effect: "Allow"
                  Action:
                    - "states:StartExecution"
                  Resource: "${self:provider.environment.STEP_FUNCTION_ARN}"
    specificFunction:
      Type: AWS::IAM::Role
      Properties:
        RoleName: specificFunction
        AssumeRolePolicyDocument:
          Version: '2012-10-17'
          Statement:
            - Effect: Allow
              Principal:
                Service:
                  - lambda.amazonaws.com
              Action: sts:AssumeRole
        Policies:
          - PolicyName: specificFunction
            PolicyDocument:
              Version: '2012-10-17'
              Statement:
                - Effect: "Allow"
                  Action:
                    - "lambda:InvokeFunction"
                  Resource: "${self:provider.environment.FUNCTION_ARN}"

package:
  exclude:
    - node_modules/**
    - .serverless/**

plugins:
  - serverless-step-functions

handler.js 文件中定义 Lambda 函数。

const AWS = require('aws-sdk');

module.exports.lambdaStartStateMachine = (event, context, callback) => {
  const stepfunctions = new AWS.StepFunctions();
  const params = {
    stateMachineArn: process.env.STEP_FUNCTION_ARN,
    input: JSON.stringify({ "msg": "some input" })
  };

  // start a state machine
  stepfunctions.startExecution(params, (err, data) => {
    if (err) {
      callback(err, null);
      return;
    }

    const response = {
      statusCode: 200,
      body: JSON.stringify({
        message: 'started state machine',
        result: data
      })
    };

    callback(null, response);
  });
};

module.exports.lambdaInvokeSpecificFuncFromStateMachine = (event, context, callback) => {  
  const lambda = new AWS.Lambda();
  const params = {
    FunctionName: process.env.FUNCTION_ARN,
    Payload: JSON.stringify({ message: 'invoked specific function' })
  };

  // invoke a specific function of a state machine
  lambda.invoke(params, (err, data) => {
    if (err) {
      callback(err, null);
      return;
    }

    const response = {
      statusCode: 200,
      body: JSON.stringify({
        message: 'invoke specific function of a state machine',
        result: data
      })
    };

    callback(null, response);
  });
};

module.exports.stateMachineFirstStep = (event, context, callback) => {
  const response = {
    statusCode: 200,
    body: JSON.stringify({
      message: 'state machine first step',
      input: event
    }),
  };

  callback(null, response);
};

部署执行:

serverless deploy stepf  
serverless deploy  

测试使用:

serverless invoke -f lambdaStartStateMachine  
serverless invoke -f lambdaInvokeSpecificFuncFromStateMachine

这是你现在的解决方法。

在您的 serverless.yml 中,定义您的 stepFunctions 以及 Outputs:

# define your step functions
stepFunctions:
  stateMachines:
    myStateMachine:
      name: stateMachineSample
      events:
        - http:
            path: my-trigger
            method: GET

# make it match your step functions definition
Outputs:
    myStateMachine:
      Value:
        Ref: StateMachineSample

然后您可以使用 ${self:resources.Outputs.fipeStateMachine.Value}.

将状态机 ARN 设置为环境