Puppet+Capistrano

I'm currently working on our upgrade to Puppet 2.6. One of the ideas I came up with was to deploy our puppet manifests (which we already store in a GIT repository) using Capistrano.

For those who don't know Capistrano already: Capistrano is a Ruby based deployment tool, used to get application code from a source control system to your application servers. Initially Capistrano was written to deploy Ruby on Rails applications. Meanwhile they also provide a 'railsless-deploy' module, which can be used to deploy any other code or framework.

What I like most about Capistrano, is that you don't have to install it on your servers. It's designed to read a couple of instructions from a "Capfile" which resides in the top directory of your application code. Once you trigger the deployment of a release, it will connect to your servers using SSH and trigger commands to deploy your Puppet manifests.

Important for all of this to work propperly is a SSH setup which uses public keys for authentication.

ssh process

Capistrano will connect to the Puppet master and issue GIT commands against your GIT server. So not only password-less authentication to the puppet server must work, but also connecting from a shell on the Puppet server to the GIT server.

Installation

Capistrano is distrubuted as a ruby gem. If your distribution does already provide a package, use it. Otherwise you can simply use rubygems.

  gem install capistrano

Capify

Next up copy the Capfile below, to your Puppet top level directory. Here is how it should look like:

  -rw-r--r--   1 sts sts  1499 Nov 26 10:33 Capfile
  -rw-r--r--   1 sts sts  1464 Nov  9 20:02 README
  -rw-r--r--   1 sts sts   907 Nov  9 20:04 TODO
  drwxr-xr-x   6 sts sts   204 Nov  9 20:02 manifests
  drwxr-xr-x  42 sts sts  1428 Nov 22 11:04 modules

There are some variables you need to change in order to make it work with your setup. Basically look through all lines which start with "set" and ajust them according to your needs.

Basically Capistrano is going to do the following:

require 'railsless-deploy'
require 'net/smtp'

set :application,     "puppet"
set :user,            "root"
set :use_sudo,        true
set :group_writebale, false
set :deploy_to,       "/etc/puppet/git/#{:branch}"
set :keep_releases,   2

set :scm,         "git"
set :repository,  "git+ssh://[email protected]/srv/git/#{application}.git"
set :branch,      "master"

role :app, "puppet.ono.at"

namespace :deploy do

    task :default do
        update
        cleanup
    end

    task :notify do
        changes_list = "[email protected]"
        user_name    = `git config user.name`.strip
        user_email   = `git config user.email`.strip
        commits      = `git log --pretty=oneline --abbrev-commit #{previous_revision}..#{current_revision}`.strip

        msg          = 
To: #{changes_list}
Subject: [puppet] deployed #{release_name}.

The following changes where just pushed to puppet by #{user_name}:

  Branch  : #{:branch}
  Release : #{release}
  Server  : #{:app}

Applied Commits /////////////////////////////////////////////// ///////

#{commits}

If you want to revert this release, please run:

 $ cap deploy:rollback

Cheers,
Capistrano.
EOM

        Net::SMTP.start('localhost') do |smtp|
             smtp.send_message msg, user_email, changes_list
        end
    end

    dec "Restart Puppetmaster"
    task :restart, :roles => :app do
        run "touch /usr/share/puppet/rack/puppetmasterd/tmp/restart.txt"
    end
end

Go

You should be able to deploy updates to your Puppet servers using the following command:

  cap deploy

Future enhancements

If you've got any ideas or see a way to enhance this process, I'd be glad if you leave me a comment. :-)

read more

Comments