Two different files in our repository contain these lines:
# library_cookbook_1/attributes/default.rb
default[:library_cookbook_1][:foo] = true
# library_cookbook_2/attributes/default.rb
default[:library_cookbook_2][:foo] = true
I would like to merge both of the attributes. It isn't enough to simply set one equal to the other, because they are both used interchangeably. My greatest concern is that somebody makes this mistake:
"environment_json_attributes": {
"library_cookbook_1": {
"foo": false //Now it's false half of the time...
}
}
Forgetting to set the value of both variables in our code is a fatal mistake under our current structure. I want to merge the attributes in a way that maintains the override hierarchy, so that if library_cookbook_1 has a role level override, but library_cookbook_2 has an environment level override, chef will handle the overrides as if the attributes were just one attribute.
The ideal merging code would look something like this:
> node.attributes.debug_value('library_cookbook_1', 'foo')
{'precedence1' => true, 'precendence3' => false}
> node.attributes.debug_value('library_cookbook_2', 'foo')
{'precedence1' => false, 'precendence2' => true}
> attr_merge(['library_cookbook_1', 'foo'], ['library_cookbook_2', 'foo'])
> node.attributes.debug_value('library_cookbook_1', 'foo')
{'precedence1' => true, 'precendence2' => true, 'precendence3' => false}
> node.attributes.debug_value('library_cookbook_2', 'foo')
{'precedence1' => true, 'precendence2' => true, 'precendence3' => false}
> node[:library_cookbook_1][:foo].precedence4 = true
> node.attributes.debug_value('library_cookbook_2', 'foo')
{'precedence1' => true, 'precendence2' => true, 'precendence3' => false, 'precedence4' => true}
Ideally, I want each attribute to be a pointer to the same thing, so that way, future calls and assignments apply to both.
Now, the obvious answer is to simply refactor away one of the attributes. Unfortunately, chef makes refactoring attributes difficult - we have 10 different environments, 7 different roles, 20 nodes per environment, etc. We're sure to make a mistake that will surface in subtle ways if we try to refactor the whole thing.