Kristian Glass - Do I Smell Burning?

Upgrading Puppet in Vagrant Boxes

I’ve finally found the time to sit down and start using Vagrant for Real Things. For the unaware, Vagrant is essentially a tool for managing development VMs - excellent for such things as managing a local development environment, or developing and testing Chef/Puppet configuration. For more detail see the excellent set of slides by Vagrant author Mitchell Hashimoto - Develop and Test Configuration Management Scripts with Vagrant.

Something I swiftly ran into was that I have several manifests written for Puppet 3. Among things introduced since Puppet 2.7 are the addition of unless as a synonym for if ! to the DSL, and the introduction of Hiera as a “first class citizen”.

So, I want to use Puppet 3, but I really don’t want to have to go and rebuild existing Vagrant boxes. I have Puppet modules for ensuring that I’m running the latest stable Puppet, but that’s not going to work when the existing install can’t parse said modules.

It turns out you can have multiple Provisioners in Vagrant. So, while in general Puppet (or Chef if you’re of that persuasion) is The Right Way to provision things, we can add a Shell provisioner to run before the Puppet provisioner and ensure the VM is running Puppet 3.

upgrade-puppet.sh

Note: Everything I’m doing at the moment is Ubuntu-based; this script is Debian/Ubuntu specific, but should be fairly trivial to adapt to the (supported) distro of your choosing

PuppetLabs provides packages to enable their apt repositories for Debian and Ubuntu, so it’s a simple matter of extracting the OS code name (helpfully provided by /etc/lsb-release as $DISTRIB_CODENAME Update: This doesn’t work for Debian; better to use lsb_release --codename --short after installing the lsb-release package providing it) and using that to fetch and install the right package, before updating the package indexes and upgrading Puppet:

#!/bin/bash

apt-get install --yes lsb-release
DISTRIB_CODENAME=$(lsb_release --codename --short)
DEB="puppetlabs-release-${DISTRIB_CODENAME}.deb"
DEB_PROVIDES="/etc/apt/sources.list.d/puppetlabs.list" # Assume that this file's existence means we have the Puppet Labs repo added

if [ ! -e $DEB_PROVIDES ]
then
    # Print statement useful for debugging, but automated runs of this will interpret any output as an error
    # print "Could not find $DEB_PROVIDES - fetching and installing $DEB"
    wget -q http://apt.puppetlabs.com/$DEB
    sudo dpkg -i $DEB
fi
sudo apt-get update
sudo apt-get install --yes puppet

With that in place, all that remains is to get Vagrant to use it as a shell provisioner. Just drop the below line into your Vagrantfile, somewhere before your Puppet provisioner:

config.vm.provision :shell, :path => "upgrade_puppet.sh"

Puppet 3 Provisioner

Once I’d upgraded to Puppet 3, I noticed a few warnings appear across my boxes. Naturally, I wanted to squash these

FQDN

Warning: Could not retrieve fact fqdn

Something (I haven’t quite established what) was checking the fqdn fact. All the boxes I use seem not to set an FQDN, for example:

$ hostname -f
precise32

It’s a simple matter of setting config.vm.host_name to a valid FQDN, for example:

config.vm.hostname = "vagrant.example.com"

(If you’re using Vagrant v1 configuration, you’ll want config.vm.host_name (note the underscore))

Hiera

Warning: Config file /etc/puppet/hiera.yaml not found, using Hiera defaults

Puppet 3 now has Hiera built in, and while its default configuration seems fairly sane and reasonable, it still regards lack of an explicit configuration file as warning-worthy. So, use options to explicitly set Puppet’s hiera_config option, for example:

config.vm.provision :puppet do |puppet|
    puppet.manifests_path = "manifests"
    puppet.manifest_file  = "base.pp"
    puppet.module_path = "modules"
    puppet.options = "--hiera_config /vagrant/hiera.yaml"
end

Conclusion

Sure, perhaps you’re better off building a new base box, but if you’re not ready to do that, this should hopefully come in useful!