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-api
或 sam local start-lambda
启动服务。
- 使用这些命令启动 api 有什么不同吗?
- 在我粘贴的模板中,我使用
!Ref
获取状态机 ARN,但这不起作用,返回相同的字符串,如果我将其更改为 !GetAtt StepFunctionsStateMachine.Arn
- 更改 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 中提交了一个工作示例,其中包含用于检查执行状态的附加方法。
我正在尝试为工作流设置状态机,但我似乎无法让它正常工作,这是我的 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-api
或 sam local start-lambda
启动服务。
- 使用这些命令启动 api 有什么不同吗?
- 在我粘贴的模板中,我使用
!Ref
获取状态机 ARN,但这不起作用,返回相同的字符串,如果我将其更改为!GetAtt StepFunctionsStateMachine.Arn
- 更改 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 中提交了一个工作示例,其中包含用于检查执行状态的附加方法。