Setting custom puppet facts from within your Vagrantfile

You may want to set custom puppet facts in your development environment by specifying them in your Vagrantfile, so you can have a unique fact per developer or identify your own environment. Here’s a quick way to do that.

First: make sure you are running the latest version of facter (yum update facter), it should be at least version 1.7 as it supports custom facts easily (check with ‘facter –version’).

$ facter --version
1.7.1

Now, before the Vagrantfile changes, your facter facts will look like this. The solution is within the :shell provider, in the first few lines of the Vagrantfile.

$ facter | grep 'custom'
[empty]

Your Vagrantfile can now be modified to look like this, to set up custom facts.

Vagrant.configure("2") do |config|
  # First: run a shell provisioner to set up the custom facts
  config.vm.provision :shell do |shell|
    shell_cmd = ""

    # Make sure the facts directory exists
    shell_cmd << "mkdir -p /etc/facter/facts.d/; "

    # Add as much of these lins for any custom fact you want
    shell_cmd << "echo 'custom_fact1=the value of the fact' > /etc/facter/facts.d/custom_fact1.txt; "

    # Run the inline shell to create those facts
    shell.inline = "#{shell_cmd}"
  end

  # Then: run puppet like you normally would
  config.vm.provision :puppet do |puppet|
    puppet.manifests_path = "manifests"
    puppet.manifest_file = "my_manifest.pp"
  end
end

After a ‘vagrant provision’, your facts will be updated.

$ facter | grep custom
custom_fact1=the value of the fact

And you can now use the $::custom_fact1 variable within your manifests/modules.

Update 16/5: as Dieter De Meyer pointed out , there’s a more elegant solution using the puppet provider itself. The downside is the facts are only available if you use ‘vagrant provision’ to start a Puppet run, if you use Puppet from within the virtual machine, these facts won’t be present (see the Vagrant Helper Scripts for Puppet to speed up your Puppet deployments).

Vagrant.configure("2") do |config|
  config.vm.define :test do |vmconfig|
    vmconfig.vm.provision :puppet do |puppet|
      puppet.manifests_path = "manifests"
      puppet.manifest_file = "test.pp"
      puppet.module_path = [ "../", "./modules" ]
      puppet.facter = {
        "custom_fact1" => "value1",
        "custom_fact2" => "value2"
      }
      puppet.options = "--verbose"
    end
  end
end

Thanks!