Accessing environment attributes in cookbooks

Hi,

I’m new to Chef and am trying to migrate my existing infrastructure. Sorry
if this is explained in the docs or elsewhere, but I’ve not been able to
find it.

I have two Chef environments, dev and prod, and want to specify file paths
in a cookbook that have a different parent directory based on the
environment. When I try to access the environment attribute in my cookbook,
however, all I get is ‘nil’.

For example, in my “dev” environment’s JSON file, I have


“default_attributes”: {
“my_attr”: “/my/path”
},

And I can verify my_attr is defined in
https://manage.opscode.com/environments/dev. If I do a knife node show dev_all it shows the proper environment, role, run list, and recipe. In
that recipe’s attributes/default.rb, I have:

Chef::Log.info(’---------------’)
Chef::Log.info(node.chef_environment)
Chef::Log.info(node[:my_attr])
Chef::Log.info(Chef::Environment.load(node.chef_environment).default_attributes[‘my_attr’])
Chef::Log.info(’---------------’)

When I run a vagrant provision, it prints:

$ rvmsudo vagrant provision
[default] Running provisioner: Vagrant::Provisioners::ChefClient…
[default] Creating folder to hold client key…
[default] Uploading chef client validation key…
[default] Generating chef JSON and uploading…
[default] Running chef-client…
stdin: is not a tty
[2012-12-26T06:52:26+00:00] INFO: *** Chef 10.16.2 ***
[2012-12-26T06:52:27+00:00] INFO: Run List is [role[web]]
[2012-12-26T06:52:27+00:00] INFO: Run List expands to [vine_web]
[2012-12-26T06:52:28+00:00] INFO: Starting Chef Run for dev_all
[2012-12-26T06:52:28+00:00] INFO: Running start handlers
[2012-12-26T06:52:28+00:00] INFO: Start handlers complete.
[2012-12-26T06:52:29+00:00] INFO: Loading cookbooks [build-essential,
nginx, ohai, vine_web]
[2012-12-26T06:52:29+00:00] INFO: ---------------
[2012-12-26T06:52:29+00:00] INFO: dev
[2012-12-26T06:52:29+00:00] INFO: nil
[2012-12-26T06:52:29+00:00] INFO: /my/path
[2012-12-26T06:52:29+00:00] INFO: ---------------
[2012-12-26T06:52:31+00:00] INFO: Chef Run complete in 3.026496384 seconds
[2012-12-26T06:52:31+00:00] INFO: Running report handlers
[2012-12-26T06:52:31+00:00] INFO: Report handlers complete

I’m confused because my node defintiely has the right environment, and the
environment definitely has the right attribute, but the attribute hasn’t
been assigned to the node by the time my cookbook runs.

Is this the expected behavior, perhaps due to the order in which things
happen? If no, what have I done wrong?

Is my workaround the right thing to be doing? It took quite a bit of
googling before I stumbled into the Chef docs and thought to try that. If
yes, is there somewhere in the docs I can make a note of this?

Thanks in advance, and happy holidays!

/~s

Hi Steven,

You've placed your debugging code in the attributes/default.rb file,
this gets evaluated at compile time.

Have you tried placing the same debugging code in the
recipes/default.rb (or somewhere like that) where the debugging
statement will show what the value of an attribute is at the execution
phase?

-Mike

On Wed, Dec 26, 2012 at 2:11 AM, Steven Lehrburger lehrburger@gmail.com wrote:

Hi,

I'm new to Chef and am trying to migrate my existing infrastructure. Sorry
if this is explained in the docs or elsewhere, but I've not been able to
find it.

I have two Chef environments, dev and prod, and want to specify file paths
in a cookbook that have a different parent directory based on the
environment. When I try to access the environment attribute in my cookbook,
however, all I get is 'nil'.

For example, in my "dev" environment's JSON file, I have

...
"default_attributes": {
"my_attr": "/my/path"
},
...

And I can verify my_attr is defined in
Sign In - Chef Manage. If I do a knife node show dev_all it shows the proper environment, role, run list, and recipe. In
that recipe's attributes/default.rb, I have:

Chef::Log.info('---------------')
Chef::Log.info(node.chef_environment)
Chef::Log.info(node[:my_attr])
Chef::Log.info(Chef::Environment.load(node.chef_environment).default_attributes['my_attr'])
Chef::Log.info('---------------')

When I run a vagrant provision, it prints:

