How to prevent "deep marge" of array attribute values?


#1

I am seeing behavior from Chef Client 12 that looks like it’s explained by Chef’s “deep merge” behavior. Is there a way to turn this behavior off so I can reset a certain array-valued node attribute cleanly in a recipe, when it’s set at the same level of precedence in the environment?

Details follow.

I have an array attribute value defined in the Chef environment at the “default” level of precedence. In my cookbook recipe I try to “reset” that attribute to another array value, also at the “default” level of precedence. But at run time Chef ends up using BOTH the values from the Chef environment and the values I specify in the cookbook recipe – it merges both arrays into a unique, sorted list of values.

This behavior seems to be explained by Chef’s “deep merge” behavior as described on the “About Attributes” page (https://docs.chef.io/attributes.html#about-deep-merge):

The deep merge capabilities of the chef-client allows attributes to be layered across
cookbooks, recipes, roles, and environments … When an attribute value is an array, if the
attribute precedence levels are the same, then that data is merged.

In this specific case I don’t want this behavior: I want to cleanly reset the value of this node attribute at the “default” level of precedence to a given array value that I specify in my cookbook recipe. Is that a tried-and-true way to do this?


#2

There’s a few ways to do it, described right above the place you linked in the docs, starting here: https://docs.chef.io/attributes.html#remove-precedence-level “Full Assignment” seems to be exactly what you want.

I’m not sure exactly when all these were added, so you may need to upgrade to at least Chef 13. 12 is EOL now so that’s a good thing to do anyway.


#3

Thank you, @kallistec! I did not know that’s what “Full Assignment” referred to. I appreciate your guidance and will test it out. (While simultaneously addressing Chef Client 12 deprecation warnings in order to move the Chef Client 13 :-))


#4

I was able to reset the “default” value of the node attribute like this, as pointed out in the doc section @kallistec pointed me to above:

node.rm_default('mycookbook', 'foo')
node.default['mycookbook']['foo'] = servers

So I’m all set. I appreciate the guidance.