Postfix wrapper problem


#1

The postfix cookbook has all of its examples using roles to set various
attributes before running. I’ve seen a lot of push back on roles, and
was trying to make a wrapper cookbook, but there’s a gotcha in attribute
loading order.

https://wiki.opscode.com/display/chef/Attributes+Cookbook says:

“When Chef loads cookbook attribute files, it does so in alphabetical
order for all the cookbooks. If you need to ensure that one attribute
file is loaded before another (for example, if your Apache cookbook
attributes requires that the Rails cookbook attributes are available
first) you can use the include_attribute method”

My wrapper cookbook starts with a “w” so the postfix cookbook comes
first. I can’t add include_attribute to the postfix cookbook without
forking it, and adding include_attribute “postfix” in my own attributes
file after I set some defaults, doesn’t work, because as I look at the
code for include_attribute, it explicitly ignores files it has already
loaded.

The problem is, the postfix attribute file does some conditional loading:

if node[‘postfix’][‘main’][‘smtp_sasl_auth_enable’] == 'yes’
default[‘postfix’][‘sasl_password_file’] =
"#{node[‘postfix’][‘conf_dir’]}/sasl_passwd"
default[‘postfix’][‘main’][‘smtp_sasl_password_maps’] =
"hash:#{node[‘postfix’][‘sasl_password_file’]}"
default[‘postfix’][‘main’][‘smtp_sasl_security_options’] = 'noanonymous’
default[‘postfix’][‘sasl’][‘smtp_sasl_user_name’] = ''
default[‘postfix’][‘sasl’][‘smtp_sasl_passwd’] = ''
default[‘postfix’][‘main’][‘relayhost’] = ''
end

If I don’t have that node attribute set first, those extra attributes
don’t get set, and the postfix::sasl_auth file breaks because of nil
values. (as a side note, I think if you include postfix::sasl_auth
without setting ‘smtp_sasl_auth_enable’, you are going to hit those same
nil errors… maybe this is a bug in the postfix cookbook?)

Nothing I can do in a cookbook or recipe can fix that because the
attributes from the postfix cookbook have already been loaded and cannot
be reloaded.

so… help? where can I set
node[‘postfix’][‘main’][‘smtp_sasl_auth_enable’] before the postfix
attribute file is loaded?

workaround: I guess I set all those attributes in my own attributes file?


David Morton
dmorton@wested.org


#2

On Thursday, April 3, 2014 at 1:52 PM, David Morton wrote:

The postfix cookbook has all of its examples using roles to set various
attributes before running. I’ve seen a lot of push back on roles, and
was trying to make a wrapper cookbook, but there’s a gotcha in attribute
loading order.

https://wiki.opscode.com/display/chef/Attributes+Cookbook says:

“When Chef loads cookbook attribute files, it does so in alphabetical
order for all the cookbooks. If you need to ensure that one attribute
file is loaded before another (for example, if your Apache cookbook
attributes requires that the Rails cookbook attributes are available
first) you can use the include_attribute method”

My wrapper cookbook starts with a “w” so the postfix cookbook comes
first. I can’t add include_attribute to the postfix cookbook without
forking it, and adding include_attribute “postfix” in my own attributes
file after I set some defaults, doesn’t work, because as I look at the
code for include_attribute, it explicitly ignores files it has already
loaded.

This documentation is wrong. http://docs.opscode.com/essentials_cookbook_attribute_files.html Is up to date.

The gist of it is that does a deterministic topological sort (that also allows for circular dependencies) with the run list being the primary tiebreaker. In other words, chef iterates though your run_list, prepending each cookbook’s dependencies (and ignoring cookbooks already added to the sort order) to get a sane cookbook loading order. It then iterates through the cookbook-sorted list, loading the files in each cookbook. Alphabetical order is used on a per-cookbook basis to give you a stable, deterministic load order within a cookbook.

That said, this is still a problem with the wrapper cookbook pattern because wrapper_foo depends on foo, so foo gets loaded first. You have to either set all of the computed attributes yourself, or set your run_list so that it includes both wrapper_foo and then foo, in that order. Depending on how you manage your nodes’ run_lists that could be annoying, so you could maybe use a tiny role to encapsulate that.


Daniel DeLeo