Chef Sugar is an extension to Chef that offers DSL methods to make more readable recipes. Seth Vargo, Chef Sugar's author, wrote about his motivations for creating Chef Sugar, highlighting them with examples. InfoQ interviewed Seth to know more about his views on syntactic sugar and the benefits of a plug-in architecture in the context of Chef.
Chef Sugar provides DSL methods in several areas, such as cloud (e.g.: cloud?
, ec2?
) or platform (e.g.: ubuntu?
, centos?
). There are ongoing discussions to add additional helper methods. In his article, Seth shows an example that contrasts a recipe with and without the use of Chef Sugar. This recipe:
include_recipe 'cookbook::_windows_setup' if platform_family?('windows') include_recipe 'cookbook::_ec2_setup' if node['ec2'] || node['eucalyptus'] package 'foo' do action :nothing end.run_action(:install) execute 'untar package' do if node['kernel']['machine'] == 'x86_64' command 'ARCH_FLAGS=x64 make' else command 'ARCH_FLAGS=i386 make' end not_if do ::File.exists?('/bin/tool') && ::File.executable?('/bin/tool') && shell_out!('/bin/tool --version').stdout.strip == node['tool']['version'] end end credentials = Chef::EncryptedDataBagItem.load('accounts', 'passwords')
can be transformed into this recipe:
include_recipe 'cookbook::_windows_setup' if windows? include_recipe 'cookbook::_ec2_setup' if ec2? || eucalyptus? compile_time do package 'apache2' end execute 'untar package' do if _64_bit? command 'ARCH_FLAGS=x64 make' else command 'ARCH_FLAGS=i386 make' end not_if { installed_at_version?('/bin/tool', node['tool']['version']) } end credentials = encrypted_data_bag_item('accounts', 'passwords')
Chef Sugar was intentionally written to be accessible within a recipe, but also as a Chef library, the concept that allows arbitrary Ruby code to be included in a cookbook. The only significant difference is that when used as a library, Chef Sugar's methods take a node object as a parameter:
# cookbook/libraries/default.rb def only_on_windows(&block) yield if Chef::Sugar::PlatformFamily.windows?(@node) end
InfoQ: Syntactic sugar is sometimes viewed as something superfluous and less important. Since you created a project called Chef Sugar you clearly don't think that's always the case. When do you think a bit of sugar is good and when do you think it's a bit too much?
I think syntactic sugar is one of the top reasons why Ruby (and Rails) became such a hit among developers. For example, ActiveSupport adds sugar to Ruby's Integer class that permits method calls like
5.days.ago
. Sugar is incredibly useful in reducing complexity and repetition. Many cookbooks share common idioms or patterns - like checking if a piece of software is installed at a particular version. When I saw this type of pattern appearing, I knew it was time to slap on some sugar.Conversely, I did not (and do not) actively seek areas to "sugarize". I think this is an often-made mistake. In my opinion, a sugar has gone too far when there are more than two logic branches or components. For example, one could easily write a sugar that wraps a bunch of logic and resources, but this is better served as a library or LWRP. Sugars should be easily testable and maintainable, and novice developers should be able to dissect the method that defines the syntactic sugar.
InfoQ: Do you believe that, in general, this kind of features should be available in the core of an application or is it better to have them as "add-ons"? Why?
I am a firm believer in the plugin-architecture pattern. I easily could have added Chef Sugar to core Chef, but I made the conscious decision to keep it isolated. Just like a developer should not be forced to use ActiveSupport, a Chef developer should not be forced to use Chef Sugar.
From a maintainability standpoint, having Chef Sugar as a separate gem allows me to work and iterate independently of the Chef release cycle. Ruby itself is consuming this kind of plugin-pattern, migrating core Ruby classes to gems with individual maintainers. Rubinius 2.0 is entirely composed of gems. Just like there are advantages of having a distributed system instead of one monolithic application, those same advantages are present when using a plugin-based "add-on" rather than bundling the component in the core framework. This pattern is also present in tools like Vagrant Knife (the CLI for Chef) or Rubygems.
There is, however, a happy medium in which the plugin is locked and bundled at a particular version in the core (as a dependency), but continues to live outside of the framework as an isolated resource. Users may choose to update to the latest version of the plugin at any time, or wait to upgrade the entire software package. Ruby 2.0 follows this pattern. Try uninstalling bigdecimal and you will get this error:
ERROR: While executing gem ... (Gem::InstallError) gem "bigdecimal" cannot be uninstalled because it is a default gemBut Ruby developers can choose to upgrade to a newer version of bigdecimal at any time.
The last thing to consider (which is often overlooked), is the licensing implications. In the case of Chef Sugar, both Chef and Chef Sugar are licensed under the Apache 2.0 license, so it is not a concern. Sometimes it is not possible to bundle a plugin in a core application because it would disallow reselling, patenting, etc.
InfoQ: Is there any remaining area of Chef that could benefit with additional Chef Sugar methods?
As I said earlier, I do not actively seek areas to "sugarize". When I first released Chef Sugar, there was immense popularity. Within 20 minutes, a community member added FreeBSD platform support. The project then lived for two months without any maintenance (it just "worked"). About a month ago, someone added support for Cloudstack.
I tend to pride myself on quickly acknowledging and merging pull requests, so I always encourage people to submit them. I am also not afraid to say no when I think a patch exceeds the goals of the project. If a community member sees an area that can be "sugarized", I am happy to take a look!
InfoQ: What are the most important areas in Chef that could benefit with more community involvement?
All of Chef's issues are tracked on Chef Software's ticketing system. Most of the issues are triaged and ordered by priority. For new community members, issues tagged "trivial" or "minor" probably involve minimal changes and are a great way to dive into the Chef core. And lastly, never underestimate the power of typographical or grammatical fixes. As Chef is gaining increasing popularity, users of non-English backgrounds should be able to consume the documentation too.
Additionally, there is an open GitHub project for Chef RFCs. These are proposals from the community for high-level features or changes in the Chef roadmap. The Pull Requests in that repository significantly benefit from community involvement (even if it is just a simple :+1:).
Aside from the Chef core software project, it was announced at the Chef Community summit last November some important changes to the COOK project (the community cookbooks that Chef maintains). Chef is in the process of sharing responsibility for community cookbooks with Chef community members.