Ohai Chefs,
We recently merged some additional changes to attributes behavior for
Chef 11 that I’d like to make you aware of.
TLDR
- Attributes from roles and environments are available when attribute
files are evaluated. - Chef::Node now includes platform introspection methods, so you can use
plaform?()
and friends in attributes files. - Default and Override attributes from cookbooks, roles, and
environments are stored separately during the Chef run. - As a consequence of the above, setting a default or override attribute
in a recipe will no longer overwrite a value set by a role or
environment. - CHEF-2936 http://tickets.opscode.com/browse/CHEF-2936
Accessing Role and Environment Attributes in Attributes Files
In Chef 10.x and previous, you cannot set attribute values that depend
on other attributes in attributes files, because you do not have access
to attributes from roles. For example, suppose you want to configure the
database for your app. You’d expect code like this to work (in an
attributes file):
node.default[:app][:name] = "my_app"
node.default[:app][:env] = "development"
node.default[:app][:database] ="#{node.app.name}_#{node.app.env}"
However, this will not work if you intend to set node[:app][:name]
or
node[:app][:env]
via roles or environments, because Chef will not have
seen those attributes when evaluating the attributes files.
In Chef 11, role and environment attributes are applied when the
run_list is expanded, so the above code will work the way you want it
to.
Setting Platform-Specific Attributes in Attributes Files
In Chef 10.x and previous, the utility methods for making choices based
on a node’s platform or platform_family are available in recipes, but
not in attributes files. Some users have expressed a desire to be able
to set attributes based on platform in their attributes files. In Chef
11, these methods are now available on node objects, so you can use them
in attributes files. E.g.,:
if platform?(:debian, :ubuntu)
default[:foo] = "debian value"
elsif platform?(:centos, :rhel)
default[:foo] = "rhel value"
else
default[:foo] = "generic value"
end
Cookbook Style
Together, these changes mean you can move attributes computations out of
recipes and into attributes files. I personally think this style will be
much better than what you must do currently, but we (Opscode) haven’t
made any official recommendation on this question yet. Do keep in mind
that any cookbook written using these features won’t be usable on Chef
10.x systems if you intend to make your cookbook public.
If you wish to write your cookbooks with computed attributes in
attributes files, don’t forget to use include_attribute()
to enforce
the desired attribute file load order.
Breaking Changes
The implementation change that makes these features possible is a
potentially breaking change.
During a Chef run, default and override attributes from cookbooks,
roles, and environments are now stored separately. In the following
cases, you may get a different result when computing the value of an
attribute:
Attributes Files and Recipes Have the Same Precedence
In Chef 10.x and previous, setting a default attribute value in a recipe
would overwrite a value set by a role or environment. In Chef 11, values
set from a cookbook are stored separately, so the value set by the role
or environment will not be overwritten.
Consider a role like this:
default_attributes "app_name" => "from-role"
And a recipe file like this:
node.default["app_name"] = "from-recipe"
In Chef 10.x and lower, the value of node["app_name"]
will be
"from-recipe". In Chef 11, the value will be “from-role”
Role and Environment Attributes are Visible to Attributes Files
If, for some reason, you have been depending on attributes from roles
and environments not being visible during attribute file evaluation, you
will need to adjust your cookbooks or roles for this change.
What to Look For
Unlike the other changes to attributes in Chef 11, this one is a
behavior change, meaning that valid usage can lead to different results
in Chef 11 compared to Chef 10. I expect the vast majority of users will
not be affected, since it’s unlikely you were depending on the old
behavior intentionally.
To see if you’re affected, you’ll need to take a look at your cookbooks
and roles and look for attribute conflicts.
One strategy is to inspect your recipes to see if you’re setting
defaults:
find . -name recipes -exec grep -n 'node.default' -r {} \;
…and compare with your roles to see if there’s a conflict.
Another option is to use why-run mode and inspect the output for any
unexpected configuration changes.
–
Daniel DeLeo