Chef attribute priority

I have been curious to see how chef attibutes priority is working. So I decided to do a simple experiment. I have been using wrapper cookbooks after I read this amazing post from Jamie Winsor http://blog.vialstudios.com/the-environment-cookbook-pattern/ and this post from Doug Ireton http://dougireton.com/blog/2013/02/16/chef-cookbook-anti-patterns/. So when I have a role for my application’s webserver I have the following in my role.

name "myapp-webserver"
description "Webserver role myapp application"
run_list(
"role[base-myorg]",
"recipe[myorg_roles::myapp-webserver]"
)

This means that I call a wrapper cookbook where each role has a recipe. The recipe for myapp-webserver looks like this

# Cookbook Name:: myorg_roles
# Recipe:: myapp-webserver
#
# Copyright 2014, YOUR_COMPANY_NAME
#
# All rights reserved - Do Not Redistribute
#
include_recipe 'php'
include_recipe 'mysql::client'
include_recipe 'php::module_gd'
include_recipe 'php::module_curl'
include_recipe 'php::module_mysql'
include_recipe 'apache2'
include_recipe 'apache2::mod_php5'
include_recipe 'apache2::mod_ssl'
 
include_recipe 'myapp_webapp'

According to https://docs.chef.io/attributes.html attributes are defined by:

  • The state of the node itself
  • Cookbooks (in attribute files and/or recipes)
  • Roles
  • Environments

Which is the one which can override the rest?
In my application I have defined an attibute called

default['myapp_webapp']['git_revision'] = 'production_release'

I have also set up an environment called dev in file environments/dev.json looking like this

{
"name": "dev",
"description": "Development environment",
"cookbook_versions": {
},
"json_class": "Chef::Environment",
"chef_type": "environment",
"default_attributes": {
},
"override_attributes": {
   "myapp_webapp": {
      "git_revision": "0fa2c757a63a2ff10c879ff2af8ca6dff6059b59"
      }
   }
}

In my role file roles/myapp_webapp.rb

name "myapp-webserver"
description "Webserver role myapp application"
run_list(
"role[base-myorg]",
"recipe[myorg_roles::myapp-webserver]"
)
override_attributes(
   "apache" => {
     "serversignature" => "Off"
   },
   "myapp_webapp" => {
     "git_revision" => '8cfbf545920aece9a9328d079b8cea4dc8e6cb4f'
   } 
)

And on the wrapper’s cookbook myapp-webserver recipe

# Cookbook Name:: myorg_roles
# Recipe:: myapp-webserver
#
# Copyright 2014, YOUR_COMPANY_NAME
#
# All rights reserved - Do Not Redistribute
#

include_recipe 'php'
include_recipe 'mysql::client'
include_recipe 'php::module_gd'
include_recipe 'php::module_curl'
include_recipe 'php::module_mysql'
include_recipe 'apache2'he
include_recipe 'apache2::mod_php5'
include_recipe 'apache2::mod_ssl'

include_recipe 'myapp_webapp'

node.set['my_webapp']['git_revision'] = "51bc20cd76b210972e960a91b57fadae8ef6a1ed"

If you provision a node like this then you ll going to get the git_revision defined on the environment file. So environment wins.
If you do NOT use an environment file then you ll get the git_revision you are going to get the git_revision defined on the roles file. So role wins over cookbook when you use the node.set variable.

So when using the node.set the order is Environment–>Role–>Cookbook
Instead of using node.set on your wrapper cookbook you can use node.override then the order is Environment–>Cookbook–>Role

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s