Integrating Ansible with CloudFormation

While there are different strategies to integrate Ansible to CloudFormation, in our situation there is an obvious path. We are going to take advantage of the UserData field, and do the initialization of Ansible through the ansible-pull command.

We are going to start off the troposphere script we created earlier in this chapter. We will duplicate it and call the new script ansiblebase-cf-template.py.

Go to your template repository and duplicate the previous template as follows:

$ cd EffectiveDevOpsTemplates
$ cp helloworld-cf-template.py ansiblebase-cf-template.py  

Then, open the ansiblebase-cf-template.py script with your editor.

To keep the script readable, we will first define several variables.

Before the declaration of the application port, we will define an application name:

ApplicationName = "helloworld" 
ApplicationPort = "3000" 

We will also set a number of constants around the GitHub information. Replace the value of GithubAccount with your GitHub username or GitHub organization name:

ApplicationPort = "3000" 
 
GithubAccount = "EffectiveDevOpsWithAWS"
GithubAnsibleURL = "https://github.com/{}/ansible".format(GithubAccount)

After the definition of GithubAnsibleURL, we are going to create one more variable that will contain the command line we want to execute to configure the host through Ansible. We will call ansible-pull and use the variables GithubAnsibleURL and ApplicationName that we just defined. This is what this looks like:

AnsiblePullCmd =  
    "/usr/local/bin/ansible-pull -U {} {}.yml -i localhost".format( 
        GithubAnsibleURL, 
        ApplicationName 
    ) 

We are now going to update the userdata block. Instead of installing Node.js, downloading our application files and starting the service, we will change this block to install git and ansible, execute the command contained in the AnsiblePullCmd variable, and finally create a cronjob to re-execute that command every 10 minutes.

Delete the previous ud variable definition and replace it with the following:

ud = Base64(Join('
', [
"#!/bin/bash",
"yum install --enablerepo=epel -y git",
"pip install ansible",
AnsiblePullCmd,
"echo '*/10 * * * * {}' > /etc/cron.d/ansible-pull".format(AnsiblePullCmd)
]))

We can now save our file and use it to create our JSON template and test it. Your new script should look like this: http://bit.ly/2vZtvGD

$ python ansiblebase-cf-template.py > ansiblebase.template
$ aws cloudformation update-stack 
      --stack-name HelloWorld 
      --template-body file://ansiblebase.template 
      --parameters  ParameterKey=KeyPair,ParameterValue=EffectiveDevOpsAWS
{
    "StackId": "arn:aws:cloudformation:us-east-1:511912822958:stack/HelloWorld/ef2c3250-6428-11e7-a67b-50d501eed2b3"  
}

We can now wait until the execution is complete:

$ aws cloudformation wait stack-create-complete 
      --stack-name HelloWorld

Now that the stack creation is complete, we can query CloudFormation to get the output of the stack and more particularly its public IP address:

$ aws cloudformation describe-stacks 
--stack-name HelloWorld
--query 'Stacks[0].Outputs[0]' { "Description": "Public IP of our instance.", "OutputKey": "InstancePublicIp", "OutputValue": "54.234.241.247" }

And finally, we can verify that our server is up and running:

$ curl 54.234.241.247:3000
Hello World  

We can now commit our newly created troposphere script to our EffectiveDevOpsTemplates repository:

$ git add ansiblebase-cf-template.py
$ git commit -m "Adding a Troposphere script to create a stack that relies on Ansible to manage our application"
$ git push  

We now have a complete solution to manage our infrastructure efficiently using code. We demonstrated it on a very simple example but, as you can imagine, everything is applicable to bigger infrastructures with a greater number of services.

This chapter is almost over, we can now delete our stack to free up the resources that we are currently consuming. In the earlier part of the chapter, we did that using the web interface. As you can imagine, this can also be done easily using the command-line interface, as follows:

$ aws cloudformation delete-stack --stack-name HelloWorld  
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset