Developing Chef cookbooks requires you to run your work in progress cookbooks multiple times on your nodes. To make sure they work, you need a clean, initial state of your nodes every time you run them. You can achieve this by using a virtual machine (VM). However, manually setting up and destroying VMs is tedious and breaks your development flow.
Vagrant is a command-line tool, which provides you with a configurable, reproducible, and portable development environment by enabling you to manage VMs. It lets you define and use preconfigured disk images to create new VMs from. Also, you can configure Vagrant to use provisioners such as Shell scripts, Puppet, or Chef to bring your VM into the desired state.
In this recipe, we will see how to use Vagrant to manage VMs using VirtualBox and Chef client as the provisioner.
Download and install VirtualBox at https://www.virtualbox.org/wiki/Downloads.
Download and install Vagrant at https://www.vagrantup.com/downloads.html.
Install the Omnibus Vagrant plugin to enable Vagrant to install the Chef client on your VM by running the following command:
mma@laptop:~/chef-repo $ vagrant plugin install vagrant-omnibus Installing the 'vagrant-omnibus' plugin. This can take a few minutes... Installed the plugin 'vagrant-omnibus (1.4.1)'!
Let's create and boot a virtual node by using Vagrant:
Visit https://github.com/opscode/bento and choose a Vagrant box to base your VMs on. We'll use
opscode-ubuntu-14.10in this example.
The URL of the
opscode-ubuntu-14.10box is https://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_ubuntu-14.10_chef-provisionerless.box.
Edit your new
Vagrantfile. Make sure that you replace
<YOUR-ORG>with the name of your organization on the Chef server. Use the name and URL of the box file you noted down in the first step as
mma@laptop:~/chef-repo $ subl Vagrantfile
Vagrant.configure("2") do |config| config.vm.box = "opscode-ubuntu-14.10" config.vm.box_url = "https://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_ubuntu-14.10_chef-provisionerless.box" config.omnibus.chef_version = :latest config.vm.provision :chef_client do |chef| chef.provisioning_path = "/etc/chef" chef.chef_server_url = "https://api.chef.io/organizations/<YOUR_ORG>" chef.validation_key_path = ".chef/<YOUR_ORG>-validator.pem" chef.validation_client_name = "<YOUR_ORG>-validator" chef.node_name = "server" end end
mma@laptop:~/chef-repo $ vagrant up
Bringing machine 'server' up with 'virtualbox' provider... ...TRUNCATED OUTPUT... ==> default: Importing base box 'opscode-ubuntu-14.10'... ...TRUNCATED OUTPUT... ==> default: Installing Chef 11.16.4 Omnibus package... ...TRUNCATED OUTPUT... ==> default: Running provisioner: chef_client... ==> default: Creating folder to hold client key... ==> default: Uploading chef client validation key... Generating chef JSON and uploading... ==> default: Running chef-client... ==> default: [2014-12-01T22:00:54+00:00] INFO: *** Chef 11.16.4 *** ...TRUNCATED OUTPUT...
Log in to your virtual node using SSH:
mma@laptop:~/chef-repo $ vagrant ssh
Welcome to Ubuntu 14.10 (GNU/Linux 3.16.0-23-generic x86_64) * Documentation: https://help.ubuntu.com/ Last login: Mon Oct 27 02:22:37 2014 from 10.0.2.2 vagrant@server:~$
Log out of your virtual node:
vagrant@server:~$ exit mma@laptop:~/chef-repo $
Validate that the Chef server knows your new virtual machine as a client called server:
mma@laptop:~/chef-repo $ knife client list
Go to https://manage.chef.io/organizations/<YOUR ORGANIZATION>/nodes and validate that your new virtual machine shows up as a registered node:
First, we create a
config object. Vagrant will use this
config object to configure the VM:
Vagrant.configure("2") do |config| end
config block, we tell Vagrant which VM image to use, in order to boot the node:
config.vm.box = "opscode-ubuntu-14.10" config.vm.box_url = "https://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_ubuntu-14.10_chef-provisionerless.box"
We want to boot our VM using a so-called Bento Box, provided by Chef. We use Ubuntu Version 14.10 here.
If you have never used the box before, Vagrant will download the image file (a few hundred megabytes) when you run
vagrant up for the first time.
config.omnibus.chef_version = :latest
After selecting the VM image to boot, we configure how to provision the box by using Chef. The Chef configuration happens in a nested Ruby block:
config.vm.provision :chef_client do |chef| ... end
Inside this Chef block, we need to instruct Vagrant on how to hook up our virtual node to the Chef server. First, we need to tell Vagrant where to store all the Chef stuff on your node:
chef.provisioning_path = "/etc/chef"
Vagrant needs to know the API endpoint of your Chef server. If you use hosted Chef, it is
https://api.chef.io/organizations/<YOUR_ORG>. You need to replace
<YOUR_ORG> with the name of the organization that you created in your account on hosted Chef. If you are using your own Chef server, change the URL accordingly:
chef.chef_server_url = "https://api.chef.io/organizations/<YOUR_ORG>"
While creating your organization on hosted Chef, you must download your private key. Tell Vagrant where to find this file:
chef.validation_key_path = ".chef/<YOUR_ORG>—validator.pem"
Also, you need to tell Vagrant as to which client it should validate itself against the Chef server:
chef.validation_client_name = "<YOUR_ORG>-validator"
Finally, you should tell Vagrant how to name your node:
chef.node_name = "server"
After configuring your
Vagrantfile, all you need to do is run the basic Vagrant commands such as
vagrant provision, and
vagrant ssh. To stop your VM, just run the
vagrant halt command.
mma@laptop:~/chef-repo $ vagrant destroy mma@laptop:~/chef-repo $ knife node delete server -y && knife client delete server -y
Alternatively, you may use the Vagrant Butcher plugin found at https://github.com/cassianoleal/vagrant-butcher.
Find the Vagrant documentation at http://docs.vagrantup.com/v2/getting-started/index.html
You can use a Vagrant plugin for VMware instead of VirtualBox and find it at http://www.vagrantup.com/vmware
You can use a Vagrant plugin for Amazon AWS instead of VirtualBox and find the same at https://github.com/mitchellh/vagrant-aws