Working on AWS Step function create, I have these steps:
The question for me - how I can wait until CloudFormation stack creating will be completed before Lambda from step 3 execute another Lambda?
There are a few ways you could do this, but the best solution is likely to use a polling loop in your Step Functions statemachine. Using AWS SDK Service Integrations, you may be able to avoid the need for maintaining a Lambda function just to call the CloudFormation API. See the example below where I generate a super simple template (just creating a single SQS Queue), then use a polling loop to monitor for completion.
Rather than baking the template directly into the state machine definition, you could store it in S3 and use arn:aws:states:::aws-sdk:s3:getObject
to load it at runtime.
One thing to keep in mind here is the 256 kB payload size limit for Step Functions. If your template size was expected to approach that size, then that would be a reason to use a Lambda function to call CreateStack instead (though you could then have it return the stack_id and continue with the rest of this).
And if you want to have multiple stack creations in sequence, you could create this one as a re-usable "utility" (with some input processing to specify which template and parameters) then have other state machines use the arn:aws:states:::states:startExecution.sync:2
integration to call this state machine from a parent. Given that this supports the Run a Job (.sync) integration pattern, you don't need to add another polling loop.
{
"Comment": "An example of creating a CloudFormation stack and waiting for completion.",
"StartAt": "Generate Template",
"States": {
"Generate Template": {
"Comment": "Placeholder for a task state which starts a job. Replace with an API action.",
"Type": "Pass",
"Next": "Create Stack",
"Result": {
"AWSTemplateFormatVersion": "2010-09-09",
"Resources": {
"SQSQueue": {
"Type": "AWS::SQS::Queue"
}
}
},
"ResultPath": "$.template_body"
},
"Create Stack": {
"Type": "Task",
"Parameters": {
"StackName.$": "States.Format('TestStack-{}',States.UUID())",
"TemplateBody.$": "States.JsonToString($.template_body)"
},
"Resource": "arn:aws:states:::aws-sdk:cloudformation:createStack",
"Next": "Wait 15 Seconds",
"ResultPath": "$.stack_name",
"Retry": [
{
"ErrorEquals": [
"States.ALL"
],
"BackoffRate": 2,
"IntervalSeconds": 2,
"MaxAttempts": 3,
"JitterStrategy": "FULL"
}
]
},
"Wait 15 Seconds": {
"Type": "Wait",
"Next": "Describe Stack",
"Seconds": 15
},
"Describe Stack": {
"Type": "Task",
"Parameters": {
"StackName.$": "$.stack_name.StackId"
},
"Resource": "arn:aws:states:::aws-sdk:cloudformation:describeStacks",
"Next": "Stack Creation Complete?",
"ResultSelector": {
"Status.$": "$.Stacks[0].StackStatus"
},
"ResultPath": "$.stack_status",
"Retry": [
{
"ErrorEquals": [
"States.ALL"
],
"BackoffRate": 4,
"IntervalSeconds": 2,
"MaxAttempts": 5,
"JitterStrategy": "FULL"
}
]
},
"Stack Creation Complete?": {
"Type": "Choice",
"Choices": [
{
"Variable": "$.stack_status.Status",
"StringEquals": "CREATE_FAILED",
"Next": "Stack Creation Failed"
},
{
"Variable": "$.stack_status.Status",
"StringEquals": "CREATE_COMPLETE",
"Next": "Stack Creation Successful"
},
{
"Variable": "$.stack_status.Status",
"StringEquals": "CREATE_IN_PROGRESS",
"Next": "Wait 15 Seconds"
}
],
"Default": "Stack Creation Result Unknown"
},
"Stack Creation Result Unknown": {
"Type": "Fail",
"Error": "Unexpected Completion",
"CausePath": "$.stack_status.Status"
},
"Stack Creation Successful": {
"Type": "Succeed"
},
"Stack Creation Failed": {
"Type": "Fail",
"Error": "Stack Creation Failed"
}
}
}