by Zachary Crownover, Technical Consultant at Taos
For anyone coming from a Puppet background, one of the first things you’ll learn about Chef is that it emphasizes programming rather than Puppet’s administrative mindset. In other words, mastering Chef takes a commitment to thinking differently. You’ll want to become intimately familiar, first and foremost, with the concept of Ohai and the Chef node object to advance as quickly as possible, and you’ll need to adjust to a series of quirks. Often, your problems will manifest themselves as programmatic rather than administrative, but troubleshooting them will always come down to a matter of using the ingenuity and accumulation of knowledge you already have. Take everything you remember from Puppet, and use it as an overview of concepts to apply to Chef, as a general rule of thumb. Most importantly, never forget, unlike in Puppet where nearly everything is processed on the server and sent to the client to apply locally, EVERYTHING in Chef is client side.
While it’s technically true that YAML is a superset of JSON, one of the first things that you’ll notice about Ohai is that the output is in JSON instead of YAML. Initially, that might not seem like much of a difference, but where you’ll notice the difference is the level of verbosity of data extracted, that there are multidimensional hashes, and that the data is structured. The next big thing you’ll need to take into account is that in the Puppet world, all these parts from Facter (known as facts in the Puppet world) are presented in the form of class variables in the manner Ruby does @variable. In Ohai, node attributes (the equivalent to facts), are referenced as a hash relative to the system and the depth, i.e., node[‘fqdn’] or node[‘chef’][‘version’].
Chef and Puppet both make extensive use of their own unique system profiling utilities, Ohai and Facter, respectively. Both are executed by their respective configuration management system to profile a node, and both are extensible by the end user as well, though you should consider whether it’s worth it to add additional node attributes to your Chef runs. While Puppet Labs has been reimplementing Facter from its original form of being purely Ruby to almost exclusively in C++, drastically reducing memory footprint and run time, Chef’s Ohai is still 100% Ruby, and the run time clearly shows it in comparison. In Puppet in order to add a fact you would add a file to modules/modulename/lib/facter/factname.rb and define a fact, where the return value of the code run is the value of the fact. Adding a node attribute in Chef is slightly more involved, if managed by Ohai. It requires, among other things, including ‘Ohai::Config[:plugin_path] << SYSTEM_PATH’ in your client.rb. The file path for specific plugins is taken from the Ohai cookbook, which defaults to cookbooks/cookbookname/files/default/plugins/attributename.rb. From there you would add a file in the aforementioned path, and set the specific attributes within your hash to the values from the system, generally following the same rule as creating facts in Puppet. In Ohai, plugins are what generate node attributes. When the Chef client runs the Ohai cookbook, the plugin is created and executed on the local system, before being added to the Chef node object. When using structured data, you’ll also need to invoke a special object class called Mash.
Puppet modules have their own naming convention for files containing locally scoped variables. The default location for these variables is in a manifest file called variables.pp or params.pp. Unlike Chef, however, these variables are not part of any central object. Often when referenced in other places, it’s passed in as a parameter and shortened to local scope to avoid extra typing. Puppet comes with extensive libraries that can be used for validating data types due to Ruby’s dynamic typing not granting as much power there out of the box. The same in Chef is done through a file in cookbookname/attributes/default.rb, where variables are set as default[‘variable’][‘name’] = value. When later referenced, they are part of the node object if included in the run list and will be seen as node[‘variable’][‘name’]. Cookbooks in Chef however are not parameterized classes and do not take external input in the same manner, but instead more often involve overriding variables or appending to them, part of the expansion of the globally accessible node object. Equivalent methods in Chef to the Puppet validation of variable types do not exist.
Chef is definitely geared more towards a sysadmin with a programming background, though there’s no reason it can’t be learned quickly and well by one without that experience. Chef differs from Puppet with a sharper line of access to Ruby internals, and encourages you to interact with every aspect of a system through classes, objects, and toolsets provided to build and test your works. The encouragement to run debuggers rather than simply read ambiguous output from a client run is another step in that direction as well, but even with all that said, you’ll end up with a programming background one way or the other.