Cookbook Testing using Vagrant

There came a time in our team where we started churning out cookbooks by the hour. Now the question that needed to be answered was - How does one QA a chef cookbook. We could either have had one team member solely responsible for writing out rspecs and testing the cookbooks on a virtual environment, but what happens when the only team members who can be used to perform the above task as busy creating the cookbooks themselves. We needed a faster and smoother answer. In came Vagrant.

Well Vagrant does everything that one would need to do to set up a virtual environment without wasting time in installations, snapshots, teardowns etc.

Vagrant gives us one file "Vagrantfile" that needs to be configured with the environment that needs to be set and voila! everything works like you want it to. The standard (read easiest) way to use vagrant is as below.
Create a directory where you want to store all your vagrant data, I call it vagrant. Then download the boxes that you need in your test environment. The box packages are available at http://vagrantbox.es/. One would wonder what exactly is a box. "Vagrant doesn’t create a virtual machine instance completely from scratch. Instead, it imports a base image (read .box files) for a VM and builds off of that. This simplifies things greatly for Vagrant users since they don’t have to spend time specifying tedious details such as memory capacity, hard disk capacity, network controllers, etc, and also allows customize-able bases to build projects from." (Source http://vagrantup.com/docs/getting-started/)

Now run the "vagrant init" command in the vagrant directory.

mkdir vagrant
vagrant init
This command would create the Vagrantfile. The file by default sets up a single VM environment. A box can be added as below
vagrant box add centos57 http://dl.dropbox.com/u/8072848/centos-5.7-x86_64.box
But when you have a production environment where you have all versions of operating systems you would want to set up a testing environment that would test cookbooks on all images of the production set-up. Customize the Vagrantfile as below:
test_vms = {
  :centos55 => {
    :hostname => "centos55",
    :ipaddress => "x.x.x.x",
    :run_list => "recipe[cookbook_1],recipe[cookbook_2]"
  },
  :centos57 => {
    :hostname => "centos57",
    :ipaddress => "x.x.x.x",
    :run_list => "recipe[cookbook_1],recipe[cookbook_2]"
  },
  :centos6 => {
    :hostname => "centos6",
    :ipaddress => "x.x.x.x",
    :run_list => "recipe[cookbook_1],recipe[cookbook_2]"
  }
}
Vagrant::Config.run do |global_config|
  test_vms.each_pair do |name, setup|
    global_config.vm.define name do |config|
      config.vm.share_folder("v-root", "/vagrant", ".", :disabled => true)
      config.vm.box = name.to_s
      config.vm.boot_mode = :headless
      config.vm.host_name = name
      config.vm.network :bridged, setup[:ipaddress]
      config.vm.provision :chef_solo do |chef|
        chef.cookbooks_path = "cookbooks" #path relative to the location of Vagrantfile 
        chef.node_name = name
        chef.log_level = :info
        chef.run_list = options[:run_list].split(",").flatten
      end
    end
  end
end
Now there are two types of adapters that can be used to setup config.vm.network :bridged and :hostonly. Using :bridged adapter the vms would be able to talk to each other and using :hostonly they would behave as individual vms on separate networks.

Another part that one would need to keep in mind while testing in a self contained cloud environment would be that if there are cookbooks that try to access a web server / yum repo server / gem server in the same environment that it would be essential that there be a cookbook that stops the iptables is the first to run in the run_list each time.

Now, just run vagrant up and all the vms would be provisioned as configured in the Vagrantfile. While we are at it also remember that that vagrant up would try to recreate the entire environment each time the command is run. So, say you hit an error in a cookbook you ran. You change the cookbook but you don't want to rebuild the entire environment again, run the command vagrant provision <vm_name>. This command would only re-provision the mentioned vm.

Coming to teardown. The easiest way to teardown a vagrant environment is running the command is
vagrant destroy -f
This would forcefully destroy all the vms created by the vagrant up command.

For more information on vagrant refer http://vagrantup.com/docs/getting-started

Comments

Popular posts from this blog

To DR or Not To DR

High Availability NAT for AWS VPC with Multiple Private Subnets.

Load Balancer with SSL offloading - nginx + HAProxy