Managing different environments with chef attributes and a case statement.

Like everyone else using chef I manage several environments such as dev, staging, testing & production. Many times the only difference is a single config file( for me that is most daemons such as mongo, mysql, redis, varnish, etc….)There are several ways of doing it. One way is to use templates( which I find to be confusing and more than what I need).Another way is to create a different recipe for each environment ( mongo.dev, mongo.prod ,etc….) This seams like too much work.What I found to be the simplest and cleanest way is to use the case statement with attributes.Don’t forget the creators of chef( opscode ) allow you to exit the DML and just write ruby so take advantage of it.
Lets so you have a recipe to install and configure mongo.The entire recipe is the same except for the config file.This can be easily managed using attributes and case statement.First create an empty role for each of the different environments (dev, prod, etc…), then assign them the same attribute in this case app_environment with a different value for the environment.In json this looks like this:

{"overrides":{},"defaults":{"app_environment":"dev"}}

Then in the recipe use the case statement to determine which config file the node gets:

cookbook_file "/etc/mysql/my.cnf" dosource_file = case node[:app_environment]when "dev" then "my.cnf.dev"when "prod" then "my.cnf.prod"endsource source_filenotifies :restart, "service[mysql]", :immediately mode "0644"owner "root"end