$ rvmsudo vagrant provision
[default] Running provisioner: Vagrant::Provisioners::ChefClient...
[default] Creating folder to hold client key...
[default] Uploading chef client validation key...
[default] Generating chef JSON and uploading...
[default] Running chef-client...
stdin: is not a tty
[2012-12-26T06:52:26+00:00] INFO: *** Chef 10.16.2 ***
[2012-12-26T06:52:27+00:00] INFO: Run List is [role[web]]
[2012-12-26T06:52:27+00:00] INFO: Run List expands to [vine_web]
[2012-12-26T06:52:28+00:00] INFO: Starting Chef Run for dev_all
[2012-12-26T06:52:28+00:00] INFO: Running start handlers
[2012-12-26T06:52:28+00:00] INFO: Start handlers complete.
[2012-12-26T06:52:29+00:00] INFO: Loading cookbooks [build-essential, nginx,
ohai, vine_web]
[2012-12-26T06:52:29+00:00] INFO: ---------------
[2012-12-26T06:52:29+00:00] INFO: dev
[2012-12-26T06:52:29+00:00] INFO: nil
[2012-12-26T06:52:29+00:00] INFO: /my/path
[2012-12-26T06:52:29+00:00] INFO: ---------------
[2012-12-26T06:52:31+00:00] INFO: Chef Run complete in 3.026496384 seconds
[2012-12-26T06:52:31+00:00] INFO: Running report handlers
[2012-12-26T06:52:31+00:00] INFO: Report handlers complete

I'm confused because my node defintiely has the right environment, and the
environment definitely has the right attribute, but the attribute hasn't
been assigned to the node by the time my cookbook runs.

Is this the expected behavior, perhaps due to the order in which things
happen? If no, what have I done wrong?

Is my workaround the right thing to be doing? It took quite a bit of
googling before I stumbled into the Chef docs and thought to try that. If
yes, is there somewhere in the docs I can make a note of this?

Thanks in advance, and happy holidays!

/~s

On Wednesday, December 26, 2012 at 8:00 AM, Mike wrote:

Hi Steven,

You've placed your debugging code in the attributes/default.rb file,
this gets evaluated at compile time.

Have you tried placing the same debugging code in the
recipes/default.rb (or somewhere like that) where the debugging
statement will show what the value of an attribute is at the execution
phase?

-Mike
A slightly longer explanation:

Attributes from roles and environments are not applied to the node until after attributes files have all been evaluated. In Chef 11, this has been changed and you will be able to use role/environment attributes in attributes files.

--
Daniel DeLeo

Ok, what he said. :slight_smile:

On Wed, Dec 26, 2012 at 11:07 AM, Daniel DeLeo dan@kallistec.com wrote:

On Wednesday, December 26, 2012 at 8:00 AM, Mike wrote:

Hi Steven,

You've placed your debugging code in the attributes/default.rb file,
this gets evaluated at compile time.

Have you tried placing the same debugging code in the
recipes/default.rb (or somewhere like that) where the debugging
statement will show what the value of an attribute is at the execution
phase?

-Mike

A slightly longer explanation:

Attributes from roles and environments are not applied to the node until
after attributes files have all been evaluated. In Chef 11, this has been
changed and you will be able to use role/environment attributes in
attributes files.

--
Daniel DeLeo

Mike and Daniel, thanks for the responses, and that makes sense about the
attributes files. I did try logging from my cookbook's recipes/default.rb
file, but my environment attribute was being evaluated as an empty string.

For example, with this in my environment's JSON file:

"default_attributes": {
"my_attr": "/my/path"
},

Then if I put this in my attributes/default.rb file:

default['my_cookbook']['cookbook_dir'] = "#{node[: my_attr]}/some/directory"

And then log it like this in my recipes/default.rb:

Chef::Log.info(node[:my_attr])
Chef::Log.info(node['my_cookbook']['cookbook_dir'])

Then it logs:

INFO: /my/path
INFO: /some/directory

And not:

INFO: /my/path
INFO: /my/path/some/directory

Which is what I want. I would guess I'm just not using the proper syntax to
define my attribute? But I've tried it with everything I can think of, and
it's fine if I have to explicitly load the environment until Chef 11 :slight_smile:

Thanks!

/~s

On Wed, Dec 26, 2012 at 11:09 AM, Mike miketheman@gmail.com wrote:

Ok, what he said. :slight_smile:

On Wed, Dec 26, 2012 at 11:07 AM, Daniel DeLeo dan@kallistec.com wrote:

On Wednesday, December 26, 2012 at 8:00 AM, Mike wrote:

Hi Steven,

You've placed your debugging code in the attributes/default.rb file,
this gets evaluated at compile time.

Have you tried placing the same debugging code in the
recipes/default.rb (or somewhere like that) where the debugging
statement will show what the value of an attribute is at the execution
phase?

-Mike

A slightly longer explanation:

Attributes from roles and environments are not applied to the node until
after attributes files have all been evaluated. In Chef 11, this has been
changed and you will be able to use role/environment attributes in
attributes files.

--
Daniel DeLeo

On Wednesday, December 26, 2012 at 11:16 AM, Steven Lehrburger wrote:

Then if I put this in my attributes/default.rb file:

default['my_cookbook']['cookbook_dir'] = "#{node[: my_attr]}/some/directory"

That's what I was getting at with my explanation earlier. In Chef 10.x (down to 0.8.x), the attribute precedence described here:

http://docs.opscode.com/essentials_cookbook_attribute_files_attribute_precedence.html

is implemented by the order in which the various attribute sources are merged in. Since attribute files are lower precedence than roles and environments, they are not merged in until later so they're invisible to attributes files. Your best bet is to move code that computes attributes based on other attributes into your recipes for now.

