serverless-step-functions
serverless-step-functions copied to clipboard
Support lambda-less definitions with ${} style resource references
This is a Feature Proposal to support Lambda-less definitions with references to other resources (AWS Batch)
Description
If you create a serverless application that is comprised only of a stepFunctions
block and a resources
block (that defines some stuff in AWS Batch via a CF yml file), you are unable to refer to the CloudFormation Resources via ${Name}
and have that result in the ARN of that resource. Much of this setup was inspired from this blog post and this code.
Here's a snipped of a stepFunction that should reproduce the issue:
resources:
- ${file(batch.yml)}
stepFunctions:
validate: true
stateMachines:
TestPipeline:
name: ${self:service}-StepFunction-${opt:stage}
useExactVersion: true
definition:
StartAt: PipelineStep
States:
PipelineStep:
Type: Task
Resource: arn:aws:states:::batch:submitJob.sync
Parameters:
JobName: MyJob-${opt:stage}
JobDefinition: "${SlsJobDefinition}"
JobQueue: "${SlsJobQueue}"
where batch.yml
contains CloudFormation to setup an AWS Batch environment.
This generates a serverless state file that has a DefinitionString
for this step function that is a string of the serialized JSON. This means that CloudFormation will not do any replacement of the ${SlsJobDefinition}
and ${SlsJobQueue}
parameters with their respective ARNs. Instead the literal values as they appear here are used in the Step Function definition.
You can trigger this behavior if you also have a state that references a lambda functions. The code here shows more, but basically the raw json string gets wrapped in a Fn::Sub
call in the generated CF template, but only when there are references to lambdas or there are pseudo parameters.
I did try to convert the ${}
references to #{}
references which did trigger a new path, but unfortunately failed because of this block of code. Basically if you've specified useExactVersion
, and we're wrapping the json in that call, the assumption is that the Fn::Sub
key contains an object you can reference [1]
on, but if you go down this branch, and have no lambda references and have some pseudo parameters, the value of the Fn::Sub
key is a string (the json string)...and so you get an error like this:
TypeError: Cannot assign to read only property '1' of string '{
...more json here
'
We were able to work around this fully by changing our definition to the following:
stepFunctions:
validate: true
stateMachines:
TestPipeline:
name: ${self:service}-StepFunction-${opt:stage}
#useExactVersion: true
definition:
StartAt: PipelineStep
States:
PipelineStep:
Type: Task
Resource: arn:aws:states:::batch:submitJob.sync
Parameters:
JobName: MyJob-${opt:stage}
JobDefinition: "#{SlsJobDefinition}"
JobQueue: "#{SlsJobQueue}"
Basically switch to using pseudo-parameter style references (no long required in our version of sls) and the disabling of exact versioning (which for us, isn't a deal breaker).
Additional Data
Here's some output from a failure run:
Operating System: linux
Node Version: 17.3.0
Framework Version: 2.65.0
Plugin Version: 5.5.1
SDK Version: 4.3.0
Components Version: 3.18.1