Tagged: vagrant

Puppet Module Development with Vagrant

By way of background, I recently switched employers, and in that change, made the switch from Puppet to Chef at work. In doing so, I’ve become a big fan of a Vagrant-driven development workflow. However, on my own time, I still hack around with Puppet – and find myself wanting to use a similar development process when writing modules as opposed to cookbooks.

As far as my searching could could turn up, most of the documentation out on the web pertaining to using Puppet and Vagrant together is about using the Vagrant Puppet provisioner to set up an application development environment, not for using Vagrant to actively test Puppet modules during their development. This was momentarily frustrating to me, but the configuration I came up with to do this is pretty simple. My solution? Use a slightly non-standard module directory layout, add an additional “vagrant.pp” file, and include this in your Vagrantfile:

  config.vm.provision :puppet do |puppet|
    puppet.manifests_path = 'vagrant'
    puppet.manifest_file = 'vagrant.pp'
    puppet.module_path = '../'
  end

The Puppet module directory layout looks like this:

module/
├── Gemfile
├── Gemfile.lock
├── Modulefile
├── README
├── Vagrantfile
├── manifests
│   └── init.pp
├── spec
│   └── spec_helper.rb
├── tests
│   └── init.pp
└── vagrant
    └── vagrant.pp

In particular, in addition to the Vagrantfile, note the “vagrant” directory and the “vagrant.pp” file contained within it; said “vagrant.pp” file is short and sweet:

# Include this module
include <module>

(Where “<module>” is replaced with the actual module name.)

Finally, note that your development directory name must match the class name – otherwise the Puppet provisioner will be unable to find the included class. So, if you namespace your Puppet modules on GitHub with a leading “puppet-” or something similar, you’ll need to rename your development directory.

This layout does conflict with the Puppet module layout specification (by adding additional files/directories), although I haven’t yet noticed any ill effects. I expect – and hope – that test-kitchen for Puppet will render this blog post obsolete in the near future.

Edit 9/28/2013, 10/1/2013: If you are running a somewhat dated Vagrant box, you may find that “package” resources fail, ultimately with an error similar to the following:

E: Unable to fetch some archives, maybe run apt-get update or try with --fix-missing?

If updating your box isn’t an immediate option, you can work around this on Ubuntu by adding the following to your Vagrantfile before the Puppet provisioner block:

config.vm.provision :shell, :inline => '/usr/bin/apt-get update'

To avoid running this every time, you can wrap it in a test for an environment variable:

unless ENV['NO_VAGRANT_APTGET']
  config.vm.provision :shell, :inline => '/usr/bin/apt-get update'
end

and then run “vagrant provision” as follows:

NO_VAGRANT_APTGET=1 vagrant provision