AWS Template Creation by Script

During an AWS architecture class, we had to create and launch an AWS Stack. Within the stack, it was Infrastructure as Code, but the actual launch of the stack was done at the console. Once upon a time, I knew I had worked with stack creation as IaC. I dug back through some of my old examples and found the code (below) that I used to create the stack, along with some of the variables.

The Code

Line numbers are for reference. Note that this is a single bash shell block (hence the “\” at the end of each line starting in line 2.

1.  cfn_stack_name="${JOB_NAME}-${pipeline_instance_id}"
2.  cfn_stack_id=$(aws cloudformation create-stack \
3.     --disable-rollback \
4.     --region $region \
5.     --stack-name "$cfn_stack_name" \
6.     --template-body "file://${cfn_template_path}" \
7.     --parameters ParameterKey=amiID,ParameterValue=$baseami \
8.         ParameterKey=vpcID,ParameterValue=$vpc \
9.         ParameterKey=subnetID,ParameterValue=$subnet \
10.        ParameterKey=keypairName,ParameterValue=$jenkins_key_name \
11.    --tags Key=BuiltBy,Value="Jenkins_$(hostname)" \
12.    --tags Key=AWS_OP_ENV,Value="$aws_op_env" \
13.    --tags Key=Server,Value="$server_function" \
14.    --tags Key=System,Value="$system" \
15.    --query 'StackId' --output text)
16. max_waitime=600
17. wait_interval=5
.
.
.
18. # wait until the stack is created
19. echo "Waiting for CFN stack to be created..."
20. time monitor_stack --region "$region" --stack "$cfn_stack_name"
21. cfn_instance_id=$(aws cloudformation describe-stacks --region $region --stack-name="$cfn_stack_name" --query 'Stacks[0].Outputs[0].OutputValue' --output text)
22. echo "CGN stack created!"

The other thing to note is you need to have the AWS CLI installed in your build environment for this to work. In most cases, you will be building this inside AWS, so the CLI will be available to you.

The Explanation

In the code starting on line 1:

cfn_stack_name="${JOB_NAME}-${pipeline_instance_id}"

The JOB_NAME and pipeline_instance_id are generated by the Jenkins job. You can name it however you want, that was just what we used. We originally started with just date/time stamps.

Line 2 begins the actually stack creation:

cfn_stack_id=$(aws cloudformation create-stack

The cfn_stack_id is generated at the end of the code block: --query 'StackID' --output text. The syntax may be old, check the documentation for the correct call for the StackID. The rest of the data is necessary to define the stack.

Most of the variables are defined higher up in the script, most based on calls to a DymanoDB instance where we would store various bits of data that may or may not have changed throughout the build process, or as defined by the customer. We also saved the stack name in that same DB system so we could tear it down later.

Finally we wrapped it with a timer value. This may need to be adjusted based on the speed of the environment or number of variables you are pushing into the stack. You want the system to error out if things are too busy, otherwise the script will hang and the build server will appear to be stuck. We also had some additional verbiage at the bottom of the script that pushed text to the log file/console output so you could see it succeed as shown in lines 18 - 22.

One other thing to note is that the stack also launches an AMI (again pulled from reference). Once this stack and associated AMI are up, the next part of the pipeline starts. This could populate the AMI, test it, turn it into a Jenkins build server, whatever was necessary. The key here is it is all code.