Dissecting the Vagrantfile

It’s been over a month since my last post. Not good. In the interim, Vagrant has gone from 1.5.1 to 1.5.4, so you may want to update that. Ubuntu 14.04 also came out; we’ll use that to go through how to build a base box some time soon. Vagrant cloud I think also might allow hosting boxes now. So, lots of changes, but apart from heartbleed nothing too earth-shattering(well I guess systemd adoption and such might qualify).

I remember the Vagrant documentation not being the most intuitive thing in the world so today I’m going to dissect the Vagrantfile you downloaded for the previous post and link you in to the official docs + provide an explanation where appropriate.

Machines and Top-Level Objects

First up at the top of the file under the editor / interpreter stuff is the configuration version(See vagrant documentation). This is actually remarkably static.


VAGRANTFILE_API_VERSION = "2"

This would also be where you change the provider(See vagrant documentation), although we’re happy to not set anything and use the default, which is Virtualbox.

Following that is what you should think of as a global scope, because, well, it is. If you ever do a clean vagrant init or desire a single machine configuration this is all that’s set up and/or pretty much all you need.


Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
...
end

You’ll note that the Vagrantfile from before doesn’t leave it at that; within the top config I set up several machines:


Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  config.vm.define "puppet" do |puppetmaster|
  ...
  end

  config.vm.define "centos" do |centos|
  ...
  end

  config.vm.define "ubuntu" do |ubuntu|
  ...
  end
end

Which sets up the vms puppet, centos, and ubuntu(Vagrant calls this a multi-machine configuration, each vm has it’s own config.vm namespace), but doesn’t actually configure them. Which brings us to….

Configuration

Defining the machines by themselves does nothing particularly useful. We need to actually configure them; tell vagrant what they should be.

The base box

Basic information on base boxes is provided in the vagrant documentation here, with more specific information here. Configuration parameters specifics for boxes are outlined in the config.vm namespace document referenced earlier. Just look for anything box.

The box configuration for one of the VMS defined previously follows:


Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
 config.vm.define "centos" do |centos|
    centos.vm.box = "example-CentOS6.5"
    centos.vm.box_url = "./boxes/centos.box",
      "http://puppet-vagrant-boxes.puppetlabs.com/centos-65-x64-virtualbox-puppet.box"
  end
end

This causes the centos vm to use the example-CentOS6.5 base box(as seen with a vagrant box list). If that base box has not already been added, it will first attempt to retrieve it at the relative path ./boxes/centos.box. If that fails, it follows up with the puppet URL.

Synced folders

Synced or shared folders are host OS folders that are mapped and mounted into the guest OS. They are defined via vm.synced_folder and documented by Vagrant here.

Globally they’re defined with the top config block(as below).


Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  config.vm.synced_folder "", "/vagrant", disabled: true
end

The above is actually turning off the default synced folder, so we’ll use a different example:


Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  config.vm.define "puppet" do |puppetmaster|
    puppetmaster.vm.synced_folder "puppet/ssl/puppetmaster",
      "/var/lib/puppet/ssl",
        owner: "puppet",
        group: "puppet"
  end
end

This mounts the relative(to the Vagrantfile) path puppet/ssl/puppetmaster via mount.vboxfs within the guest at /var/lib/puppet/ssl. The owner of the directory will be puppet and the group will also be puppet.

Synced folders are global and shared(or disabled) across all machines if within the main(config) block. If within a machine block they are local to an individual machine. A shared folder within a local machine will(as of 1.5.4) override a global one if the mount points conflict. This behavior is not shared by….

Provisioning

The vagrant documentation overview of provisioning is available here, more detailed documentation here, and documentation specific to the :puppet provisioner here.

Like synced folders, provisioning can be global or local. Unlike synced folders, provisioning is additive.

So within the top scope we set a modules and manifests path in order to apply a universal config:


Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  config.vm.provision :puppet do |puppet|
    puppet.module_path = "./puppet/modules"
    puppet.manifests_path = "./puppet/manifests"
  end
end

These will actually be mounted as synced folders within /tmp(generally within the format /tmp/vagrant-puppet-$x/$dir) which will be passed as arguments to a local puppet run. As no manifest is specified it will use default.pp (which is the puppet behavior).

Within each machine another set of provisioning config applies a specific manifest to the vm. In the following example puppetmaster.pp:

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  config.vm.define "puppet" do |puppetmaster|
    puppetmaster.vm.provision :puppet do |puppet|
      puppet.manifest_file = "puppetmaster.pp"
      puppet.module_path = "./puppet/modules"
      puppet.manifests_path = "./puppet/manifests"
    end
  end
end

This is functionally identical to setting these up as synced folders, logging into to the machine and manually running puppet twice. Obvious caveats here are that puppet needs to be installed, virtualbox guest additions(and thus synced folders) need to be installed and working, and vagrant has to be able to remote in.

Networking

The basic overview is here. the specific launch point is here, and the details of private networking can be found here

To emulate a puppet master / agent environment we need to set up networking. We do that as follows:


config.vm.define "centos" do |centos|
  centos.vm.hostname = "centos6.example.com"
  centos.vm.network "private_network",
    ip: "203.0.113.3",
    virtualbox__intnet: "example"
end

This sets the machine hostname to centos6.example.com and sets up a secondary interface with ip 203.0.113.3 within a virtualbox internal network called example. Not really much to go into here.

Final Thoughts

That's it, we're done. Not really all that much to it was there?

Leave a Reply

Your email address will not be published. Required fields are marked *