Dom's Blog

Using Ruby to Find a Cycle in a Graph of Puppet Dependencies

Today, I had a small issue while using Puppet. To make it quick: I got a circular dependency in my Puppet recipes and Puppet failed with a verbose but not so helpful message:

1
2
3
4
err: Could not apply complete catalog: Found dependency cycles in the following relationships:
User[root] => File[/usr/share/locale/locale.alias], Package[python-setuptools] ...
# INSERT TONS of other dependencies here
... try using the '--graph' option and open the '.dot' files in OmniGraffle or GraphViz

Of course, I tried the ‘–graph’ option but, due to it’s size, the generated diagram was anything but readable.

I decided to script my way out of this tangle and, with help from this forum entry, I was able to quickly piece together a Ruby script that detects cycles in a graph:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
require 'rubygems'
require 'rgl/connected_components'
require 'rgl/adjacency'

graph = RGL::DirectedAdjacencyGraph[
  *File.open("data.txt").read.split(/,[ \n]+/).each.map do |line|
    line.strip.chomp(",").split(' => ')
  end.flatten]

inv_comp_map = {}
graph.strongly_connected_components.comp_map.each do |v, n|
  (inv_comp_map[n] ||= []) << v
end
puts inv_comp_map.values.delete_if { |scc| scc.size == 1 }.inspect

The script reads a file containing lines of the form:

1
2
3
4
User[dom] => File[foo],
User[bar] => User[dom],
File[foo] => User[bar],
User[foobar] => File[foo]

and outputs :

1
[["User[dom]", "File[foo]", "User[bar]"]]

To use the script:

1
2
3
4
gem install rgl
cat > detect_cycle.rb # copy and paste the script
cat > data.txt # copy and paste Puppet's dependency information
ruby detect_cycle.rb

Rejoice ! ;-)

Debian Wheezy 64 Vagrant Base Box

In the same spirit as Debian Squeeze 64 Vagrant Base Box this post describes a new Vagrant base box for Debian Wheezy. Wheezy is currently the unstable version of Debian, meaning the box is a constant work in progress. I will update this post each time the box is upgraded.

Quickstart

To get up and running you just need to:

1
2
3
4
gem install vagrant
vagrant box add wheezy64 http://dl.dropbox.com/u/937870/VMs/wheezy64.box
vagrant init wheezy64
vagrant up

Details

The base box has the following characteristics:

  • 395Mb in it’s packaged form;
  • 8Gb hard drive;
  • Debian Wheezy with a linux-image-3.2.0-1-amd64 kernel;
  • fr_CH keyboard layout;
  • Debian packaged ruby 1.8;
  • Debian packaged puppet 2.7.10-1;
  • Chef 0.9.14 installed as a system wide gem;
  • VirtualBox Guest Tools 4.1.8r75467

Recipe

For those interrested in the details, the box was built by following Vagrant’s instructions for creating base boxes to create a Squeeze box which was then upgraded to Wheezy.

Cleanup

In order to reduce the packaged VM’s size, a little bit of cleaning up was required. The following steps where used:

Inside the VM:

1
2
3
4
5
6
7
8
9
sudo aptitude purge cpp-4.3 gcc-4.3-base
sudo aptitude purge cpp-4.4 gcc-4.4-base g++-4.4
sudo aptitude purge python2.6 python2.6-minimal
sudo debfoster
sudo aptitude install zerofree
sudo apt-get clean
sudo rm -rf /usr/src/vboxguest*
sudo rm -rf /usr/share/doc
sudo find /var/cache -type f -exec rm -rf {} \;

Then halt the VM with vagrant:

1
vagrant halt

Restart the VM with VirtualBox and log in as root (the root password was set to ‘vagrant’ during previous steps):

1
init 1

Type the root password and then:

1
2
mount -o remount,ro /dev/sda1
zerofree /dev/sda1
  • Update (04/01/2012): The base box has been updated to Virtual Box Guest Additions v4.1.10, chef 0.10.8 and the latest _Debian Wheezy updates.
  • Update (04/04/2012): The base box has been updated to Virtual Box Guest Additions v4.1.12 and the latest _Debian Wheezy updates.
  • Update (29/04/2012): The package has been updated to the latest Debian Wheezy updates and the nfs-common_ package was installed.
  • Update (05/07/2012): The base box has been updated to Virtual Box Guest Additions v4.1.14 and the latest _Debian Wheezy updates.