Deploying CloudFormation Stacks From Azure DevOps to AWS

Deploying CloudFormation Stacks From Azure DevOps to AWS

This guide demonstrates how to deploy a CloudFormation stack from Azure DevOps to AWS. To keep this guide simple the CloudFormation Stack will only contain three S3 buckets.

For this guide you will need to create to files: pipeline.yaml for the pipeline file and template.yaml for the CloudFormation template file.

Variables

To follow along with this guide you will need to the define the following variables:

Variable Description
AwsServiceConnection Service connection name found under Service Connections in the project settings page
AwsBucket AWS bucket for the deploy files
Region AWS region to deploy the solution to. E.g: eu-west-1
StackName Name of the stack to deploy

The variables needs to be placed in the library folder with the name prod.

Azure DevOps Build File

The Azure DevOps build file contains three steps: create a S3 bucket, build the template files and lastly deploying the template file.

Create Deploy Bucket for CloudFormation Template

AWS CloudFormation stacks can be at most 51,200 bytes using the API or the CLI. The template size limit can be increased by uploading the CloudFormation template file to AWS S3. In this example we use the built in S3Upload task in Azure DevOps. This task is used only to create an empty bucket for the CloudFormation template to be uploadet to. The inputs used are

  • The AWS service connection
  • The AWS S3 bucket name
  • The region to place the bucket
  • createBucket to ensure that the bucket is created if it doesn't exist
  • globExpressions with the value undefined is used because we don't want to upload any files. By using the value undefined no files are uploaded to the bucket, as this value will not match any files in your project folder.
- task: S3Upload@1
  displayName: Create Deploy Bucket
  inputs:
    awsCredentials: AwsServiceConnection
    bucketName: $(AwsBucket)
    regionName: $(Region)
    globExpressions: "undefined"
    createBucket: true

Build Template

During this step we build the template using the SAM CLI. We could have used the built in AWS task inside Azure DevOps to create and update our template, but if we want to build Lamba functions we need to use the SAM CLI to build the Lamba functions. The Azure DevOps task AWSShellScript already have the SAM CLI ready for us to use. The inputs used are:

  • The AWS service connection
  • The AWS region
  • The script type defined as inline
  • The inline script itself which uses the command sam build to build the project
- task: AWSShellScript@1
  displayName: Package
  inputs:
    awsCredentials: AwsServiceConnection
    regionName: $(Region)
    scriptType: 'inline'
    inlineScript: |
      sam build --debug \
      --template-file template.yaml

Deploy Template

Lastly, we need to deploy the CloudFormation template to AWS. Again we use the AWSShellScript, but this time we use the SAM CLI command deploy which deploys the CloudFormation stack to AWS. In this task we use the following inputs:

  • The AWS service connection
  • The AWS region
  • Defining the script type as inline
  • The sam deploy command

The following options are added to the sam deploy command:

  • template-file - defining the name of the CloudFormation template to deploy, in our case that is template.yaml
  • no-confirm-changset - don't ask for confirmation to deploy the changes
  • capabilities - accept the stack to create IAM roles and to create nested stacks
  • stack-name - stack name
  • s3-bucket - S3 bucket to store the CloudFormation files
  • s3-prefix - Prefix for the CloudFormation deploy files
- task: AWSShellScript@1
    displayName: Deploy Infrastructure
    inputs:
      awsCredentials: AwsServiceConnection
      regionName: $(Region)
      scriptType: "inline"
      inlineScript: |
        sam deploy \
        --template-file template.yaml \
        --no-confirm-changeset \
        --capabilities CAPABILITY_IAM CAPABILITY_AUTO_EXPAND \
        --stack-name $(StackName) \
        --s3-bucket $(AwsBucket) \
        --s3-prefix $(StackName)

The Complete Build File

The complete build file can be seen below. As you see there are a few parts not mentioned yet. The trigger section defines what to trigger a new build, and in this case the master branch. pool defines the underlying vm to use. variables reference to a library group called prod.

trigger:
  branches:
    include:
      - master

pool:
  vmImage: "ubuntu-latest"

variables:
  - group: prod

steps:
  - task: S3Upload@1
    displayName: Create Deploy Bucket
    inputs:
      awsCredentials: AwsServiceConnection
      bucketName: $(AwsBucket)
      regionName: $(Region)
      globExpressions: "undefined"
      createBucket: true

  - task: AWSShellScript@1
    displayName: Package
    inputs:
      awsCredentials: AwsServiceConnection
      regionName: $(Region)
      scriptType: 'inline'
      disableAutoCwd: true
      inlineScript: |
        sam build --debug \
        --template-file template.yaml

  - task: AWSShellScript@1
    displayName: Deploy Infrastructure
    inputs:
      awsCredentials: AwsServiceConnection
      regionName: $(Region)
      scriptType: "inline"
      inlineScript: |
        sam deploy \
        --template-file template.yaml \
        --no-confirm-changeset \
        --capabilities CAPABILITY_IAM CAPABILITY_AUTO_EXPAND \
        --stack-name $(StackName) \
        --s3-bucket $(AwsBucket) \
        --s3-prefix $(StackName)

Template File

Create a file called template.yaml. The template file itself in this guide is kept short to simplify the example. The template contains three AWS S3 buckets with the names: images-bucket, thumbnail-bucket and video-bucket.

AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Description: Description

Resources:  
  ImagesBucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: images-bucket

  ThumbnailBucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: thumbnail-bucket
      
  VideBucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: video-bucket

Support

If you want to support this blog you can do so by signing up to DigitalOcean using this referral link.