Instantly share code, notes, and snippets.

Embed
What would you like to do?
An example of how to write Vagrantfiles following the DRY principle.
=begin
Example box JSON schema
{
    :name => :name_of_vagrant_box, #REQUIRED
    :ip => '10.0.0.11', #REQUIRED
    :synced_folders => [
        { '.' => '/home/vagrant/myapp' }
    ],
    :commands => [
        'touch /tmp/myfile'
    ],
    :vbox_config => [
        { '--memory' => '1536' }
    ],
    :chef_role => 'myrole',
    :chef_json => {
        'local' => true,
        'env_name' => 'development',
    }
}  
=end

boxes = [
    # Clean box, Ubuntu 12.04 LTS - for experimentation
    { 
        :name => :clean, 
        :ip => '33.33.33.80'
    },
    # MongoDB box, with Chef 'mongo' role
    { 
        :name => :mongo,
        :ip => '33.33.33.81',
        :chef_role => 'mongo'
    },
    # Jenkins master box, with Chef 'jenkins' role
    { 
        :name => :jenkins,
        :ip => '33.33.33.82',
        :vbox_config => [
            { '--memory' => '1536' }
        ],
        :chef_role => 'jenkins',
        :chef_json => {
            'jenkins' => {
                'server' => {
                    'user' => 'jenkins'
                }
            }
        }
    }
]

# Chef JSON config for all boxes
chef_json = {
    "local" => true,
    "env_name" => "development",
    "s3cmd" => {
        "user" => "vagrant"
    },
    "chef_client" => {
        "cron" => {
            "hour" => "4",
            "minute" => "0"
        }
    }
}

Vagrant.configure("2") do |config|
    boxes.each do |opts|
        config.vm.define opts[:name] do |config|
            # Box basics
            config.vm.box = "precise64"
            config.vm.box_url = "http://files.vagrantup.com/precise64.box"
            config.vm.network :private_network, ip: opts[:ip]
            config.ssh.forward_agent = true

            # Synced folders
            opts[:synced_folders].each do |hash|
                hash.each do |folder1, folder2|
                    config.vm.synced_folder folder1, folder2
                end
            end

            # VirtualBox customizations
            unless opts[:vbox_config].nil?
                config.vm.provider :virtualbox do |vb|
                    opts[:vbox_config].each do |hash|
                        hash.each do |key, value|
                            vb.customize ['modifyvm', :id, key, value]
                        end
                    end
                end
            end

            # Use a more recent version of Chef
            config.vm.provision :shell, :inline => "gem install chef --version 11.6.0 --no-rdoc --no-ri --conservative"
            
            # Run shell commands for box
            opts[:commands].each do |command|
                config.vm.provision :shell, :inline => command    
            end

            # Configure the box with Chef
            config.vm.provision :chef_solo do |chef|
                # Set paths to local Chef resources
                chef.provisioning_path = "/etc/chef"
                chef.cookbooks_path = ["../chef/cookbooks", "../chef/vendor/cookbooks"]
                chef.roles_path = "../chef/roles"

                # Add a Chef role if specified
                unless opts[:chef_role].nil?
                    chef.add_role(opts[:chef_role])   
                end

                # Merge the general Chef JSON with box-specific JSON
                chef.json = chef_json.merge(opts[:chef_json])
            end    
        end
    end
end
@brettswift

This comment has been minimized.

brettswift commented Jan 17, 2014

Thanks for this - I've been trying to get the "Vagrant.configure("2") " section into a "Base" file.. and then have multiple "Vagrantfiles" with just the "boxes" variable declared in them, and a load "../BaseVagrantfile" at the top. I can't seem to get this to work though.

desired folder structure:

./BaseVagrantfile
./project1/Vagrantfile
./project2/Vagrantfile

so each project can run their own project file with only simplified "boxes" variables declared.

Think that could work somehow?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment