Deploying CloudFormation changes with Gradle

AWS

Last Updated on March 18, 2021

1. Introduction

AWS CloudFormation provides a great way to write infrastructure as code, and then to deploy that using the AWS API or AWS Console. Sometimes though, we need a deploy mechanism that’s more integrated into our project. In this article, you’ll learn how to use Gradle to easily deploy CloudFormation infrastructure by just running a Gradle task. This makes life a lot easier if you’re thinking about writing microservices or setting up a continuous delivery CI pipeline.

2. Gradle plugins to the rescue

Fortunately, a Gradle plugin already exists for this, the multi-purpose Gradle AWS plugin. It uses the AWS API to make all sorts of infrastructure changes, but importantly it allows us to:

  • update a CloudFormation stack
  • wait for a stack to reach a certain status, such as CREATE_COMPLETE

We’ll see how this works later in this article when we run through a working demo.

3. CloudFormation recap

As a reminder, in CloudFormation we deploy changes as a stack. This generally represents one YAML or JSON template file (unless we are using nested stacks). To make changes to a stack, we can deploy a new version of our CloudFormation template and wait for AWS to modify our infrastructure accordingly.

It follows then, that we’ll use a very similar process in Gradle, by creating/updating a stack, then waiting for the magic to finish happening. This is all accomplished by using tasks that are exposed by the Gradle AWS plugin.

4. Configuring a demo project

To see how this works, let’s start by configuring a Gradle project to use the AWS Gradle plugin.

Tip: Run gradle init to initialise the current working directory as a Gradle project. This will create the Gradle wrapper script and build.gradle.

In the build.gradle apply the plugin using the Gradle plugins configuration.

plugins {
   id "jp.classmethod.aws.cloudformation" version "0.41"
}

Configure the default credentials to be used by the plugin to access AWS. If you don’t have AWS credentials setup on your machine follow this guide to installing the AWS CLI and this guide to configuring your credentials using aws configure.

aws {
   profileName 'default'
}

If required you can also specify a region in this section e.g. region 'eu-west-1'

Important: your AWS credentials will need to provide permissions to allows CloudFormation and S3 resources to be modified. Specifically, the following actions are required:

cloudformation:UpdateStack
cloudformation:DescribeStacks
cloudformation:CreateStack
cloudformation:DeleteStack
s3:CreateBucket
s3:DeleteBucket

Now let’s add a CloudFormation template to our project that we can deploy to AWS. To keep things simple, we’ll just create a very basic S3 bucket.

s3Bucket.yml

AWSTemplateFormatVersion: 2010-09-09
Description: S3 bucket for testing AWS Gradle plugin
Resources:
 EncryptedS3Bucket:
   Type: AWS::S3::Bucket
   Properties:
     BucketName: !Sub 'test-bucket-${AWS::Region}-${AWS::AccountId}'
   DeletionPolicy: Delete

It’s now time to configure the AWS Gradle plugin to deploy this template as a CloudFormation stack. All we need to provide are the name of the stack we want to create and the template file.

cloudFormation {
   stackName 'test-stack'
   templateFile project.file('s3Bucket.yml')
}

Here’s the full build.gradle combining all the snippets above.

plugins {
   id "jp.classmethod.aws.cloudformation" version "0.41"
}

aws {
   profileName 'default'
}

cloudFormation {
   stackName 'test-stack'
   templateFile project.file('s3Bucket.yml')
}

Now if you run ./gradlew tasks you’ll see that the AWS Gradle plugin has added various CloudFormation related tasks.

Tip: on windows you’ll want to run gradlew.bat

 AWS tasks
---------
awsCfnCreateChangeSet - Create cfn change set.
awsCfnDeleteStack - Delete cfn stack.
awsCfnExecuteChangeSet - execute latest cfn change set.
awsCfnMigrateStack - Create/Migrate cfn stack.
awsCfnSetStackPolicy - Set CloudFormation stack policy
awsCfnUpdateStackTerminationProtection - Update CloudFormation stack termination protection
awsCfnUploadStackPolicy - Upload cfn stack policy file to the Amazon S3 bucket.
awsCfnUploadTemplate - Upload cfn template file to the Amazon S3 bucket.
awsCfnValidateTemplateUrl - Validate template URL.
awsCfnWaitStackComplete - Wait cfn stack for CREATE_COMPLETE or UPDATE_COMPLETE status.
awsCfnWaitStackCompleteAfterCreateChangeSet - Wait cfn stack for CREATE_COMPLETE, UPDATE_COMPLETE or REVIEW_IN_PROGRESS status.
awsCfnWaitStackDeleted - Wait cfn stack for DELETE_COMPLETE status.
awsCfnWaitStackReady - Wait cfn stack for *_COMPLETE status.
awsWaitCreateChangeSetComplete - Wait cfn change set for CREATE_COMPLETE status

The one we’re going to use is awsCfnMigrateStack which does the job of updating the CloudFormation stack, but it doesn’t wait for all the changes to be rolled out by AWS. For this we’ll also have to run awsCfnWaitStackComplete which waits for the stack to reach a completed state.

So run those 2 tasks using ./gradlew awsCfnMigrateStack awsCfnWaitStackComplete and wait for it to complete successfully.

That’s it! Your CloudFormation template has been applied and your S3 bucket has been created. To verify this log into the AWS console and you should see your bucket listed when you click on Services > S3, like this:

Similarly, if you go to Services > CloudFormation then you’ll see test-stack listed with status CREATE_COMPLETE.

To clean this up we just need to run ./gradlew awsCfnDeleteStack which will delete the stack and consequently the S3 bucket too.

5. Conclusion

You’ve seen how to deploy CloudFormation changes from Gradle using the Gradle AWS plugin. This opens up many possibilities in terms of automating deployment of infrastructure, and bringing infrastructure and software together so they can be rolled out from a single repository.

Get going with Gradle course
Gradle icon

Want to learn more about Gradle?
Check out the full selection of Gradle tutorials.

Deploying CloudFormation changes with Gradle

Leave a Reply

Your email address will not be published. Required fields are marked *

Scroll to top