Domesticate AWS nested stacks in Java: doing the chores Cloudformation doesn't do (w/ code samples)
Tags: website, aws, cloudformation, java
Published: 2024-05-13 07:06:51

---
title: Domesticate AWS nested stacks in Java: doing the chores Cloudformation doesn't do (w/ code samples)
published: true
date: 2024-05-07 20:49:02 UTC
tags: Website,AWS,Cloudformation,Java
canonical_url: https://marcoaguzzi.it/2024/05/07/domesticate-nested-stack/
---

In this article we’ll navigate through the creation of a Nested Stack in Cloudformation using the Java SDK. The child stack will be a lambda function, and the code will be uploaded with a zip archive.

# What’s Cloudformation, and what’s a nested stack?

Cloudformation is the AWS offering of _infrastructure as code_. Instead of navigating the web UI adding and configuring resources, Cloudformation offers the capability of reading a user - supplied file (either JSON or YAML) containing the list of resources and their relationships and create them as the code states.  
These resources must be grouped in _Stacks_, which is the parentmost object that Cloudformation can process.  
Things get interesting when stacks reference _other_ stacks, of course :-)

# A nested stack example

Doing this process with SDK, there are a couple of things that are not done automatically (or easier) than using the AWS CLI. Let’s get through them

## Parent stack

Below there is the JSON for the parent stack. There is no specification that this is a stack (it’s written in the _Description_, but it’s arbitrary), because the command that will create the stack will ask first for a stack name to create (or update).  
On the contrary, the child stack is explicitly declared as one of the resources with an _AWS::CloudFormation::Stack_ type (line 7). Within the _ChildStack_ element, the most important property is the _TemplateURL_ (line 9), that points to the file (YAML in this case). The path is relative to the root template location.  
Here’s the code:

_Parent stack_

```
{
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "Root stack",
 ...
"Resources": {
"ChildStack":{
"Type" : "AWS::CloudFormation::Stack",
"Properties": {
"TemplateURL":"child-folder/child-template.yaml",
 ...
}
},
"OtherResource": {
"Type": "ResourceType",
 ...
}
}
}

```

Let’s view the child stack:

## Child stack

Also in this case there’s no particular reference to the fact that this is a child stack. The parent stack can pass parameters to the child stack via the parameter section, but that’s it.

_Child stack_

```
AWSTemplateFormatVersion: "2010-09-09"
Description: child stack
Parameters:
...
Resources:
LambdaEdge:
Properties:
Runtime: nodejs20.x
Handler: index.handler
Code:
S3Bucket:
...
S3Key: "example value"
Role: !GetAtt LambdaRoleForCF.Arn
Type: "AWS::Lambda::Function"
Outputs:
...

```

### The lambda reference

On line 13, the template file references a S3 location there the zip file with the code must be found. So the zip file with the code must be uploaded in S3 before the creation of the parent stack is issued, otherwise the references won’t work. As it’s noted in the next section, the AWS CLI _package_ command can resolve references like this, but it’s not present in the SDK.  
Once that the zip file with the code is uploaded onto S3, the creation of the stack can proceed.

# Creating the stack

Before creating the stack, the template file must be present on S3 in order to be pointed at by the create-stack command.  
This is fine, but the template contains the child stack file path that references the local machine, which won’t never work from s3.  
The solution for Cloudformation is packaging the stack.

# Packaging the stack

## Using the CLI

Via the CLI is quite easy: there’s a _package_ command that

- detects the substack reference
- searches for the referenced file
- uploads it on s3
- changes the reference in the parent file

## Java SDK

Unfortunately, the aws-cli _package_ command is not available in Java SDK, so a manual approach must be taken.  
Here’s the code from the [S3 static website project](https://github.com/maguzzi/s3_static_website_gradle/blob/main/src/main/java/it/marcoaguzzi/staticwebsite/commands/misc/PackageTemplateCommand.java) (around line 44)  
The code does the same stuff that the cli do:

- _templateSrcPath_ (line 3) contains the path to the local parent template
- _s3PathToReplace_ (line 9) contains the path to the child stack template already uploaded to S3
- lines 4 to 11 cycle throught the parent template,
  - searches for a resource with type _AWS::CloudFormation::Stack_
  - replaces the _TemplateURL_ attribute with the path of the template uploaded onto S3
- Then it persist the file with the substitution onto a temporary folder.  
Using the SDK the template can be referenced from within the disk.

_Template packaging_

```
App.screenMessage("PACKAGE TEMPLATE START");
ObjectMapper objectMapper = new ObjectMapper();
JsonNode root = objectMapper.readTree(Utils.readFileContent(templateSrcPath)); 
Iterator<JsonNode> elements = root.get("Resources").elements();
while(elements.hasNext()) {
 JsonNode node = elements.next(); 
 if ("AWS::CloudFormation::Stack".equals(node.get("Type").asText())) {
JsonNode properties = node.get("Properties");
 ((ObjectNode)properties).put("TemplateURL", s3PathToReplace);
 }
};
File file = File.createTempFile(new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()),"\_compiled\_template.json");
objectMapper.writeValue(file, root);
App.screenMessage("PACKAGE TEMPLATE END");

```

Once that the template on the disk has all of its references ready, the _CreateStack_ api can be called and the stack will be created along with all of its resources.

# Improvements and what’s next

The actual CLI package command does not only resolve nested stack references, but also lambda code (as it has been shown) and a bunch of other stuff (as stated here).  
There are two major improvements to the code for the package section

- also discover other type of references (like lambda code)
- automatically upload the referenced path to s3 without actually asking for it in the input parameters

If you’d like to browse to the full code [here](https://github.com/maguzzi/s3_static_website_gradle), please give it a go!