Idiomatic way to invoke chef-solo?
What is the idiomatic way to invoke chef-solo? Most sites do this:
chef-solo -c ~/solo.rb -j ~/node.json -r http://www.example.com/chef-solo.tar.gz
But that's long. There are a few shorter ways to do this that I can think of:
- A rake task (
rake chef-solo
). - A small shell script (
run-chef-solo
). - An alias (can override the name, like
chef-solo
).
What is the idiomatic way to do this? How are other chef users invoking chef?
By default, chef-solo
reads its configuration from /etc/chef/solo.rb
. The command-line parameters correspond to config values that can be set in this file. This is done using the mixlib-config library.
option :config_file,
:short => "-c CONFIG",
:long => "--config CONFIG",
:default => "/etc/chef/solo.rb",
:description => "The configuration file to use"
option :json_attribs,
:short => "-j JSON_ATTRIBS",
:long => "--json-attributes JSON_ATTRIBS",
:description => "Load attributes from a JSON file or URL",
:proc => nil
option :recipe_url,
:short => "-r RECIPE_URL",
:long => "--recipe-url RECIPE_URL",
:description => "Pull down a remote gzipped tarball of recipes and untar it to the cookbook ca
che.",
:proc => nil
The 'option' is the config file value.
The actual config file, /etc/chef/solo.rb
would look like:
file_cache_path "/tmp/chef-solo"
cookbook_path "/tmp/chef-solo/cookbooks"
role_path "/tmp/chef-solo/roles"
json_attribs "/tmp/chef-solo/node.json"
recipe_url "http://www.example.com/chef-solo.tar.gz"
Also note that the JSON file can be a remote URL, too.
json_attribs "http://www.example.com/node.json"
You can use Ohai as a library within the config file as well, to detect the platform or other attributes to specify what JSON file to use.
require 'rubygems'
require 'ohai'
o = Ohai::System.new
o.all_plugins
file_cache_path "/tmp/chef-solo"
cookbook_path "/tmp/chef-solo/cookbooks"
role_path "/tmp/chef-solo/roles"
json_attribs "/tmp/chef-solo/#{o[:platform]}.json"
recipe_url "http://www.example.com/chef-solo.tar.gz"
And then you'd have "platform" specific JSON files, for example. Or you could use o[:hostname]
, o[:domain]
or o[:fqdn]
to use JSON files based on the hostname, domain or fqdn. But once you start having the scaffolding of servers to support this kind of dynamic configuration, you might look at running a Chef Server :-).
@jtimberman has already written a great answer. Here's my personal way of invoking chef-solo. This gets the basics working and you will probably need to add more attributes to /etc/chef/node.json
and explore some of the options described in the other answer.
# cat > /etc/chef/solo.rb << EOF
cookbook_path "/var/chef-solo/cookbooks"
json_attribs "/etc/chef/node.json"
EOF
# cat > /etc/chef/node.json << EOF
{
"run_list": ["recipe[foo]", "recipe[bar]"]
}
EOF
Either copy over your cookbooks into /var/chef-solo/cookbooks
or tar.gz them up on a webserver and use the recipe_url
parameter. Running chef-solo
on the node is all that's required to invoke it.
If possible I try and keep everything in solo.rb
as I quite like being able to run chef-solo without having to remember any extra arguments.