Creating the CloudFormation template

In order to keep our code fairly similar to what we saw in Chapter 3, Treating Your Infrastructure As Code, we are going to start off the helloworld troposphere code that we created in that chapter. We are first going to duplicate the Python script. Go to your EffectiveDevOpsTemplates directory where you have your troposphere templates and then clone the ansiblebase-cf-template.pyfile:

$ cp ansiblebase-cf-template.py jenkins-cf-template.py  

The Jenkins host will need to interact with AWS. For that, we will create an instance profile (more on that later) taking advantage of another library developed by the same authors as troposphere's. We will install it as follows:

$ pip install awacs

We are now going to edit jenkins-cf-template.py.

The first two changes we will make are to the application name and port. Jenkins runs by default on TCP/8080:

ApplicationName = "jenkins" 
ApplicationPort = "8080" 

We also want to add an instance IAM profile to control better how our EC2 instance can interact with AWS services such as EC2. We previously used the IAM service in Chapter 2, Deploying Your First Web Application, when we created our user. You may recall that in addition to creating the user, we also assigned it the administrator policy which gives the user full access to all of AWS. On top of that, we generated an access key and secret access key which we are currently using to authenticate ourselves as that administrator user and to interact with services such as CloudFormation and EC2.

When you are using EC2 instances, the instance profile feature provided lets you specify an IAM role to your instance. In other words, we can assign IAM permissions directly to EC2 instances without having to use access keys and secret access keys.

Having an instance profile will be very useful in a later part of this chapter when we work on the CI pipeline and integrate our Jenkins instance with AWS managed services. To do so, we will first import some extra libraries. Below the first from troposphere import() section, add the following:

from troposphere.iam import ( 
    InstanceProfile, 
    PolicyType as IAMPolicy, 
    Role,  
) 
 
from awacs.aws import ( 
    Action, 
    Allow, 
    Policy, 
    Principal, 
    Statement, 
) 
 
from awacs.sts import AssumeRole 

Then, in between the instantiation of the variables ud and the creation of the instance, we are going to create and add our role resource to the template as shown next:

t.add_resource(Role(
    "Role",
    AssumeRolePolicyDocument=Policy(
        Statement=[
            Statement(
                Effect=Allow,
                Action=[AssumeRole],
                Principal=Principal("Service", ["ec2.amazonaws.com"])
            )
        ]
    )
))

Proceeding similarly to what we just did for the role, we can now create our instance profile and reference the role. Below the creation of our role, add the following:

t.add_resource(InstanceProfile( 
    "InstanceProfile", 
    Path="/", 
    Roles=[Ref("Role")] 
)) 

Finally, we can reference our new instance profile by updating the declaration of our instance. We will add a period after UserData=ud and on the line after initialize the IamInstanceProfile like so:

t.add_resource(ec2.Instance(
"instance",
ImageId="ami-a4c7edb2",
InstanceType="t2.micro",
SecurityGroups=[Ref("SecurityGroup")],
KeyName=Ref("KeyPair"),
UserData=ud,
IamInstanceProfile=Ref("InstanceProfile"),
))

The file should now look like this: http://bit.ly/2uDvyRi. You can save the changes, commit the new script to GitHub and generate the CloudFormation template:

$ git add jenkins-cf-template.py
$ git commit -m "Adding troposphere script to generate a Jenkins instance"
$ git push
$ python jenkins-cf-template.py > jenkins-cf.template
..................Content has been hidden....................

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