Skip to content

Lambdas deployed on AWS

Christophe Bougère edited this page Aug 31, 2018 · 9 revisions

Test stepfunctions-local with Lambdas deployed on AWS

Prerequesites

Some dependencies are required in order to use the test commands.

Setup

We some environment variables in order to use the test commands.

export AWS_ACCOUNT_ID=<your-account-id>
export AWS_PROFILE=<your-profile>
export AWS_LAMBDA_REGION=<your-lambda-region>

Start Servers

You need to start stepfunctions-local server:

# start stepfunctions-local server
DEBUG=stepfunctions-local:* stepfunctions-local start --lambda-endpoint https://lambda.$AWS_LAMBDA_REGION.amazonaws.com --lambda-region $AWS_LAMBDA_REGION

Create policy

Ref: https://docs.aws.amazon.com/cli/latest/reference/iam/create-policy.html

We first need to create a policy for the lambdas role.

# create policy file (policy.json)
echo '{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:Get*",
        "s3:List*"
      ],
      "Resource": [
        "arn:aws:s3:::my-bucket/shared/*"
      ]
    }
  ]
}
' > policy.json

# create policy
aws iam create-policy --policy-name stepfunctions-local --policy-document file://policy.json

Create role

Ref: https://docs.aws.amazon.com/cli/latest/reference/iam/create-role.html

We need to create the role that we be used for the Lambdas.

# create role file (role.json)
echo '{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": {
      "Service": "lambda.amazonaws.com"
    },
    "Action": "sts:AssumeRole"
  }]
}' > role.json

# create role
aws --profile $AWS_PROFILE iam create-role --role-name StepFunctionsLocal --assume-role-policy-document file://role.json | export ROLE_ARN=`jq -r .Role.Arn`

# attach additional policies to role
aws --profile $AWS_PROFILE iam attach-role-policy --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole --role-name StepFunctionsLocal

You now have a $ROLE_ARN environment variable containing the role arn.

Create lambda functions

We will now create three simple lambda functions:

  • Success: A lambda function that will succeed
  • InternalErrorNotHandled: A lambda function that will fail because of an internal error (error not handled)
  • InternalErrorHandled: A lambda function that will fail because of an internal error (error handled)
  • Timeout: A lambda function that will timeout
# create handlers file (handlers.json)
echo 'module.exports.successHandler = function (event, context, callback) { event.result = { key: { subkey: "value" }}; callback(null, event); };
module.exports.internalErrorNotHandledHandler = function (event, context, callback) { throw new Error("Internal Error"); };
module.exports.internalErrorHandledHandler = function (event, context, callback) { try { throw new Error("Internal Error"); } catch (e) { callback(e); } };
module.exports.timeoutHandler = function (event, context, callback) { setTimeout(function() { callback(null, event); }, (context.getRemainingTimeInMillis() + 1000)); };' > handlers.js

# create zipfile (handlers.zip)
zip handlers.zip handlers.js

# create the functions and export lambda arns
aws lambda --profile $AWS_PROFILE create-function --function-name Success --runtime nodejs6.10 --role $ROLE_ARN --handler handlers.successHandler --zip-file fileb://handlers.zip | export SUCCESS_LAMBDA_ARN=`jq -r .FunctionArn`

aws lambda --profile $AWS_PROFILE create-function --function-name InternalErrorNotHandled --runtime nodejs6.10 --role $ROLE_ARN --handler handlers.internalErrorNotHandledHandler --zip-file fileb://handlers.zip | export INTERNAL_ERROR_NOT_HANDLED_LAMBDA_ARN=`jq -r .FunctionArn`

aws lambda --profile $AWS_PROFILE create-function --function-name InternalErrorHandled --runtime nodejs6.10 --role $ROLE_ARN --handler handlers.internalErrorHandledHandler --zip-file fileb://handlers.zip | export INTERNAL_ERROR_HANDLED_LAMBDA_ARN=`jq -r .FunctionArn`

aws lambda --profile $AWS_PROFILE create-function --function-name Timeout --runtime nodejs6.10 --role $ROLE_ARN --handler handlers.timeoutHandler --zip-file fileb://handlers.zip | export TIMEOUT_LAMBDA_ARN=`jq -r .FunctionArn`

You now have $SUCCESS_LAMBDA_ARN, $INTERNAL_ERROR_NOT_HANDLED_LAMBDA_ARN, $INTERNAL_ERROR_HANDLED_LAMBDA_ARN and $TIMEOUT_LAMBDA_ARN as environment variables containing the corresponding lambda functions arn.

Create State Machine

We will now create a simple State Machine. Note: You need to start the stepfunctions-local server.

cat <<EOF | xargs -0 aws stepfunctions --endpoint http://localhost:4584 create-state-machine --name test-state-machine --role-arn arn:aws:iam::0123456789:role/service-role/MyRole --definition
{"Comment": "Test Step Function","StartAt": "StartState","States": {"StartState": {"Type": "Pass","Next": "ChoiceState"},"ChoiceState": {"Type": "Choice","Choices": [{"Variable": "$.lambda","StringEquals": "InternalErrorNotHandled","Next": "InternalErrorNotHandledLambda"},{"Variable": "$.lambda","StringEquals": "InternalErrorHandled","Next": "InternalErrorHandledLambda"},{"Variable": "$.lambda","StringEquals": "Success","Next": "SuccessLambda"},{"Variable": "$.lambda","StringEquals": "Timeout","Next": "TimeoutLambda"}],"Default": "FailState"},"FailState": {"Type": "Fail","Error": "NoLambdaError","Cause": "No Matches!"},"SuccessLambda": {"Type": "Task","Resource": "$SUCCESS_LAMBDA_ARN","Next": "EndState"},"InternalErrorNotHandledLambda": {"Type": "Task","Resource": "$INTERNAL_ERROR_NOT_HANDLED_LAMBDA_ARN","Next": "EndState"},"InternalErrorHandledLambda": {"Type": "Task","Resource": "$INTERNAL_ERROR_HANDLED_LAMBDA_ARN","Next": "EndState"},"TimeoutLambda": {"Type": "Task","Resource": "$TIMEOUT_LAMBDA_ARN","Next": "EndState"},"EndState": {"Type": "Pass","End": true}}}
EOF

aws stepfunctions --endpoint http://localhost:4584 list-state-machines | export STATE_MACHINE_ARN=`jq -r .stateMachines[0].stateMachineArn`

Execute state machine

We will now execute the state machine with different inputs in order to trigger the different lambdas.
The lambda key contained in the input will be used as a filter to trigger the different lambdas.
It can take the following values:

  • Success > will trigger Success lambda
  • Timeout > will trigger Timeout lambda
  • InternalErrorNotHandled > will trigger InternalErrorNotHandled lambda
  • InternalErrorHandled > will trigger InternalErrorHandled lambda
# Success lambda
aws stepfunctions --endpoint http://localhost:4584 start-execution --state-machine-arn $STATE_MACHINE_ARN --input '{"lambda":"Success"}' --name success-execution

# InternalErrorNotHandled lambda
aws stepfunctions --endpoint http://localhost:4584 start-execution --state-machine-arn $STATE_MACHINE_ARN --input '{"lambda":"InternalErrorNotHandled"}' --name internal-error-not-handled-execution

# InternalErrorHandled lambda
aws stepfunctions --endpoint http://localhost:4584 start-execution --state-machine-arn $STATE_MACHINE_ARN --input '{"lambda":"InternalErrorHandled"}' --name internal-error-handled-execution

# Timeout lambda
aws stepfunctions --endpoint http://localhost:4584 start-execution --state-machine-arn $STATE_MACHINE_ARN --input '{"lambda":"Timeout"}' --name timeout-execution

The listing of the state machine executions should return one success and three failures:

aws stepfunctions --endpoint http://localhost:4584 list-executions --state-machine-arn $STATE_MACHINE_ARN
Clone this wiki locally