Bratty Redhead

the sarcasm is free!

Puppet for Chef Users

I picked up a Puppet gig recently.  The client already has an OS level Puppet install working.  My job is to use my understanding of automation tooling to configure an app stack.  I was pretty cocky.  I thought, well, I really know Chef after over a year working with it and extending it at another client, how hard can Puppet be? 

It’s not hard really.  But it’s not cooperative either.  They look really similar, Puppet and Chef, but I’m finding it hard to get Puppet to do what I want.  First, I need to figure out what I want to do.  Then I automatically consider how I would do it in chef.  Then I have to figure out how to do it in Puppet.  This is harder than it sounds as a direct translation of something is not always the most useful, graceful or appropriate method.

I keep wishing I could find an article or manual on the Interwebs called something like “Puppet for Chef Users,” where it would translate all the things done in Chef to what they do in Puppet.  I haven’t found it.  And I don’t have all the answers.  As you can see here, I actually have very few answers.  None really.  But I’m eking out answers as I go.

Example: I want to set a node attribute. 

Well, hm.  Ok.  A node is still a node(mostly) in Puppet.  Puppet has Facter instead of Ohai.  Right, I knew that.  So, then I have to address the philosophical question, is that the correct way to do what I want?  Do I add things like myapp_home, java_install_dir to Facter?  Yah, I think I do.  I want stuff outside the myapp module to know where the myapp log dir is, maybe (it could happen).

Let’s say I do want to add custom facts.  That’s just like node attributes aren’t they?  I’m still not positive, but I’ve got to make a decision and start coding something.  I can always revise if I’m wrong.

Alright, where’s the attributes file?  Whoops!  No attribute file.  I downloaded a sample Apache module from puppet labs in order to have an example to work with.  I needed the example to be complex enough to have custom attributes but not so complicated I couldn’t read it.  I figured an Apache server was a good compromise. 

I found that Puppet modules can define new facts in the lib directory of the module.  Strangely, at first I thought it was defined in a directory called ‘plugins’ as I first noticed the new facts defined there.  But as I read the documentation on defining new facts, I realized that was the old directory. The new way dictates that all custom code goes in modules/myapp/lib. 

The directory storing new facts has small rb files with code similar to ohai snippets.  This seemed like more coding than I needed, but I’m still not sure how to just set an attribute without writing a code snippet.  Here’s the code example I found:

require ‘facter’
Facter.add(:gem_passenger_version) do
    setcode do %x{rpmquery –qf=’%{VERSION}’ rubygem-passenger} end
end

here’s my experimental code:

require ‘facter’
myapp_facts={“myapp_home” => “/opt/myapp”, “myapp_server_dir” => “/opt/myapp/server”,”myapp_log_dir” => “/var/log/myapp”}

myapp_facts.each do |k,v|
  Facter.add(k) do
    setcode do { k=v } end
  end
end

This is what came out of testing:

[root@pixel rubylib]#  RUBYLIB=. facter|grep myapp
myapp_home => /opt/myapp
myapp_log_dir => /var/log/myapp
myapp_server_dir => /opt/myapp/server

So yay!  I figured it out. I added my puppet equivalent of node attributes.  Kind of.  As far as I can tell, Facter is not hierarchical a la Ohai, so my node attributes are flattened instead of in a hierarchy.

To recap, in Chef/In Puppet:

  • Ohai/Facter
  • node attributes/facts
  • ohai is hierarchical json: facter is flat key => value pairs
  • chef node attributes are defined in myapp/attributes/attribute.rb/Puppet facts are defined in myapp/lib/facts 

Coming soon, my adventures with Hiera and data storage, also Puppet ruby DSL vs Puppet Puppet DSL.