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
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
stepFunctionsblock and aresourcesblock (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:
where
batch.ymlcontains CloudFormation to setup an AWS Batch environment.This generates a serverless state file that has a
DefinitionStringfor 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::Subcall 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 specifieduseExactVersion, and we're wrapping the json in that call, the assumption is that theFn::Subkey 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 theFn::Subkey is a string (the json string)...and so you get an error like this:We were able to work around this fully by changing our definition to the following:
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: