Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overriding attributes in the recipe

Let's say I have a default attribute in a cookbook:

default.nginx_upstreams = {     'service1' => ['service1.server.com'],     'service2' => ['service2.server.com'], } 

Then it gets modified and overridden in roles and environments until it finally gets to my recipe. There, I compute some additional services that I would like to add to the attribute. If I do something like this:

node.nginx_upstreams.merge! {'service3' => ['service3.server.com']} 

then when I try to use the attribute in my template, I get a undefined method 'each' for nil:NilClass in my template when I try to do

<% node.nginx_upstreams.each do |name, servers| %> 

Plus, I also get a WARN: Setting attributes without specifying a precedence is deprecated and will be removed in Chef 11.0. The helpful warning tells me how to set attributes at normal precedence (apparently, using node.set["key"] = "value", but doesn't tell me how to specify default or override attributes.

I can get around this problem by doing something like this:

upstreams = node.nginx_upstreams.to_hash upstreams.merge! {'service3' => ['service3.server.com']}  template "nginx_config" do     variables({:upstreams=>upstreams}) end 

but that feels like a hack. I cannot find any documentation on node.set() beyond this page, which also indicates that you can set both normal and override attributes in the recipe but doesn't say how.

So... how do you properly set attributes (that get deep-merged along with everything else) from inside the recipe? What does the node.set() call actually do, and can I tell it the precedence I want to merge at?

like image 217
Igor Serebryany Avatar asked Jan 31 '13 05:01

Igor Serebryany


People also ask

What is node default Chef?

In short "node[a]" is used to read the existing value saved within the Chef node object and "node. default[a]" is used to set the value.


2 Answers

default.nginx_upstreams is the same as default[:nginx_upstreams] and default['nginx_upstreams'] - the convention is to use 1 of the latter two. And as you are using strings further, use them here too.

The way you init nginx_upstreams in attribute file is the same as doing it this way:

default['nginx_upstreams']['service1'] = ['service1.server.com'] default['nginx_upstreams']['service2'] = ['service2.server.com'] 

And you don't have to init default['nginx_upstreams'] = {} before that. These are not hashes, but attributes, and they are a lot smarter. :)

Modifying attributes from inside the recipe is done like that:

node.default['nginx_upstreams']['service3'] = ['service3.server.com'] 

You can use set or override instead of default here, if you need to change precedence. Omitting the precedence name (node['nginx_upstreams'] or node.nginx_upstreams) will use the set precedence. But this is deprecated and soon to be removed - that's what the warning is all about. Check out the manual page about attributes, because everything is actually there.

like image 84
Draco Ater Avatar answered Sep 20 '22 03:09

Draco Ater


Just wanted to give further insight on Chef attributes, it is very important for users, who is going to refer this question on node attribute override.

File Methods corresponds to attributes

Use the following methods within the attributes file for a cookbook or within a recipe. These methods correspond to the attribute type of the same name:

  • override
  • default
  • normal (or set, where set is an alias for normal)
  • _unless
  • attribute?

Attribute Precedence

Attributes are always applied by the chef-client in the following order:

  1. A default attribute located in a cookbook attribute file
  2. A default attribute located in a recipe
  3. A default attribute located in an environment
  4. A default attribute located in role
  5. A force_default attribute located in a cookbook attribute file
  6. A force_default attribute located in a recipe
  7. A normal attribute located in a cookbook attribute file
  8. A normal attribute located in a recipe
  9. An override attribute located in a cookbook attribute file
  10. An override attribute located in a recipe
  11. An override attribute located in a role
  12. An override attribute located in an environment
  13. A force_override attribute located in a cookbook attribute file
  14. A force_override attribute located in a recipe
  15. An automatic attribute identified by Ohai at the start of the chef-client run

where the last attribute in the list is the one that is applied to the node.

It means that, OHAI attribute will have the highest precedence, where as the default attribute in cookbook attribute file will have the lowest precedence.

Note: Provided the important details from Chef docs for attributes for the benefit of users. Because sometimes the URL will be moved or invalid.

like image 22
Saravanan G Avatar answered Sep 20 '22 03:09

Saravanan G