Deploying changes with Rake
Rake is a useful tool from the Ruby world which you can use to help automate your Puppet workflow. Although there are lots of other ways to run commands on remote servers, this happens to be the one I use, and it's easily extensible to whatever you need it to do.
The first helpful thing we can have Rake perform for us is log into the remote machine and run the pull-updates
script to apply any new Puppet manifest changes. This is fairly simple to do, as you'll see in the following sections.
Getting ready
You may already have Rake installed (try running rake
), but if not, here's how to install it:
Run the following command:
sudo apt-get install rake
How to do it...
Perform the following steps:
In your Puppet repo, create the file,
Rakefile
with the following contents. Replacessh...
with the correctssh
command line for you to log into your server:SSH = 'ssh -A -i ~/git/bitfield/bitfield.pem -l ubuntu' desc "Run Puppet on ENV['CLIENT']" task :apply do client = ENV['CLIENT'] sh "git push" sh "#{SSH} #{client} pull-updates" end
Add, commit, and push the change to the Git repo:
ubuntu@cookbook:~/puppet$ git add Rakefile ubuntu@cookbook:~/puppet$ git commit -m "adding Rakefile" [master 63bb0c1] adding Rakefile 1 file changed, 8 insertions(+) create mode 100644 Rakefile ubuntu@cookbook:~/puppet$ git push Counting objects: 31, done. Compressing objects: 100% (22/22), done. Writing objects: 100% (28/28), 4.67 KiB, done. Total 28 (delta 1), reused 0 (delta 0) To git@github.com:bitfield/cookbook.git a063a5b..63bb0c1 master -> master
On your own computer, check out a working copy of the Puppet repo, if you haven't already got one (replace the Git URL with the URL to your own repo):
[john@Susie:~/git]$ git clone git@github.com:bitfield/cookbook.git Cloning into 'cookbook'... remote: Counting objects: 36, done. remote: Compressing objects: 100% (26/26), done. remote: Total 36 (delta 1), reused 33 (delta 1) Receiving objects: 100% (36/36), 5.28 KiB, done. Resolving deltas: 100% (1/1), done.
Run the following command, replacing
cookbook
with the address of your server:[john@Susie:~/git]$ cd cookbook [john@Susie:~/git/cookbook(master)]$ rake CLIENT= cookbook apply (in /Users/john/git/cookbook) git push Everything up-to-date ssh -A -i ~/git/bitfield/bitfield.pem -l ubuntu cookbook pull-updates Already up-to-date. Notice: Finished catalog run in 0.18 seconds Connection to cookbook closed.
How it works...
What you'd do manually to update your server is log into it using SSH, and then run pull-updates
. The Rakefile simply automates this for you. First, we set up the correct SSH command line:
SSH = 'ssh -A -i ~/git/bitfield/bitfield.pem -l ubuntu'
The arguments to ssh
are as follows:
-A
: Forward your SSH key to the remote server, so that you can use it for further authentication-i KEYFILE
: Set the SSH private key to use (in this case, it's the Amazon AWS keyfile that I'm using. You may not need this argument if you're already set up for SSH access to the server with your default key.)-l ubuntu
: Log in as userubuntu
(the standard arrangement on EC2 servers; you may not need this argument if you log into servers using the same username as on your local machine.)
We then define a Rake task named apply
:
desc "Run Puppet on ENV['CLIENT']" task :apply do end
The desc
is just a helpful description, which you'll see if you run the command, rake -T
, which lists available tasks:
$ rake –T (in /Users/john/git/cookbook) rake apply # Run puppet on ENV['CLIENT']
The code between task
and end
will be run when you run rake apply
. Here's what it does:
client = ENV['CLIENT']
This captures the value of the CLIENT
environment variable, which tells the script the address of the remote servers to connect to.
The next line is as follows:
sh "git push"
sh
simply runs a command in your local shell, in this case to make sure any changes to the Puppet repo have been pushed to GitHub. If they weren't, they wouldn't be picked up on the remote machine.
sh "#{SSH} #{client} pull-updates"
This is the line which actually connects to the client, using the ssh
command line we defined at the start of the script, and the client address. Having logged in, it will then run the pull-updates
command as the remote user.
Since we already set up the pull-updates
script to do everything necessary to get the latest changes from GitHub and apply Puppet, that's all we need to do.
There's more...
You can now make and apply Puppet changes to your remote servers without ever explicitly logging into them. Once you've installed Puppet on a machine, checked out a copy of the manifest repo, and run Puppet for the first time, you can then do all the administration for that machine remotely.
If you're as lazy as I am, you're already asking, "Couldn't we use a Rake task to do the initial Puppet install and checkout, as well as just applying changes?"
We certainly can, and we'll see how to do that in the next section.