Defining Nested Stacks
This tutorial references the code in the aws-connectedcar-dotnet-serverless repository. If you're new to this course, see the introduction for information about setting up your workstation and getting the sample code.
CloudFormation makes it possible to define nested stacks by declaring child templates within a parent template. This feature makes it possible to organize your templates into smaller, more cohesive units that can potentially be reused across different projects. As you’ll see below, the templates for the sample code are structured in this way.
Defining CloudFormation Stacks as Resources
Nested stacks are made possible by defining child templates as “stack” resources within parent templates. These stack resources reference the child templates in the TemplateURL property, as shown in the master.yaml template, below:
In the code shown above, lines 32 to 39 define the child stack, including the logical stack name, the S3-hosted TemplateURL for the uploaded services.yaml template, and the value assignments for the three parameters that this template requires.
Reading Outputs from Child Stacks
When all your resources are defined in a single template, it’s easy to reference properties for other resources. Like with structured programming, once you move resource definitions to separate child templates, you then need to expose some properties as outputs so that they can be passed back as values that can be applied in other templates.
To show how this works, here’s the RoleStack resource in the master.yaml template. The ServiceStack that precedes this in the template includes an IAM policy that grants access to the resources it deploys. The ARN for this policy is made available as the “ServicesPolicyArn” in the services.yaml outputs. This output is then referenced as a parameter for the roles.yaml template that follows, as shown on lines 47-49 below:
Deploying Nested Stacks
When running the command to create a CloudFormation stack, one of the arguments is the name of a local file for the template to be used. With nested stacks, however, CloudFormation needs to read the child templates while it’s executing in the cloud. As a result, the child templates need to be uploaded to an S3 bucket that CloudFormation can access, and these uploads need to happen before a deployment script calls the create- or update-stack commands.
You can look at the deploy.zsh script for the SAM version of the sample code to see how it performs these template uploads prior to calling the create/update stack commands:
On lines 11-29, you can see that each of the child templates is uploaded to the S3 bucket using the service and environment name parameters to construct file keys. Looking again at the service stack resource in the master.yaml template, you can see that the TemplateURL property is constructed to match, on line 35 below:
It’s important to keep the uploaded templates for different environments separate from one another in this way, so that changes can be made to the templates for each without impacting the others.