# Using env attr to override a default

**URL:** <https://discourse.chef.io/t/using-env-attr-to-override-a-default/2067>\
**Category:** Chef Infra (archive)\
**Created:** [September 27, 2011, 4:49am UTC](https://discourse.chef.io/t/using-env-attr-to-override-a-default/2067 "2011-09-27T04:49:21Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![Kallen](https://sea2.discourse-cdn.com/flex016/user_avatar/discourse.chef.io/kallen/32/1049_2.png) [@Kallen](https://discourse.chef.io/u/Kallen)\
**Post date:** [September 27, 2011, 4:49am UTC](https://discourse.chef.io/t/using-env-attr-to-override-a-default/2067/1 "2011-09-27T04:49:21Z")

</div>

hello. after many, many years of cfengine, i’m wading thru a learning  
phase with chef, and loving it. bear with me while i get a handle on  
this. i’m trying to override an attribute in the postfix cookbook using  
an environment attribute. which cookbook it is doesn’t matter. it’s  
something fundamental i’m trying to grasp, and this is a simple example.

let’s say for my prod environment i want my postfix clients to use a  
certain mail relay, and for my dev environment i want them to use  
another. in the postfix cookbook attributes (the lowest precedence), i  
can set defaults.

it’s not working for me, and i’m wondering what i’m doing wrong. what i  
expect to have on my mail client node is a relayhost of  
[mungbeans.dev.dorqtown.com](http://mungbeans.dev.dorqtown.com), but what i’m getting is  
[mailrelay.dev.dorqtown.com](http://mailrelay.dev.dorqtown.com).

first, the prod and dev environments:

```
[chef-repo]$ knife environment show dev
chef_type: environment
cookbook_versions:    
default_attributes:  
  mail-client: 
    relayhost: mungbeans.dev.dorqtown.com
  mail-server: 
    relayhost: [smtp.gmail.com]:587
description: Development environment (dev)
json_class: Chef::Environment
name: dev
override_attributes:  

[chef-repo]$ knife environment show prod
chef_type: environment
cookbook_versions:    
default_attributes:  
  mail-client: 
    relayhost: mailrelay.prod.dorqtown.com
  mail-server: 
    relayhost: [smtp.sendgrid.net]:587
    smtp_fallback_relay: [smtp.gmail.com]:587
description: Production environment
json_class: Chef::Environment
name: prod
override_attributes:  

```

a test node’s run list:

```
[chef-repo]$ knife node show sous-chef1.dev.dorqtown.com -r
run_list: 
    role[base]
    role[dns-client]
    role[mail-client]
    role[syslog-ng-client]
    recipe[toolbin]

[chef-repo]$ knife role show mail-client -a run_list
run_list: recipe[postfix]

```

so, above, we know the “default” recipe is implied. i could’ve written  
this as recipe[postfix::default]. i wonder if this is biting me - in my  
attributes dir, i only have mail-client.rb and mail-server.rb, not  
default.rb. does that matter? i wonder how the chef-client run would  
parse either of those if run\_list isn’t recipe[postfix::mail-client] or  
recipe[postfix::mail-server]. i’m misunderstanding something on the use  
of the attributes dir. but let’s get to it:

the relayhost attribute:

```
[chef-repo]$ grep relayhost cookbooks/postfix/attributes/mail-client.rb
default[:postfix][:relayhost] = "mailrelay.dev.dorqtown.com"

[chef-repo]$ grep relayhost cookbooks/postfix/attributes/mail-server.rb 
default[:postfix][:relayhost] = "[smtp.gmail.com]:587"

```

a relevant portion of the template,  
postfix/templates/default/main.cf.erb. do i need to add logic to the  
template to first check for attribute coming from an env before the  
cookbook attributes file?

```
<% if node[:postfix][:mail_type] == "mail-server" -%>
relayhost = <%= node[:postfix][:relayhost] %>
smtp_fallback_relay = <%= node[:postfix][:relayhost] %>
mynetworks = <%= node[:postfix][:mail_relay_networks] %>
inet_interfaces = all
<% else -%>
relayhost = <%= node[:postfix][:relayhost] %>
mynetworks = <%= node[:postfix][:mail_relay_networks] %>
inet_interfaces = localhost
<% end -%>

```

the resulting [main.cf](http://main.cf) on a client:  
###  
# Generated by Chef for [sous-chef1.dev.dorqtown.com](http://sous-chef1.dev.dorqtown.com)  
# Configured as mail-client  
###  
biff = no  
append\_dot\_mydomain = yes  
myhostname = [sous-chef1.dev.dorqtown.com](http://sous-chef1.dev.dorqtown.com)  
mydomain = [dev.dorqtown.com](http://dev.dorqtown.com)  
myorigin = $myhostname  
smtpd\_banner = $myhostname ESMTP $mail\_name  
alias\_maps = hash:/etc/aliases  
alias\_database = hash:/etc/aliases  
mydestination = [sous-chef1.dev.dorqtown.com](http://sous-chef1.dev.dorqtown.com), sous-chef1, localhost.localdomain, localhost  
relayhost = [mailrelay.dev.dorqtown.com](http://mailrelay.dev.dorqtown.com)  
mynetworks = 127.0.0.0/8  
inet\_interfaces = localhost  
mailbox\_size\_limit = 0  
recipient\_delimiter = +

above, i want the dev env attribute for relayhost, not the default one  
from cookbooks/postfix/attributes/mail-client.rb.

and hmmm… my test node running the mail-server role kept picking up the  
mail-client postfix config UNTIL i removed all attribute files from  
cookbooks/postfix/attributes EXCEPT for server.rb. hmmm. clearly i need  
to be schooled…

thanks a lot,  
kallen

---

<div class="post-metadata">

**Author:** ![AJ\_Christensen](https://sea2.discourse-cdn.com/flex016/user_avatar/discourse.chef.io/aj_christensen/32/525_2.png) [@AJ\_Christensen](https://discourse.chef.io/u/AJ_Christensen)\
**Post date:** [September 27, 2011, 6:59am UTC](https://discourse.chef.io/t/using-env-attr-to-override-a-default/2067/2 "2011-09-27T06:59:50Z")

</div>

Yo,

Your environments attributes are wrong:

On 27 September 2011 17:49, [kallen@groknaut.net](mailto:kallen@groknaut.net) wrote:

> hello. after many, many years of cfengine, i'm wading thru a learning  
> phase with chef, and loving it. bear with me while i get a handle on  
> this. i'm trying to override an attribute in the postfix cookbook using  
> an environment attribute. which cookbook it is doesn't matter. it's  
> something fundamental i'm trying to grasp, and this is a simple example.
> 
> let's say for my prod environment i want my postfix clients to use a  
> certain mail relay, and for my dev environment i want them to use  
> another. in the postfix cookbook attributes (the lowest precedence), i  
> can set defaults.
> 
> it's not working for me, and i'm wondering what i'm doing wrong. what i  
> expect to have on my mail client node is a relayhost of  
> [mungbeans.dev.dorqtown.com](http://mungbeans.dev.dorqtown.com), but what i'm getting is  
> [mailrelay.dev.dorqtown.com](http://mailrelay.dev.dorqtown.com).
> 
> first, the prod and dev environments:
> 
> [chef-repo]$ knife environment show dev  
> chef\_type: environment  
> cookbook\_versions:  
> default\_attributes:  
> mail-client:  
> relayhost: [mungbeans.dev.dorqtown.com](http://mungbeans.dev.dorqtown.com)  
> mail-server:  
> relayhost: [[smtp.gmail.com](http://smtp.gmail.com)]:587  
> description: Development environment (dev)  
> json\_class: Chef::Environment  
> name: dev  
> override\_attributes:

this should be:  
default\_attributes "postfix" =\> { "relayhost" =\> "whatever" }

The attributes are deep merged together onto the node and thus the  
atribute structure must remain the same. Does this make sense?

If you can post the on-disk, ruby version of the environment files I  
can point out the problem, otherwise good luck!

–AJ

> [chef-repo]$ knife environment show prod  
> chef\_type: environment  
> cookbook\_versions:  
> default\_attributes:  
> mail-client:  
> relayhost: [mailrelay.prod.dorqtown.com](http://mailrelay.prod.dorqtown.com)  
> mail-server:  
> relayhost: [[smtp.sendgrid.net](http://smtp.sendgrid.net)]:587  
> smtp\_fallback\_relay: [[smtp.gmail.com](http://smtp.gmail.com)]:587  
> description: Production environment  
> json\_class: Chef::Environment  
> name: prod  
> override\_attributes:
> 
> a test node's run list:
> 
> [chef-repo]$ knife node show [sous-chef1.dev.dorqtown.com](http://sous-chef1.dev.dorqtown.com) -r  
> run\_list:  
> role[base]  
> role[dns-client]  
> role[mail-client]  
> role[syslog-ng-client]  
> recipe[toolbin]
> 
> [chef-repo]$ knife role show mail-client -a run\_list  
> run\_list: recipe[postfix]
> 
> so, above, we know the "default" recipe is implied. i could've written  
> this as recipe[postfix::default]. i wonder if this is biting me - in my  
> attributes dir, i only have mail-client.rb and mail-server.rb, not  
> default.rb. does that matter? i wonder how the chef-client run would  
> parse either of those if run\_list isn't recipe[postfix::mail-client] or  
> recipe[postfix::mail-server]. i'm misunderstanding something on the use  
> of the attributes dir. but let's get to it:
> 
> the relayhost attribute:
> 
> [chef-repo]$ grep relayhost cookbooks/postfix/attributes/mail-client.rb  
> default[:postfix][:relayhost] = "[mailrelay.dev.dorqtown.com](http://mailrelay.dev.dorqtown.com)"
> 
> [chef-repo]$ grep relayhost cookbooks/postfix/attributes/mail-server.rb  
> default[:postfix][:relayhost] = "[[smtp.gmail.com](http://smtp.gmail.com)]:587"
> 
> a relevant portion of the template,  
> postfix/templates/default/main.cf.erb. do i need to add logic to the  
> template to first check for attribute coming from an env before the  
> cookbook attributes file?
> 
> \<% if node[:postfix][:mail\_type] == "mail-server" -%\>  
> relayhost = \<%= node[:postfix][:relayhost] %\>  
> smtp\_fallback\_relay = \<%= node[:postfix][:relayhost] %\>  
> mynetworks = \<%= node[:postfix][:mail\_relay\_networks] %\>  
> inet\_interfaces = all  
> \<% else -%\>  
> relayhost = \<%= node[:postfix][:relayhost] %\>  
> mynetworks = \<%= node[:postfix][:mail\_relay\_networks] %\>  
> inet\_interfaces = localhost  
> \<% end -%\>
> 
> the resulting main.cf on a client:
> 
> ### 
> 
> # Generated by Chef for [sous-chef1.dev.dorqtown.com](http://sous-chef1.dev.dorqtown.com)
> 
> # Configured as mail-client
> 
> ### 
> 
> biff = no  
> append\_dot\_mydomain = yes  
> myhostname = [sous-chef1.dev.dorqtown.com](http://sous-chef1.dev.dorqtown.com)  
> mydomain = [dev.dorqtown.com](http://dev.dorqtown.com)  
> myorigin = $myhostname  
> smtpd\_banner = $myhostname ESMTP $mail\_name  
> alias\_maps = hash:/etc/aliases  
> alias\_database = hash:/etc/aliases  
> mydestination = [sous-chef1.dev.dorqtown.com](http://sous-chef1.dev.dorqtown.com), sous-chef1, localhost.localdomain, localhost  
> relayhost = [mailrelay.dev.dorqtown.com](http://mailrelay.dev.dorqtown.com)  
> mynetworks = 127.0.0.0/8  
> inet\_interfaces = localhost  
> mailbox\_size\_limit = 0  
> recipient\_delimiter = +
> 
> above, i want the dev env attribute for relayhost, not the default one  
> from cookbooks/postfix/attributes/mail-client.rb.
> 
> and hmmm.. my test node running the mail-server role kept picking up the  
> mail-client postfix config UNTIL i removed all attribute files from  
> cookbooks/postfix/attributes EXCEPT for server.rb. hmmm. clearly i need  
> to be schooled...
> 
> thanks a lot,  
> kallen

---

<div class="post-metadata">

**Author:** ![Kallen](https://sea2.discourse-cdn.com/flex016/user_avatar/discourse.chef.io/kallen/32/1049_2.png) [@Kallen](https://discourse.chef.io/u/Kallen)\
**Post date:** [September 27, 2011, 6:32pm UTC](https://discourse.chef.io/t/using-env-attr-to-override-a-default/2067/3 "2011-09-27T18:32:22Z")

</div>

On Tue, 27 Sep 2011, AJ Christensen wrote:

> Yo,
> 
> Your environments attributes are wrong:
> 
> On 27 September 2011 17:49, [kallen@groknaut.net](mailto:kallen@groknaut.net) wrote:
> 
> > first, the prod and dev environments:
> > 
> > [chef-repo]$ knife environment show dev  
> > chef\_type: environment  
> > cookbook\_versions:  
> > default\_attributes:  
> > mail-client:  
> > relayhost: [mungbeans.dev.dorqtown.com](http://mungbeans.dev.dorqtown.com)  
> > mail-server:  
> > relayhost: [[smtp.gmail.com](http://smtp.gmail.com)]:587  
> > description: Development environment (dev)  
> > json\_class: Chef::Environment  
> > name: dev  
> > override\_attributes:
> 
> this should be:  
> default\_attributes "postfix" =\> { "relayhost" =\> "whatever" }
> 
> The attributes are deep merged together onto the node and thus the  
> atribute structure must remain the same. Does this make sense?
> 
> If you can post the on-disk, ruby version of the environment files I  
> can point out the problem, otherwise good luck!

i can show you the json version of the env files. i was trying to  
cobble together the ruby, but not getting it quickly. for the sake of  
speed i'll show the json. i see what you're saying about attribute  
structure, so i corrected it, i believe. but the client's relayhost  
in main.cf is still picking up the setting from the postfix cookbook  
attr setting rather than the dev env setting.

[chef-repo]$ cat environments/dev.json  
{  
"name": "dev",  
"default\_attributes": {  
"postfix": {  
"mail-server": {  
"relayhost": "[[outbound.mailhop.org](http://outbound.mailhop.org)],[[smtp.gmail.com](http://smtp.gmail.com)]:587"  
},  
"mail-client": {  
"relayhost": "[mungbeans.dev.dorqtown.com](http://mungbeans.dev.dorqtown.com)"  
}  
}  
},  
"json\_class": "Chef::Environment",  
"description": "Development environment (dev)",  
"chef\_type": "environment"  
}

[chef-repo]$ knife node show [sous-chef1.dev.dorqtown.com](http://sous-chef1.dev.dorqtown.com) -r  
run\_list: role[mail-client]

[sous-chef1-dev ~]# grep relayhost /etc/postfix/main.cf  
relayhost = [mailrelay.dev.dorqtown.com](http://mailrelay.dev.dorqtown.com)

where to look?

---

<div class="post-metadata">

**Author:** ![andi\_abes](https://avatars.discourse-cdn.com/v4/letter/a/dc4da7/32.png) [@andi\_abes](https://discourse.chef.io/u/andi_abes)\
**Post date:** [September 27, 2011, 9:40pm UTC](https://discourse.chef.io/t/using-env-attr-to-override-a-default/2067/4 "2011-09-27T21:40:10Z")

</div>

silly question - are your nodes actually assigned to the different  
environments?

You've shown that you've created the environments, and the nodes' run lists,  
but not the nodes' environments.  
see for manipulating node's env:  
[http://wiki.opscode.com/display/chef/Environments#Environments-SettingaNode'sEnvironment](http://wiki.opscode.com/display/chef/Environments#Environments-SettingaNode%27sEnvironment)

On Tue, Sep 27, 2011 at 2:32 PM, [kallen@groknaut.net](mailto:kallen@groknaut.net) wrote:

> On Tue, 27 Sep 2011, AJ Christensen wrote:
> 
> > Yo,
> > 
> > Your environments attributes are wrong:
> > 
> > On 27 September 2011 17:49, [kallen@groknaut.net](mailto:kallen@groknaut.net) wrote:
> > 
> > > first, the prod and dev environments:
> > > 
> > > [chef-repo]$ knife environment show dev  
> > > chef\_type: environment  
> > > cookbook\_versions:  
> > > default\_attributes:  
> > > mail-client:  
> > > relayhost: [mungbeans.dev.dorqtown.com](http://mungbeans.dev.dorqtown.com)  
> > > mail-server:  
> > > relayhost: [[smtp.gmail.com](http://smtp.gmail.com)]:587  
> > > description: Development environment (dev)  
> > > json\_class: Chef::Environment  
> > > name: dev  
> > > override\_attributes:
> > 
> > this should be:  
> > default\_attributes "postfix" =\> { "relayhost" =\> "whatever" }
> > 
> > The attributes are deep merged together onto the node and thus the  
> > atribute structure must remain the same. Does this make sense?
> > 
> > If you can post the on-disk, ruby version of the environment files I  
> > can point out the problem, otherwise good luck!
> 
> i can show you the json version of the env files. i was trying to  
> cobble together the ruby, but not getting it quickly. for the sake of  
> speed i'll show the json. i see what you're saying about attribute  
> structure, so i corrected it, i believe. but the client's relayhost  
> in main.cf is still picking up the setting from the postfix cookbook  
> attr setting rather than the dev env setting.
> 
> [chef-repo]$ cat environments/dev.json  
> {  
> "name": "dev",  
> "default\_attributes": {  
> "postfix": {  
> "mail-server": {  
> "relayhost": "[[outbound.mailhop.org](http://outbound.mailhop.org)],[[smtp.gmail.com](http://smtp.gmail.com)]:587"  
> },  
> "mail-client": {  
> "relayhost": "[mungbeans.dev.dorqtown.com](http://mungbeans.dev.dorqtown.com)"  
> }  
> }  
> },  
> "json\_class": "Chef::Environment",  
> "description": "Development environment (dev)",  
> "chef\_type": "environment"  
> }
> 
> [chef-repo]$ knife node show [sous-chef1.dev.dorqtown.com](http://sous-chef1.dev.dorqtown.com) -r  
> run\_list: role[mail-client]
> 
> [sous-chef1-dev ~]# grep relayhost /etc/postfix/main.cf  
> relayhost = [mailrelay.dev.dorqtown.com](http://mailrelay.dev.dorqtown.com)
> 
> where to look?

---

<div class="post-metadata">

**Author:** ![Kallen](https://sea2.discourse-cdn.com/flex016/user_avatar/discourse.chef.io/kallen/32/1049_2.png) [@Kallen](https://discourse.chef.io/u/Kallen)\
**Post date:** [September 27, 2011, 10:04pm UTC](https://discourse.chef.io/t/using-env-attr-to-override-a-default/2067/5 "2011-09-27T22:04:31Z")

</div>

On Tue, 27 Sep 2011, andi abes wrote:

> silly question - are your nodes actually assigned to the different  
> environments?

not silly, cuz i do silly things sometimes. but i think my env is set  
correctly:

test node which i desire to be a mail-client:  
[sous-chef1-dev ~]# grep environment /etc/chef/client.rb  
environment "dev"

again, mail-client should pick up the env override for relayhost  
as "[mungbeans.dev.dorqtown.com](http://mungbeans.dev.dorqtown.com)" instead of the default value from  
the recipe attributes. but it's not.

test node which i desire to be a mail-server:  
[sous-chef2-dev ~]# grep environment /etc/chef/client.rb  
environment "dev"

in debug output, i do see it seeking out env info.  
[Tue, 27 Sep 2011 18:15:50 +0000] DEBUG: Sending HTTP Request via POST to 10.2.7.238:4000/environments/dev/cookbook\_versions  
[Tue, 27 Sep 2011 18:15:51 +0000] DEBUG: Sending HTTP Request via GET to 10.2.7.238:4000/environments/dev

and fwiw, the chef clients are CentOS 5.6, running 0.10.4, RPMs  
from RBEL (e.g. rubygem-chef-0.10.4-1.el5).

i'm running my own chef server, Ubuntu 11.04, 0.10.4-1.

> You've shown that you've created the environments, and the nodes' run lists,  
> but not the nodes' environments.  
> see for manipulating node's env:  
> [http://wiki.opscode.com/display/chef/Environments#Environments-SettingaNode'sEnvironment](http://wiki.opscode.com/display/chef/Environments#Environments-SettingaNode%27sEnvironment)

> On Tue, Sep 27, 2011 at 2:32 PM, [kallen@groknaut.net](mailto:kallen@groknaut.net) wrote:
> 
> > On Tue, 27 Sep 2011, AJ Christensen wrote:
> > 
> > > Yo,
> > > 
> > > Your environments attributes are wrong:
> > > 
> > > On 27 September 2011 17:49, [kallen@groknaut.net](mailto:kallen@groknaut.net) wrote:
> > > 
> > > > first, the prod and dev environments:
> > > > 
> > > > [chef-repo]$ knife environment show dev  
> > > > chef\_type: environment  
> > > > cookbook\_versions:  
> > > > default\_attributes:  
> > > > mail-client:  
> > > > relayhost: [mungbeans.dev.dorqtown.com](http://mungbeans.dev.dorqtown.com)  
> > > > mail-server:  
> > > > relayhost: [[smtp.gmail.com](http://smtp.gmail.com)]:587  
> > > > description: Development environment (dev)  
> > > > json\_class: Chef::Environment  
> > > > name: dev  
> > > > override\_attributes:
> > > 
> > > this should be:  
> > > default\_attributes "postfix" =\> { "relayhost" =\> "whatever" }
> > > 
> > > The attributes are deep merged together onto the node and thus the  
> > > atribute structure must remain the same. Does this make sense?
> > > 
> > > If you can post the on-disk, ruby version of the environment files I  
> > > can point out the problem, otherwise good luck!
> > 
> > i can show you the json version of the env files. i was trying to  
> > cobble together the ruby, but not getting it quickly. for the sake of  
> > speed i'll show the json. i see what you're saying about attribute  
> > structure, so i corrected it, i believe. but the client's relayhost  
> > in main.cf is still picking up the setting from the postfix cookbook  
> > attr setting rather than the dev env setting.
> > 
> > [chef-repo]$ cat environments/dev.json  
> > {  
> > "name": "dev",  
> > "default\_attributes": {  
> > "postfix": {  
> > "mail-server": {  
> > "relayhost": "[[outbound.mailhop.org](http://outbound.mailhop.org)],[[smtp.gmail.com](http://smtp.gmail.com)]:587"  
> > },  
> > "mail-client": {  
> > "relayhost": "[mungbeans.dev.dorqtown.com](http://mungbeans.dev.dorqtown.com)"  
> > }  
> > }  
> > },  
> > "json\_class": "Chef::Environment",  
> > "description": "Development environment (dev)",  
> > "chef\_type": "environment"  
> > }
> > 
> > [chef-repo]$ knife node show [sous-chef1.dev.dorqtown.com](http://sous-chef1.dev.dorqtown.com) -r  
> > run\_list: role[mail-client]
> > 
> > [sous-chef1-dev ~]# grep relayhost /etc/postfix/main.cf  
> > relayhost = [mailrelay.dev.dorqtown.com](http://mailrelay.dev.dorqtown.com)
> > 
> > where to look?

---

<div class="post-metadata">

**Author:** ![Matt\_Ray\_OPSCODE](https://sea2.discourse-cdn.com/flex016/user_avatar/discourse.chef.io/matt_ray_opscode/32/459_2.png) [@Matt\_Ray\_OPSCODE](https://discourse.chef.io/u/Matt_Ray_OPSCODE)\
**Post date:** [September 27, 2011, 10:27pm UTC](https://discourse.chef.io/t/using-env-attr-to-override-a-default/2067/6 "2011-09-27T22:27:16Z")

</div>

Could you show the output of  
knife node show yourmail-server  
knife node show yourmail-server -a postfix  
knife environment show dev  
knife environment show prod

Are any of the roles setting the attributes? Here are the precedence  
rules for reference:  
[http://wiki.opscode.com/display/chef/Attributes#Attributes-Precedence](http://wiki.opscode.com/display/chef/Attributes#Attributes-Precedence)

Thanks,  
Matt Ray  
Senior Technical Evangelist | Opscode Inc.  
[matt@opscode.com](mailto:matt@opscode.com) | (512) 731-2218  
Twitter, IRC, GitHub: mattray

On Tue, Sep 27, 2011 at 5:04 PM, [kallen@groknaut.net](mailto:kallen@groknaut.net) wrote:

> On Tue, 27 Sep 2011, andi abes wrote:
> 
> > silly question - are your nodes actually assigned to the different  
> > environments?
> 
> not silly, cuz i do silly things sometimes. but i think my env is set  
> correctly:
> 
> test node which i desire to be a mail-client:  
> [sous-chef1-dev ~]# grep environment /etc/chef/client.rb  
> environment "dev"
> 
> again, mail-client should pick up the env override for relayhost  
> as "[mungbeans.dev.dorqtown.com](http://mungbeans.dev.dorqtown.com)" instead of the default value from  
> the recipe attributes. but it's not.
> 
> test node which i desire to be a mail-server:  
> [sous-chef2-dev ~]# grep environment /etc/chef/client.rb  
> environment "dev"
> 
> in debug output, i do see it seeking out env info.  
> [Tue, 27 Sep 2011 18:15:50 +0000] DEBUG: Sending HTTP Request via POST to 10.2.7.238:4000/environments/dev/cookbook\_versions  
> [Tue, 27 Sep 2011 18:15:51 +0000] DEBUG: Sending HTTP Request via GET to 10.2.7.238:4000/environments/dev
> 
> and fwiw, the chef clients are CentOS 5.6, running 0.10.4, RPMs  
> from RBEL (e.g. rubygem-chef-0.10.4-1.el5).
> 
> i'm running my own chef server, Ubuntu 11.04, 0.10.4-1.
> 
> > You've shown that you've created the environments, and the nodes' run lists,  
> > but not the nodes' environments.  
> > see for manipulating node's env:  
> > [http://wiki.opscode.com/display/chef/Environments#Environments-SettingaNode'sEnvironment](http://wiki.opscode.com/display/chef/Environments#Environments-SettingaNode%27sEnvironment)
> 
> > On Tue, Sep 27, 2011 at 2:32 PM, [kallen@groknaut.net](mailto:kallen@groknaut.net) wrote:
> > 
> > > On Tue, 27 Sep 2011, AJ Christensen wrote:
> > > 
> > > > Yo,
> > > > 
> > > > Your environments attributes are wrong:
> > > > 
> > > > On 27 September 2011 17:49, [kallen@groknaut.net](mailto:kallen@groknaut.net) wrote:
> > > > 
> > > > > first, the prod and dev environments:
> > > > > 
> > > > > [chef-repo]$ knife environment show dev  
> > > > > chef\_type: environment  
> > > > > cookbook\_versions:  
> > > > > default\_attributes:  
> > > > > mail-client:  
> > > > > relayhost: [mungbeans.dev.dorqtown.com](http://mungbeans.dev.dorqtown.com)  
> > > > > mail-server:  
> > > > > relayhost: [[smtp.gmail.com](http://smtp.gmail.com)]:587  
> > > > > description: Development environment (dev)  
> > > > > json\_class: Chef::Environment  
> > > > > name: dev  
> > > > > override\_attributes:
> > > > 
> > > > this should be:  
> > > > default\_attributes "postfix" =\> { "relayhost" =\> "whatever" }
> > > > 
> > > > The attributes are deep merged together onto the node and thus the  
> > > > atribute structure must remain the same. Does this make sense?
> > > > 
> > > > If you can post the on-disk, ruby version of the environment files I  
> > > > can point out the problem, otherwise good luck!
> > > 
> > > i can show you the json version of the env files. i was trying to  
> > > cobble together the ruby, but not getting it quickly. for the sake of  
> > > speed i'll show the json. i see what you're saying about attribute  
> > > structure, so i corrected it, i believe. but the client's relayhost  
> > > in main.cf is still picking up the setting from the postfix cookbook  
> > > attr setting rather than the dev env setting.
> > > 
> > > [chef-repo]$ cat environments/dev.json  
> > > {  
> > > "name": "dev",  
> > > "default\_attributes": {  
> > > "postfix": {  
> > > "mail-server": {  
> > > "relayhost": "[[outbound.mailhop.org](http://outbound.mailhop.org)],[[smtp.gmail.com](http://smtp.gmail.com)]:587"  
> > > },  
> > > "mail-client": {  
> > > "relayhost": "[mungbeans.dev.dorqtown.com](http://mungbeans.dev.dorqtown.com)"  
> > > }  
> > > }  
> > > },  
> > > "json\_class": "Chef::Environment",  
> > > "description": "Development environment (dev)",  
> > > "chef\_type": "environment"  
> > > }
> > > 
> > > [chef-repo]$ knife node show [sous-chef1.dev.dorqtown.com](http://sous-chef1.dev.dorqtown.com) -r  
> > > run\_list: role[mail-client]
> > > 
> > > [sous-chef1-dev ~]# grep relayhost /etc/postfix/main.cf  
> > > relayhost = [mailrelay.dev.dorqtown.com](http://mailrelay.dev.dorqtown.com)
> > > 
> > > where to look?

---

<div class="post-metadata">

**Author:** ![AJ\_Christensen](https://sea2.discourse-cdn.com/flex016/user_avatar/discourse.chef.io/aj_christensen/32/525_2.png) [@AJ\_Christensen](https://discourse.chef.io/u/AJ_Christensen)\
**Post date:** [September 27, 2011, 10:43pm UTC](https://discourse.chef.io/t/using-env-attr-to-override-a-default/2067/7 "2011-09-27T22:43:21Z")

</div>

Yo,

Thanks for the paste, comments in-line:

On 28 September 2011 07:32, [kallen@groknaut.net](mailto:kallen@groknaut.net) wrote:

> On Tue, 27 Sep 2011, AJ Christensen wrote:
> 
> > Yo,
> > 
> > Your environments attributes are wrong:
> > 
> > On 27 September 2011 17:49, [kallen@groknaut.net](mailto:kallen@groknaut.net) wrote:
> > 
> > > first, the prod and dev environments:
> > > 
> > > [chef-repo]$ knife environment show dev  
> > > chef\_type: environment  
> > > cookbook\_versions:  
> > > default\_attributes:  
> > > mail-client:  
> > > relayhost: [mungbeans.dev.dorqtown.com](http://mungbeans.dev.dorqtown.com)  
> > > mail-server:  
> > > relayhost: [[smtp.gmail.com](http://smtp.gmail.com)]:587  
> > > description: Development environment (dev)  
> > > json\_class: Chef::Environment  
> > > name: dev  
> > > override\_attributes:

> > this should be:  
> > default\_attributes "postfix" =\> { "relayhost" =\> "whatever" }
> > 
> > The attributes are deep merged together onto the node and thus the  
> > atribute structure must remain the same. Does this make sense?
> > 
> > If you can post the on-disk, ruby version of the environment files I  
> > can point out the problem, otherwise good luck!
> 
> i can show you the json version of the env files. i was trying to  
> cobble together the ruby, but not getting it quickly. for the sake of  
> speed i'll show the json. i see what you're saying about attribute  
> structure, so i corrected it, i believe. but the client's relayhost  
> in main.cf is still picking up the setting from the postfix cookbook  
> attr setting rather than the dev env setting.
> 
> [chef-repo]$ cat environments/dev.json  
> {  
> "name": "dev",  
> "default\_attributes": {  
> "postfix": {  
> "mail-server": {  
> "relayhost": "[[outbound.mailhop.org](http://outbound.mailhop.org)],[[smtp.gmail.com](http://smtp.gmail.com)]:587"  
> },  
> "mail-client": {  
> "relayhost": "[mungbeans.dev.dorqtown.com](http://mungbeans.dev.dorqtown.com)"  
> }  
> }  
> },  
> "json\_class": "Chef::Environment",  
> "description": "Development environment (dev)",  
> "chef\_type": "environment"  
> }

This new one is bad too. The structure you want, quote unquote, is:

"default\_attributes": {  
"postfix": { "relayhost" : "[mungbeans.dev.dorqtown.com](http://mungbeans.dev.dorqtown.com)" }  
}

Notice the wildly obvious exclusion of any mention of the "name" of  
your other roles, "mail-server" and "mail-client" - the names of the  
roles are irrelevant. they are _attribute holders_ - you will unlikely  
ever refer to them by name apart from when doing a Search or run\_list  
introspection for dual-behavior.

This whole pattern you're in - setting things globally - is a sure  
sign of a cfengine "expert". In chef, you do _not_ want to be doing  
that configuration - you want to be discovering it. The relay server  
node can expose attributes to the search index, which is exposed to  
all nodes with access. You can simply query for a combination of a  
recipe + particular attribute/value.

I'd suggest using the existing Opscode cookbooks which already  
implement Search for discovery of the local relay master, by toggling  
an attribute.

[https://github.com/opscode/cookbooks/blob/master/postfix/attributes/default.rb#L1](https://github.com/opscode/cookbooks/blob/master/postfix/attributes/default.rb#L1)

e.g.

role postfix\_client defaults postfix.client\_type = "client"  
role postfix\_server defaults postfix.client\_type = "master"

Done.

–AJ

> [chef-repo]$ knife node show [sous-chef1.dev.dorqtown.com](http://sous-chef1.dev.dorqtown.com) -r  
> run\_list: role[mail-client]
> 
> [sous-chef1-dev ~]# grep relayhost /etc/postfix/main.cf  
> relayhost = [mailrelay.dev.dorqtown.com](http://mailrelay.dev.dorqtown.com)
> 
> where to look?

---

<div class="post-metadata">

**Author:** ![Kallen](https://sea2.discourse-cdn.com/flex016/user_avatar/discourse.chef.io/kallen/32/1049_2.png) [@Kallen](https://discourse.chef.io/u/Kallen)\
**Post date:** [September 27, 2011, 11:20pm UTC](https://discourse.chef.io/t/using-env-attr-to-override-a-default/2067/8 "2011-09-27T23:20:48Z")

</div>

On Tue, 27 Sep 2011, Matt Ray wrote:

> Could you show the output of  
> knife node show yourmail-server  
> knife node show yourmail-server -a postfix  
> knife environment show dev  
> knife environment show prod

[chef-repo]$ knife node show [sous-chef2.dev.dorqtown.com](http://sous-chef2.dev.dorqtown.com)  
Node Name: [sous-chef2.dev.dorqtown.com](http://sous-chef2.dev.dorqtown.com)  
Environment: dev  
FQDN: [sous-chef2.dev.dorqtown.com](http://sous-chef2.dev.dorqtown.com)  
IP: 50.19.69.96  
Run List: role[mail-server]  
Roles: mail-server  
Recipes: postfix  
Platform: centos 5.6

[cheftain01]$ knife node show [sous-chef2.dev.dorqtown.com](http://sous-chef2.dev.dorqtown.com) -a postfix  
postfix:  
mail-client:  
relayhost: [mungbeans.dev.dorqtown.com](http://mungbeans.dev.dorqtown.com)  
mail-server:  
relayhost: [[outbound.mailhop.org](http://outbound.mailhop.org)],[[smtp.gmail.com](http://smtp.gmail.com)]:587  
mail\_relay\_networks: 127.0.0.0/8  
mail\_type: mail-client  
mydomain: [dev.dorqtown.com](http://dev.dorqtown.com)  
myhostname: [sous-chef2.dev.dorqtown.com](http://sous-chef2.dev.dorqtown.com)  
myorigin: $myhostname  
relayhost: [mailrelay.dev.dorqtown.com](http://mailrelay.dev.dorqtown.com)  
smtp\_fallback\_relay: [[smtp.gmail.com](http://smtp.gmail.com)]:587  
smtp\_sasl\_auth\_enable: no  
smtp\_sasl\_passwd:  
smtp\_sasl\_password\_maps: hash:/etc/postfix/sasl\_passwd  
smtp\_sasl\_security\_options: noanonymous  
smtp\_sasl\_user\_name:  
smtp\_tls\_cafile: /etc/postfix/cacert.pem  
smtp\_use\_tls: no

[chef-repo]$ knife environment show dev  
chef\_type: environment  
cookbook\_versions:  
default\_attributes:  
postfix:  
mail-client:  
relayhost: [mungbeans.dev.dorqtown.com](http://mungbeans.dev.dorqtown.com)  
mail-server:  
relayhost: [[outbound.mailhop.org](http://outbound.mailhop.org)],[[smtp.gmail.com](http://smtp.gmail.com)]:587  
description: Development environment (dev)  
json\_class: Chef::Environment  
name: dev  
override\_attributes:

[chef-repo]$ knife environment show prod  
chef\_type: environment  
cookbook\_versions:  
default\_attributes:  
mail-client:  
relayhost: [mailrelay.prod.dorqtown.com](http://mailrelay.prod.dorqtown.com)  
mail-server:  
relayhost: [[smtp.sendgrid.net](http://smtp.sendgrid.net)]:587  
smtp\_fallback\_relay: [[outbound.mailhop.org](http://outbound.mailhop.org)],[[smtp.gmail.com](http://smtp.gmail.com)]:587  
description: Production environment  
json\_class: Chef::Environment  
name: prod  
override\_attributes:

> Are any of the roles setting the attributes?

nope. the roles only set the run-list.

> Here are the precedence  
> rules for reference:  
> [http://wiki.opscode.com/display/chef/Attributes#Attributes-Precedence](http://wiki.opscode.com/display/chef/Attributes#Attributes-Precedence)
> 
> Thanks,  
> Matt Ray  
> Senior Technical Evangelist | Opscode Inc.  
> [matt@opscode.com](mailto:matt@opscode.com) | (512) 731-2218  
> Twitter, IRC, GitHub: mattray

---

<div class="post-metadata">

**Author:** ![Kallen](https://sea2.discourse-cdn.com/flex016/user_avatar/discourse.chef.io/kallen/32/1049_2.png) [@Kallen](https://discourse.chef.io/u/Kallen)\
**Post date:** [September 28, 2011, 1:32am UTC](https://discourse.chef.io/t/using-env-attr-to-override-a-default/2067/9 "2011-09-28T01:32:10Z")

</div>

hai, responses inline.

On Wed, 28 Sep 2011, AJ Christensen wrote:

> > [chef-repo]$ cat environments/dev.json  
> > {  
> > "name": "dev",  
> > "default\_attributes": {  
> > "postfix": {  
> > "mail-server": {  
> > "relayhost": "[[outbound.mailhop.org](http://outbound.mailhop.org)],[[smtp.gmail.com](http://smtp.gmail.com)]:587"  
> > },  
> > "mail-client": {  
> > "relayhost": "[mungbeans.dev.dorqtown.com](http://mungbeans.dev.dorqtown.com)"  
> > }  
> > }  
> > },  
> > "json\_class": "Chef::Environment",  
> > "description": "Development environment (dev)",  
> > "chef\_type": "environment"  
> > }
> 
> This new one is bad too. The structure you want, quote unquote, is:
> 
> "default\_attributes": {  
> "postfix": { "relayhost" : "[mungbeans.dev.dorqtown.com](http://mungbeans.dev.dorqtown.com)" }  
> }
> 
> Notice the wildly obvious exclusion of any mention of the "name" of  
> your other roles, "mail-server" and "mail-client" - the names of the  
> roles are irrelevant. they are _attribute holders_ - you will unlikely  
> ever refer to them by name apart from when doing a Search or run\_list  
> introspection for dual-behavior.

ah.. and now that i've corrected the dev env with your feedback  
above, it's working, in that a client's main.cf gets the env relayhost  
rather that the default one from the cookbook. yay!

> This whole pattern you're in - setting things globally - is a sure  
> sign of a cfengine "expert".

ayep. i'm workin' on grokkin' a new config mgmt paradigm here.

> In chef, you do _not_ want to be doing  
> that configuration - you want to be discovering it. The relay server  
> node can expose attributes to the search index, which is exposed to  
> all nodes with access. You can simply query for a combination of a  
> recipe + particular attribute/value.
> 
> I'd suggest using the existing Opscode cookbooks which already  
> implement Search for discovery of the local relay master, by toggling  
> an attribute.
> 
> [https://github.com/opscode/cookbooks/blob/master/postfix/attributes/default.rb#L1](https://github.com/opscode/cookbooks/blob/master/postfix/attributes/default.rb#L1)
> 
> e.g.
> 
> role postfix\_client defaults postfix.client\_type = "client"  
> role postfix\_server defaults postfix.client\_type = "master"

i just ran thru the opscode postfix cookbook from a pristine state,  
and followed jtimberman's blog about "Encrypted Data Bag for Postfix  
SASL Authentication". that helped turn a little light on for me, even  
tho i'm getting a chef client error about smtp\_sasl (i'll poke at that  
later). so i skip the smtp\_sasl bit, and just try to get a vanilla  
postfix master and client.

my postfix master node kept converging as a client until, while using  
jtimberman's "operations master" role, i added an override\_attribute  
to that role as "mail\_type" =\> "master". once i did that, it worked:  
it became a master. (jtimberman, is that missing from your role in this  
blog post?)

now i wonder if i'm still falling back into setting things globally.  
am i? is there a better, more flexible way to do this?

my mail-server role, based on jtimberman's post  
([http://jtimberman.posterous.com/64227128](http://jtimberman.posterous.com/64227128)), sans recipe[postfix::sasl\_auth]:

name "mail-server"  
override\_attributes(  
"postfix" =\> {  
"mail\_type" =\> "master",  
"relayhost" =\> "[[outbound.mailhop.org](http://outbound.mailhop.org)]",  
"smtp\_sasl\_auth\_enable" =\> "no",  
"smtp\_sasl\_passwd" =\> "",  
"smtp\_sasl\_user\_name" =\> ""  
}  
)

practice practice practice.. thanks for your help so far.

kallen

---

<div class="post-metadata">

**Author:** ![AJ\_Christensen](https://sea2.discourse-cdn.com/flex016/user_avatar/discourse.chef.io/aj_christensen/32/525_2.png) [@AJ\_Christensen](https://discourse.chef.io/u/AJ_Christensen)\
**Post date:** [September 28, 2011, 1:46am UTC](https://discourse.chef.io/t/using-env-attr-to-override-a-default/2067/10 "2011-09-28T01:46:23Z")

</div>

Yo,

On 28 September 2011 14:32, [kallen@groknaut.net](mailto:kallen@groknaut.net) wrote:

> hai, responses inline.
> 
> On Wed, 28 Sep 2011, AJ Christensen wrote:
> 
> > > [chef-repo]$ cat environments/dev.json  
> > > {  
> > > "name": "dev",  
> > > "default\_attributes": {  
> > > "postfix": {  
> > > "mail-server": {  
> > > "relayhost": "[[outbound.mailhop.org](http://outbound.mailhop.org)],[[smtp.gmail.com](http://smtp.gmail.com)]:587"  
> > > },  
> > > "mail-client": {  
> > > "relayhost": "[mungbeans.dev.dorqtown.com](http://mungbeans.dev.dorqtown.com)"  
> > > }  
> > > }  
> > > },  
> > > "json\_class": "Chef::Environment",  
> > > "description": "Development environment (dev)",  
> > > "chef\_type": "environment"  
> > > }
> > 
> > This new one is bad too. The structure you want, quote unquote, is:
> > 
> > "default\_attributes": {  
> > "postfix": { "relayhost" : "[mungbeans.dev.dorqtown.com](http://mungbeans.dev.dorqtown.com)" }  
> > }
> > 
> > Notice the wildly obvious exclusion of any mention of the "name" of  
> > your other roles, "mail-server" and "mail-client" - the names of the  
> > roles are irrelevant. they are _attribute holders_ - you will unlikely  
> > ever refer to them by name apart from when doing a Search or run\_list  
> > introspection for dual-behavior.
> 
> ah.. and now that i've corrected the dev env with your feedback  
> above, it's working, in that a client's main.cf gets the env relayhost  
> rather that the default one from the cookbook. yay!
> 
> > This whole pattern you're in - setting things globally - is a sure  
> > sign of a cfengine "expert".
> 
> ayep. i'm workin' on grokkin' a new config mgmt paradigm here.
> 
> > In chef, you do _not_ want to be doing  
> > that configuration - you want to be discovering it. The relay server  
> > node can expose attributes to the search index, which is exposed to  
> > all nodes with access. You can simply query for a combination of a  
> > recipe + particular attribute/value.
> > 
> > I'd suggest using the existing Opscode cookbooks which already  
> > implement Search for discovery of the local relay master, by toggling  
> > an attribute.
> > 
> > [https://github.com/opscode/cookbooks/blob/master/postfix/attributes/default.rb#L1](https://github.com/opscode/cookbooks/blob/master/postfix/attributes/default.rb#L1)
> > 
> > e.g.
> > 
> > role postfix\_client defaults postfix.client\_type = "client"  
> > role postfix\_server defaults postfix.client\_type = "master"
> 
> i just ran thru the opscode postfix cookbook from a pristine state,  
> and followed jtimberman's blog about "Encrypted Data Bag for Postfix  
> SASL Authentication". that helped turn a little light on for me, even  
> tho i'm getting a chef client error about smtp\_sasl (i'll poke at that  
> later). so i skip the smtp\_sasl bit, and just try to get a vanilla  
> postfix master and client.
> 
> my postfix master node kept converging as a client until, while using  
> jtimberman's "operations master" role, i added an override\_attribute  
> to that role as "mail\_type" =\> "master". once i did that, it worked:  
> it became a master. (jtimberman, is that missing from your role in this  
> blog post?)

Sounds like a bug in the blog post, for sure.

> now i wonder if i'm still falling back into setting things globally.  
> am i? is there a better, more flexible way to do this?

I'd advise, for a beginner attempting to concrete some ideology, a  
postfix\_master role that defaults the attribute postfix.mail\_type to  
"master".

You can easily include this role in another role to turn it into a  
postfix master, instead of cluttering up your "mail-server" role which  
theoretically could be extended to support multiple portions of the  
Postfix system; maybe a spam filter, rewriter server or handling final  
delivery.

It also keeps all postfix master related settings in a single file /  
attribute setting for ease of management.

You can also use the environmental run lists functionality of  
environments to say, consolidate the postfix-master role automatically  
onto any mail-server role in the development environment (or similar).

> my mail-server role, based on jtimberman's post  
> ([http://jtimberman.posterous.com/64227128](http://jtimberman.posterous.com/64227128)), sans recipe[postfix::sasl\_auth]:

postfix-master.rb:

name "postfix-master"  
default\_attributes(  
"postfix" =\> {  
"mail\_type" =\> "master",  
"relayhost" =\> "[[outbound.mailhop.org](http://outbound.mailhop.org)]"  
}  
)

mail-server.rb:  
name "mail-server"  
default\_attributes(  
"postfix" =\> {  
"smtp\_sasl\_auth\_enable" =\> "no",  
"smtp\_sasl\_passwd" =\> "",  
"smtp\_sasl\_user\_name" =\> ""  
}  
)

I hope this helps.

–AJ
