01 Apr 2013Documenting Cookbooks
Our infrastructure has many cookbooks that aim to be reusable, primarily through encapsulating behaviour in LWRPs. This led to an explosion of LWRPs and sometimes the documentation didn't keep up or did just not exist.
Chef has been evolving rapidly and many of the pain points are being addressed by Opscode or by the community at large - which is great. However, one pain point that is not getting easier is writing cookbook documentation. Several threads came together last week to motivate me to change this.
- Incorrect documentation of LWRPs contributed to an outage.
Mathias Lafeldt wrote a knife
plugin that generates an initial
metadata.rbfile in a a cookbook.
- Other languages/frameworks have tools to generate documentation from annotated source code.
So I decided to try and extend Mathias's work so that I could always regenerate
README.md from the cookbook source code. This result in the
knife cookbook doc DIR
As much as possible the plugin makes use of the same metadata as used by chef
when generating the documentation. The plugin will also scan the source files
for annotations present in comments. Users can also add fragments of markdown
doc/ directory to merge into the generated
The goal is to keep the code as the authoritative source of information. The hope is that keeping the documentation close to the code will help to maintain it's currency.
metadata.rb of your cookbook according to Opscode's
attention should be paid to documenting the recipes, attributes, platform
compatibility and cookbook requirements (i.e. depends, recommends, suggests etc).
At the top of each recipe, add a detailed documentation section such as;
=begin #< The recipe is awesome. It does thing 1, thing 2 and thing 3! #> =end
In each LWRP, add detailed documentation such as;
=begin #< This creates and destroy the awesome service. @action create Create the awesome service. @action destroy Destroy the awesome service. @section Examples # An example of my awesome service mycookbook_awesome_service "my_service" do port 80 end #> =end ... #<> @attribute port The port on which the HTTP service will bind. attribute :port, :kind_of => Integer, :default => 8080
It should be noted that the documentation of the LWRP requires that the user
document the actions, using
@action <action> <description> and the attributes
@attribute <attribute> <description>. This allows meaningful
descriptions for the actions and attributes to be added to the README.
The other text will be added at the start of the LWRP documentation
except if marked with
@section <heading>, in which case it will be added
to the end of the LWRP documentation.
Finally the user should add some documentation fragments into the
Most importantly you should add
doc/overview.md which will replace the first
Description section of the readme. You should also add a
will replace the last
License and Maintainer section in the readme. The
remaining fragments will be included at the end of the readme in lexicographic
order of the filename.
Install the plugin and run the knife command, passing the directory of the cookbook as an argument.
gem install knife-cookbook-doc knife cookbook doc MY_COOKBOOK_DIR
For an example of a README generated by the plugin, check out the glassfish cookbook. Unfortunately the plugin highlights the fact that so much of the cookbook is poorly documented. However there are some LWRPs such as glassfish_mq that have the beginning of useful documentation.
The plugin is raw but usable now. It needs to evolve to be a more seem-less part of our workflow. It would also be nice to see it or something more complete be adopted by the rest of chef community. I wonder what needs to be done to build such a tool?
- knife-cookbook-doc - the new plugin.
- knife-cookbook-readme - the original plugin.
- chef-glassfish - example cookbook using the new plugin.
Updates: 3rd of April, 2013
- Added References section.
- Added inline links.
- Added notes about the credit section.
- Fixed some unclear language.