How do you set node-level attributes?


#1

Hello, master chefs. I am new to Chef, I’m writing a recipe for mongoDB, and
have a general question about node-level attributes.

My mongoDB recipe works fine for standalone servers, and I would like to extend
it, to configure 2 different systems for replica pairing. The mongoDB config
file for each server should look exactly the same, except that one file will
have the directive “pairwith = ‘db1’”, while the other will have “pairwith =
‘db2’”.

It seems silly to create two different Chef roles for two nodes that differ
only by the value of one attribute. So my hope was that both servers can be
assigned the same “mongoDB” role (and by extension the same “mongodb” recipe),
but they would differ only by the value of the @node[:mongodb][:pairwith]
attribute, which would somehow be set at the node level.

However, I cannot figure out how to set attributes at the node level! I’ve
tried setting node-level attributes through the web GUI, but it doesn’t seem to
stick (on chef-server-0.7.10-0ubuntu1.1). Besides, I’d like to pre-define them,
so that I can keep them in my Chef repo, naturally.

What’s the preferred way to predefine a “node” – that is, a set of roles, and
the attributes that are to be applied only to that server? I’ve been able to do
it from the initial JSON that’s passed to the very first command-line
invocation of chef-client, when the client first registers itself with the
server. But after that, the value seems “locked-in”. How can I change
node-level attributes once a server is already running and registered?

Thanks in advance,
Ruby Newbie


#2

What are you using to set the value (set or default) in the attributes
file? I guess that you are using set. If you want to personalize this
value in the UI you have to use default in order to set attributes
properly.

Hope this helps.

Jacobo García López de Araujo
blog: http://robotplaysguitar.com
http://workingwithrails.com/person/13395-jacobo-garc-a

On Wed, Feb 10, 2010 at 5:54 AM, rubynewbie@me.com wrote:

Hello, master chefs. I am new to Chef, I’m writing a recipe for mongoDB, and
have a general question about node-level attributes.

My mongoDB recipe works fine for standalone servers, and I would like to extend
it, to configure 2 different systems for replica pairing. The mongoDB config
file for each server should look exactly the same, except that one file will
have the directive “pairwith = ‘db1’”, while the other will have “pairwith =
‘db2’”.

It seems silly to create two different Chef roles for two nodes that differ
only by the value of one attribute. So my hope was that both servers can be
assigned the same “mongoDB” role (and by extension the same “mongodb” recipe),
but they would differ only by the value of the @node[:mongodb][:pairwith]
attribute, which would somehow be set at the node level.

However, I cannot figure out how to set attributes at the node level! I’ve
tried setting node-level attributes through the web GUI, but it doesn’t seem to
stick (on chef-server-0.7.10-0ubuntu1.1). Besides, I’d like to pre-define them,
so that I can keep them in my Chef repo, naturally.

What’s the preferred way to predefine a “node” – that is, a set of roles, and
the attributes that are to be applied only to that server? I’ve been able to do
it from the initial JSON that’s passed to the very first command-line
invocation of chef-client, when the client first registers itself with the
server. But after that, the value seems “locked-in”. How can I change
node-level attributes once a server is already running and registered?

Thanks in advance,
Ruby Newbie


#3

Hey, Jacobo.

On Feb 10, 2010, at 5:43 AM, Jacobo García wrote:

What are you using to set the value (set or default) in the attributes
file? I guess that you are using set

All attributes are set with ‘default’, like so…
default[:mongodb][:platform] = 'linux’
default[:mongodb][:arch] = 'x86_64’
default[:mongodb][:version] = ‘1.2.2’

Do you know of any way besides the web GUI to set node-level attributes? The fact that I am not managing to set them from the web interface is not as concerning as the fact that there seems to be no “best practice” for defining a node – that is, defining both its role(s), and the particular attribute values it doesn’t share with other nodes that play the same role.

Thanks for responding,
Ruby newbie.


#4

I don’t think there’s a best practice at all in setting values, what
I’d do in your case is setting these values as default, then changing
then in the UI per machine basis.

Other option is setting them based on fqdn on atributtes defined.
Something like this:

case fqdn
when "host1.foo.com"
default[:mongodb][attr1]="foo"
when "host2.foo.com"
default[:mongodb][attr1]="bar"
end

Hope this helps.

Jacobo García López de Araujo
blog: http://robotplaysguitar.com
http://workingwithrails.com/person/13395-jacobo-garc-a

On Wed, Feb 10, 2010 at 4:54 PM, Ruby Newbie rubynewbie@me.com wrote:

Hey, Jacobo.

On Feb 10, 2010, at 5:43 AM, Jacobo García wrote:

What are you using to set the value (set or default) in the attributes
file? I guess that you are using set

All attributes are set with ‘default’, like so…
default[:mongodb][:platform] = 'linux’
default[:mongodb][:arch] = 'x86_64’
default[:mongodb][:version] = ‘1.2.2’

Do you know of any way besides the web GUI to set node-level attributes? The fact that I am not managing to set them from the web interface is not as concerning as the fact that there seems to be no “best practice” for defining a node – that is, defining both its role(s), and the particular attribute values it doesn’t share with other nodes that play the same role.

Thanks for responding,
Ruby newbie.


#5

Seems like your particular case could be handled with a search, and a special node attribute in the recipe. collect on the attribute and subtract values that match the current host. This is assuming that mongo wants to know about all the other mongos out there.

If its the pair then you set it as a case statement.

Or you do it in a role attribute override. In the role you can just set an attribute that has the hosts name.

You could also use a role and a search to limit it to only members in the role that have the attribute.

Yet another way to do it would be to use the built in template specificity for your templates and hardcode the neighbor in each hosts template.

timtowtdi!

personally i favor making the recipes as intelligent as possible, and when that fails using role attributes for this sorta stuff. think this all depends your implementation/site and goals.

On Feb 10, 2010, at 9:32 AM, Jacobo García wrote:

I don’t think there’s a best practice at all in setting values, what
I’d do in your case is setting these values as default, then changing
then in the UI per machine basis.

Other option is setting them based on fqdn on atributtes defined.
Something like this:

case fqdn
when "host1.foo.com"
default[:mongodb][attr1]="foo"
when "host2.foo.com"
default[:mongodb][attr1]="bar"
end

Hope this helps.

Jacobo García López de Araujo
blog: http://robotplaysguitar.com
http://workingwithrails.com/person/13395-jacobo-garc-a

On Wed, Feb 10, 2010 at 4:54 PM, Ruby Newbie rubynewbie@me.com wrote:

Hey, Jacobo.

On Feb 10, 2010, at 5:43 AM, Jacobo García wrote:

What are you using to set the value (set or default) in the attributes
file? I guess that you are using set

All attributes are set with ‘default’, like so…
default[:mongodb][:platform] = 'linux’
default[:mongodb][:arch] = 'x86_64’
default[:mongodb][:version] = ‘1.2.2’

Do you know of any way besides the web GUI to set node-level attributes? The fact that I am not managing to set them from the web interface is not as concerning as the fact that there seems to be no “best practice” for defining a node – that is, defining both its role(s), and the particular attribute values it doesn’t share with other nodes that play the same role.

Thanks for responding,
Ruby newbie.