As mentioned before, Chef 11 fixes this so the code snippet you posted would work as expected.

Which is what I want. I would guess I'm just not using the proper syntax to define my attribute? But I've tried it with everything I can think of, and it's fine if I have to explicitly load the environment until Chef 11 :slight_smile:

Thanks!

/~s

--
Daniel DeLeo

to be able to specify something like "#{node[: my_attr]}/some/directory" in
an attribute file, you'll have to wait for chef 11.

you can do the same thing in your recipe until then:
node.default['my_cookbook']['cookbook_dir'] = "#{node[: my_attr
]}/some/directory"

On Wed, Dec 26, 2012 at 2:16 PM, Steven Lehrburger lehrburger@gmail.comwrote:

Mike and Daniel, thanks for the responses, and that makes sense about the
attributes files. I did try logging from my cookbook's recipes/default.rb
file, but my environment attribute was being evaluated as an empty string.

For example, with this in my environment's JSON file:

"default_attributes": {
"my_attr": "/my/path"
},

Then if I put this in my attributes/default.rb file:

default['my_cookbook']['cookbook_dir'] = "#{node[: my_attr
]}/some/directory"

And then log it like this in my recipes/default.rb:

Chef::Log.info(node[:my_attr])
Chef::Log.info(node['my_cookbook']['cookbook_dir'])

Then it logs:

INFO: /my/path
INFO: /some/directory

And not:

INFO: /my/path
INFO: /my/path/some/directory

Which is what I want. I would guess I'm just not using the proper syntax
to define my attribute? But I've tried it with everything I can think of,
and it's fine if I have to explicitly load the environment until Chef 11 :slight_smile:

Thanks!

/~s

On Wed, Dec 26, 2012 at 11:09 AM, Mike miketheman@gmail.com wrote:

Ok, what he said. :slight_smile:

On Wed, Dec 26, 2012 at 11:07 AM, Daniel DeLeo dan@kallistec.com wrote:

On Wednesday, December 26, 2012 at 8:00 AM, Mike wrote:

Hi Steven,

You've placed your debugging code in the attributes/default.rb file,
this gets evaluated at compile time.

Have you tried placing the same debugging code in the
recipes/default.rb (or somewhere like that) where the debugging
statement will show what the value of an attribute is at the execution
phase?

-Mike

A slightly longer explanation:

Attributes from roles and environments are not applied to the node until
after attributes files have all been evaluated. In Chef 11, this has
been
changed and you will be able to use role/environment attributes in
attributes files.

--
Daniel DeLeo

Ah, ok, that makes sense. I had looked at that precedence list and tried
using override_attributes in my environment, but of course that didn't work
either since those get merged even later.

Thanks again!

/~s

On Wed, Dec 26, 2012 at 2:43 PM, Jesse Campbell hikeit@gmail.com wrote:

to be able to specify something like "#{node[: my_attr]}/some/directory"in an attribute file, you'll have to wait for chef 11.

you can do the same thing in your recipe until then:
node.default['my_cookbook']['cookbook_dir'] = "#{node[: my_attr
]}/some/directory"

On Wed, Dec 26, 2012 at 2:16 PM, Steven Lehrburger lehrburger@gmail.comwrote:

Mike and Daniel, thanks for the responses, and that makes sense about the
attributes files. I did try logging from my cookbook's recipes/default.rb
file, but my environment attribute was being evaluated as an empty string.

For example, with this in my environment's JSON file:

"default_attributes": {
"my_attr": "/my/path"
},

Then if I put this in my attributes/default.rb file:

default['my_cookbook']['cookbook_dir'] = "#{node[: my_attr
]}/some/directory"

And then log it like this in my recipes/default.rb:

Chef::Log.info(node[:my_attr])
Chef::Log.info(node['my_cookbook']['cookbook_dir'])

Then it logs:

INFO: /my/path
INFO: /some/directory

And not:

INFO: /my/path
INFO: /my/path/some/directory

Which is what I want. I would guess I'm just not using the proper syntax
to define my attribute? But I've tried it with everything I can think of,
and it's fine if I have to explicitly load the environment until Chef 11 :slight_smile:

Thanks!

/~s

On Wed, Dec 26, 2012 at 11:09 AM, Mike miketheman@gmail.com wrote:

Ok, what he said. :slight_smile:

On Wed, Dec 26, 2012 at 11:07 AM, Daniel DeLeo dan@kallistec.com
wrote:

On Wednesday, December 26, 2012 at 8:00 AM, Mike wrote:

Hi Steven,

You've placed your debugging code in the attributes/default.rb file,
this gets evaluated at compile time.

Have you tried placing the same debugging code in the
recipes/default.rb (or somewhere like that) where the debugging
statement will show what the value of an attribute is at the execution
phase?

-Mike

A slightly longer explanation:

Attributes from roles and environments are not applied to the node
until
after attributes files have all been evaluated. In Chef 11, this has
been
changed and you will be able to use role/environment attributes in
attributes files.

--
Daniel DeLeo