Executing Cookbooks with Chef-Solo

Chef-Solo is an open source tool that runs locally and allows us to provision the guest machine using chef cookbooks without the complication of any chef client and server configuration. In this post, we will learn to execute a simple recipe which will create a file with some content inside /tmp directory using chef cookbook recipe.

To start with, we will create a directory where all our chef related content resides and for me it’s chef-repository, as follows:

$ mkdir chef-repository

Next, we will configure Knife inside our chef-repository to create cookbooks and recipes, as follows:

$ cd chef-repository
$ mkdir .chef
$ echo "cookbook_path [ '/vagrant/chef-repository/cookbooks' ]" > .chef/knife.rb

/vagrant/chef-repository/cookbooks specified above refers the path to chef cookbooks.

Now, we will create our first cookbook using knife which will also create recipe with name default.rb for us with default content, as follows:

$ knife cookbook create mycookbook

Edit the content of cookbooks/mycookbook/recipes/default.rb to create the file with name default-file with given content inside /tmp directory as below:

file "/tmp/default-file" do
  content "It's file created by Chef Recipe"
  owner "root"
  group "root"
  mode 00600

Move to directory ‘cookbooks’ and create chef configuration file solo.rb:

$ echo "cookbook_path ['$PWD']" > solo.rb

Next, run the recipe we created using chef-solo., as follows:

$ chef-solo -c solo.rb -o mycookbook::default;

Running multiple recipes inside cookbook?

We can run multiple recipes using chef-solo –override-runlist and –json-attributes command line options as follows:

a). Using chef-solo –override-runlist

chef-solo -c solo.rb -o recipe[mycookbook::default],mycookbook::first

mycookbook::first refers to the recipe with name first.rb inside directory cookbooks/mycookbook/recipes/

b). Using chef-solo –json-attributes

Create a .json file with any name for me it’s recipes.json with content as:

  "run_list": [

Then execute below command from directory ‘cookbooks’:

sudo chef-solo -c solo.rb -j recipes.json

Installing Puppet Modules – Librarian Puppet

Of course we can manually download the modules from Puppet Forge and install it but it becomes messy as you have to manually maintain the dependencies between the modules which definitely makes your repository bigger than necessary.

Already I briefed about librarian-puppet  in my Blog At Xebia, still to provide little more context, it manages the Puppet modules your infrastructure depends on, whether the modules come from the Puppet Forge, Git repositories or just a path. People who are familiar with Maven can relate librarian-puppet similar to it as it automatically download and manage dependent modules.

In this article we will learn how to install arpitaggarwal/tomcat Puppet Module using librarian-puppet. The complete source code is hosted on github.

Step 1: Create a directory with any name for me it’s vagrant, as follows:

$ mkdir vagrant
$ cd vagrant
$ vagrant init

Step 2: Edit the Vagrantfile with below content:

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.box = "hashicorp/precise32"
config.vm.network :private_network, ip: ""
config.vm.provision "shell", path: "installation-script.sh"
config.vm.provision :puppet do |puppet|
puppet.manifests_path = 'puppet/manifests'
puppet.module_path = 'puppet/modules'
puppet.manifest_file ="init.pp"

Step 3:  Create installation-script.sh in your current project directory(vagrant), which will install, librarian-puppet, it’s dependency GIT and Puppet in your guest machine, as follows:

$ touch installation-script.sh

Content of installation-script.sh should look something like this:

#!/usr/bin/env bash
set -e
# Directory in which PuppetFile is placed to be scanned by librarian-puppet.

echo "Installing Git.."
apt-get -q -y install git

echo "Installing librarian-puppet.."
if [ "$(gem search -i librarian-puppet)" = "false" ]; then
RUBY_VERSION=$(ruby -e 'print RUBY_VERSION')
case "$RUBY_VERSION" in
# For ruby 1.8.x librarian-puppet needs to use 'highline' 1.6.x
# highline >= 1.7.0 requires ruby >= 1.9.3
gem install highline --version "~>1.6.0" > /dev/null 2>&1
# Install the most recent 1.x.x version, but not 2.x.x which needs Ruby 1.9
gem install librarian-puppet --version "~>1"
gem install librarian-puppet
echo "librarian-puppet installed!"

echo "Executing PuppetFile.."
cd $PUPPET_DIR && librarian-puppet install --path modules

echo "Installing Puppet repo for Ubuntu 12.04 LTS"
wget -qO /tmp/puppetlabs-release-precise.deb \
dpkg -i /tmp/puppetlabs-release-precise.deb
rm /tmp/puppetlabs-release-precise.deb
aptitude update
echo Installing puppet
aptitude install -y puppet
echo "Puppet installed!"

Step 4: Make directory puppet and then modules and manifests under it, as follows:

$ mkdir puppet
$ cd puppet/
$ touch Puppetfile
$ mkdir modules
$ mkdir manifests
$ cd manifests
$ touch init.pp

Content of Puppetfile should look like:

forge "http://forge.puppetlabs.com"
mod "arpitaggarwal/tomcat"

Content of puppet/manifests/init.pp should look like:

class { 'tomcat': }

After performing all the above steps, your project structure should look like as:

Step 6: Now you can boot up your VM provisioned with Tomcat from the vagrant directory executing command:

$ vagrant up

That’s all. Happy Learning!