Home

Tips and tricks for chef-solo and vagrant

In your daily work at the kitchen sink :wink:, sometimes you have to be a plumber and get dirty. In order to do that you have to be familiar with the concept of debugging vagrant, chef-solo and some other useful tricks.

Debugging vagrant

If you want to enable a verbose mode for vagrant, you need to set the environment variable VAGRANT_LOG to DEBUG or INFO value, as in the example below:

~ $ VAGRANT_LOG=DEBUG vagrant up

Debugging chef-solo

You have got two options how to enable verbose mode for chef-solo.

First, you can SSH into a created virtual machine and invoke the magic command in a certain directory:

~ $ vagrant ssh

vagrant@localhost ~ $ cd /tmp/vagrant-chef-1
vagrant@localhost /tmp/vagrant-chef-1 $ sudo chef-solo -c solo.rb -j dna.json -l debug

In this magic command the parameter -c is responsible for setting a configuration file, -j is for passing a file with attributes, which is later called a node specification. Last parameter -l - most important for us - enables the verbose mode at a certain logging level.

You may be wondering why you are entering a /tmp/vagrant-chef-1 directory with a digit at the end?

The actual value depends on the number of concurrent and active provisioning processes running on the virtual machine and is represented by the get_and_update_counter method and the Counter module.

But you can enable it in a different way - by passing the arguments to a provisioner inside Vagrantfile:

1
2
3
4
5
6
7
8
9
Vagrant.configure('2') do |config|
  # ...

  config.vm.provision :chef_solo do |chef|
    # ...

    chef.arguments = '-l debug'
  end
end

Mutating the DNA

As you can see in the example above, related with the chef-solo debugging, you have got a dna.json file with attributes generated on the basis of provisioner configuration attached in Vagrantfile. We call it a node specification. But what if you already have an existing node specification, and you want to use it?

There is an attribute for that, called json, but it is a dictionary. You cannot pass a plain string with a path to the node file, like the role name in the add_role method or setting a value in the environment field.

In order to inject our attributes you need to read the file first, then parse the content as JSON and finally merge it with the existing value of the field:

1
2
3
4
5
6
7
8
9
Vagrant.configure('2') do |config|
  # ...

  config.vm.provision :chef_solo do |chef|
    # ...

    chef.json.merge!(JSON.parse(File.read('path/to/json/file')))
  end
end

Links

  1. Vagrant Github repository
  2. Vagrant documentation
Home