Testing Chef Attributes from Wrappers


I have environmental wrapper cookbooks using attributes that are mainly static but quite a few derived.

90% of those attributes are resolved correctly but some of the derived are returning blank even though I can trace them back logically.

Anyone know the order attributes are loaded prior to the run?

I've seen documentation on the chef site [https://docs.chef.io/attributes.html#attribute-precedence](http://About Attributes) but all mine are default


File : attributes \ _enviroment.rb

default['corp_app'']['environment']['server_path'] = "E:\Apps\Corp_App"

File : attributes \ appfile.rb

default['corp_app']['environment']['TempFilesLocation'] = "#{node['corp_app'']['environment']['server_path']}\Files\Temp"

Are they loaded alphabetically, filenames first, then internal attribute name?

sorry for basic question long time since I've troubleshooted this ...



Yes, attribute values are whatever is set last (at the same precedence level) - “last-in wins", and attribute files are evaluated in a-z order.

However, derived attributes don’t work like anyone expects. They work like environment variables, not like derived variables in a programming languages. So with derived attributes, the value is plugged in with whatever it is set at the time the line is read, not after all the attribute files are read. This is likely the scenario you are hitting in your code.

If you have a O’Reilly Safari subscription, I’d recommend checking out the “Managing Settings With Chef” chapter in my Learning Chef video. In particular the “Composed Attributes are Bad” section - https://learning.oreilly.com/videos/learning-chef-for/9781491959442/9781491959442-video303723 (What you call “derived attributes”).

Here’s the exact example from the video:

# attributes/default.rb

default[’tomcat_home’] = ‘/usr/local/tomcat6'

default[’tomcat_bin’] = "#{node[’tomcat_home’]/bin”]

# attributes/tomcat.rb

default[’tomcat_home’] = ‘/usr/local/tomcat8'

You’ll discover that node[’tomcat_home’] is /usr/local/tomcat6/bin not /usr/local/tomcat8/bin like you’d expect.

Chef will process default.rb first, then tomcat.rb, like you’d expect.

However, any variable replacements happen with the value when it is read. So unfortunately, like in this case - node[’tomcat_bin’] is set to whatever tomcat_home is set to when the line is being read. Since Chef hasn’t read attributes/tomcat.rb - it’s whatever tomcat_home is currently set to, like an environment variable.

There are a variety of approaches to solve this issue. There are basically two camps - one camp avoids interpolated values completely and sets the entire attribute as a single string to make things more clear to people who don’t know all the ins and outs of how Chef attributes work. Others will use ruby syntax tricks like using %{} to perform delayed interpolation. You can decide which approach works best for you.

1 Like

@misheska Great detailed response much appreciated - will work through it and hopefully resolved my problem :slight_smile: