Inline Puppet Manifest with Vagrant

I’m a huge fan of Vagrant, it allows me to quickly test applications and proposed architectures with minimal fuss and, with a provisioner, in a way that’s reproducible for myself and others.

Vagrant supports many provisioners, but I tend to stick with shell and Puppet. Shell provides a nice quick way of hacking together something that Just Works™, but it’s hard to get shell to be robust and idempotent which is why I prefer Puppet.

Sadly Vagrant doesn’t provide a way to supply an inline manifest like it does with the shell provisioner. This means that for simple environments you have to create/specify a location for the manifest file or have it within the root of the project.

If you’re looking for a quick way to get a simple inline Puppet manifest in Vagrant, here’s a simple (albeit Fugly) way to do this.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
$manifest = <<PUPPET

    Exec {
        path => ['/usr/bin', '/bin', '/usr/sbin', '/sbin', '/usr/local/bin', '/usr/local/sbin']
    }

    exec { 'apt-get update':
        command => 'apt-get -qq -y update --fix-missing',
        unless  => 'grep -F `date +"%y-%m-%d"` /var/log/apt/history.log'
    }

    package { 'build-essential':
        ensure  => present,
        name    => 'build-essential',
        require => Exec['apt-get update']
    }

PUPPET

def inline_puppet(manifest)
	require 'base64'
	"TMPFILE=$(mktemp); echo '#{Base64.strict_encode64(manifest)}' | base64 --decode > $TMPFILE; puppet apply -v $TMPFILE"
end

Vagrant.configure("2") do |config|
    config.vm.box = "ubuntu/trusty64"
    config.vm.provision :shell, :inline => inline_puppet($manifest)
end

Let me walk you though what happens.

We create a variable in the Vagrantfile to hold the Puppet manifest, and then define a function called inline_puppet, we then use this function to create a shell command that:-

  1. Base64 encodes the content of $manifest using the Base64 module in Ruby so we don’t have to worry about escaping it for the shell
  2. Uses base64 to decode the encoded manifest
  3. Writes the decoded content to a temporary file, using mktemp, within the Vagrant box
  4. Instructs Puppet to apply the manifest to the Vagrant box

We then use the built-in inline shell functionality of Vagrant to execute this shell command.

It’s not great, but it’s a simple way to have a standalone Vagrantfile with Puppet functionality.

This post was tagged with:
← Back