Sunday, April 20, 2014

Give context to your Puppet Manifests files using Vagrant

I am using Vagrant & Puppet at work and outside to develop deployment stuff (Puppet modules, native packages builders thanks to FPM).

Vagrant allows you to develop and
test your deployment process
Gitolite was the Git repository I installed at work to begin to share infrastructure code with my co-workers or directly with the infrastructure (a PuppetMaster for the time being).

Lately, in order to scale up our git practice, I installed the excellent Gitbucket to replace our  Gitolite server. 

Aside note: If you don't know Gitbucket and are interested by an internal Git server à la GitHub Enterprise (or à la GitLab), give it a try. It is free, and it is very - very easy to install (a war to drop). Lasts versions support SSH access on non privileged port (this was not the case initially, only http was supported).

Thanks to Gitbucket and it's friendly UI, I started to gitify also my Vagrant environments, and the manifests files accompanying them (it is a very convenient way to share ready to run Vagrant environments). 

My problem was the following: I must use a proxy at work, but not when I work outside. How could I pass this information (use a proxy or not) to the Puppet manifest running on to the guests VM I am provisioning with Vagrant, without having to modify the (now gitted) code of the manifest (a code which must be independent of the current location where I am working - office or outside) ?

I had a good solution right under my eyes since I started to use Vagrant, but I guess I was not yet "ready" to see it ...

In a Vagrantfile, it is possible to add custom facts to the Puppet provisioning system, and thereby to pass context information to the Puppet manifest that is executed within the guests VM.

Example 

config.vm.provision :puppet do |puppet|
        puppet.manifests_path = "manifests"
        puppet.module_path = "/path_to_git_extraction/modules"
        puppet.manifest_file  = "init.pp"
        puppet.facter = {
                "within_my_company_network" => `hostname`.chop.end_with?("acme.com")
        }
end

Then it is very easy to test this fact in the Puppet manifests file to provision or not the proxy:

if ($::within_my_company_network == 'true') {
        opensuse-tools::set-proxy { "proxy":
                proxy_host => "proxy.acme.com",
                proxy_port => "8080",
                no_proxy_domains => ".local, .acme.com",
        }
}