# Environment attributes in Cookbooks

**URL:** <https://discourse.chef.io/t/environment-attributes-in-cookbooks/6680>\
**Category:** Chef Infra (archive)\
**Created:** [June 19, 2015, 2:22pm UTC](https://discourse.chef.io/t/environment-attributes-in-cookbooks/6680 "2015-06-19T14:22:43Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![Douglas\_Garstang](https://avatars.discourse-cdn.com/v4/letter/d/c2a13f/32.png) [@Douglas\_Garstang](https://discourse.chef.io/u/Douglas_Garstang)\
**Post date:** [June 19, 2015, 2:22pm UTC](https://discourse.chef.io/t/environment-attributes-in-cookbooks/6680/1 "2015-06-19T14:22:43Z")

</div>

If I was going to put move my environmental attributes into cookbooks…

When deployed to an instance, the top level run list would need to include  
the environmental run list. That’s ok.

However, when testing, this would mean that each cookbook would need to  
either include the environment cookbook (ie #include\_recipe “env-dev”) and  
refer to it in the metadata.rb and Berksfile files, OR I’d have to  
specifically put each attribute into the Vagrantfile’s json data.

This might work for simple cookbooks, but it would mean the cookbook is not  
being effectively tested. The attributes I’m testing against aren’t what  
really gets deployed to an instance. I also have to maintain two copies of  
the attributes and the worst case scenario is where the attribute is set in  
both places but the value in the Vagranrfile is incorrect and therefore  
leads to the incorrect assumption that the cookbook is working correctly.

For my base cookbook it gets even worse. It would need to have every single  
attribute from every cookbook it includes put into the Vagrantfile’s json  
data. This just does not scale.

It doesn’t seem like the benefits of gaining some revision control outweigh  
the maintenance disadvantages here. For all those that espouse the use of  
putting environment attributes into a cookbook how do you get around this?

Doug

---

<div class="post-metadata">

**Author:** ![tknerr](https://sea2.discourse-cdn.com/flex016/user_avatar/discourse.chef.io/tknerr/32/21_2.png) [@tknerr](https://discourse.chef.io/u/tknerr)\
**Post date:** [June 21, 2015, 1:39pm UTC](https://discourse.chef.io/t/environment-attributes-in-cookbooks/6680/2 "2015-06-21T13:39:55Z")

</div>

Hey Doug,

I believe you first have to decide for what purpose you actually want to  
use Chef environments, and this decision then limits the options for  
technically implementing this.

For me the key decision is:  
a) if you are going to use the berkflow / the environment cookbook pattern  
with `berks apply environment`, then this means you will end up with one  
environment per node  
b) if you are going to use environments for dev / test / staging / prod  
stages, you probably want to share environmental attributes across many  
nodes

Personally, I prefer b) and try to stick to the following principles:

- use environments only for supplying environment specific data
- don't use environment for composing a node's run list or other node  
specific internals
- instead I use a single "top-level" wrapper cookbook per node, which
  - glues together the run list
  - sets attributes for configuring the wrapped cookbooks
  - sometimes adds addional glue code
  - locks the whole cookbook dependency graph via metadata.rb (so I can do  
it per node here and not need to use an environment for that)
  - defines the interface for the user (i.e. README, attributes, etc..)

- the environments should contain only environment specific attribute  
overrides + the versions of the "top-level" cookbooks

Since I'm wrapping other cookbooks and setting their attributes in (the  
"top-level" cookbook's) recipe, I'm sometimes faced with the "computed  
attributes problem". I tackle that by reloading the wrapped attributes file  
between setting the attributes and including the recipe, e.g. here:  
[https://docs.chef.io/chef/essentials\_cookbook\_recipes.html#reload-attributes](https://docs.chef.io/chef/essentials_cookbook_recipes.html#reload-attributes)

Also, my environments often share the same data, i.e. common attributes  
that are environmental data but still the same for many or even all of my  
environments. Ranjib recently posted a nice way on how to deal with that:

> <https://gist.github.com/ranjib/2f7e1482a3ac8f6e5bfc>

Hope that helps or at least gives you some more ideas. There are many ways  
and even more opinions 😉

Cheers,  
Torben

On Fri, Jun 19, 2015 at 4:22 PM, Douglas Garstang [doug.garstang@gmail.com](mailto:doug.garstang@gmail.com)  
wrote:

> If I was going to put move my environmental attributes into cookbooks...
> 
> When deployed to an instance, the top level run list would need to include  
> the environmental run list. That's ok.
> 
> However, when testing, this would mean that each cookbook would need to  
> either include the environment cookbook (ie #include\_recipe "env-dev") and  
> refer to it in the metadata.rb and Berksfile files, OR I'd have to  
> specifically put each attribute into the Vagrantfile's json data.
> 
> This might work for simple cookbooks, but it would mean the cookbook is  
> not being effectively tested. The attributes I'm testing against aren't  
> what really gets deployed to an instance. I also have to maintain two  
> copies of the attributes and the worst case scenario is where the attribute  
> is set in both places but the value in the Vagranrfile is incorrect and  
> therefore leads to the incorrect assumption that the cookbook is working  
> correctly.
> 
> For my base cookbook it gets even worse. It would need to have every  
> single attribute from every cookbook it includes put into the Vagrantfile's  
> json data. This just does not scale.
> 
> It doesn't seem like the benefits of gaining some revision control  
> outweigh the maintenance disadvantages here. For all those that espouse the  
> use of putting environment attributes into a cookbook how do you get around  
> this?
> 
> Doug

---

<div class="post-metadata">

**Author:** ![Yoshi\_Spendiff](https://sea2.discourse-cdn.com/flex016/user_avatar/discourse.chef.io/yoshi_spendiff/32/13_2.png) [@Yoshi\_Spendiff](https://discourse.chef.io/u/Yoshi_Spendiff)\
**Post date:** [June 22, 2015, 3:33pm UTC](https://discourse.chef.io/t/environment-attributes-in-cookbooks/6680/3 "2015-06-22T15:33:43Z")

</div>

Hi Torben,

Not sure if you know, but the A/B choice you stated above aren't actually  
mutually exclusive. If you want to use berkflow/berks apply to apply  
cookbook version locks to an environment that doesn't stop you supplying  
normal environment variables to the environment. Berkflow/berks apply  
doesn't change any attributes other than the version locks.

Cheers,  
Yoshi

On Sun, Jun 21, 2015 at 6:39 AM, Torben Knerr [mail@tknerr.de](mailto:mail@tknerr.de) wrote:

> Hey Doug,
> 
> I believe you first have to decide for what purpose you actually want to  
> use Chef environments, and this decision then limits the options for  
> technically implementing this.
> 
> For me the key decision is:  
> a) if you are going to use the berkflow / the environment cookbook pattern  
> with `berks apply environment`, then this means you will end up with one  
> environment per node  
> b) if you are going to use environments for dev / test / staging / prod  
> stages, you probably want to share environmental attributes across many  
> nodes
> 
> Personally, I prefer b) and try to stick to the following principles:
> 
> - use environments only for supplying environment specific data
> - don't use environment for composing a node's run list or other node  
> specific internals
> - instead I use a single "top-level" wrapper cookbook per node, which
> - glues together the run list
> - sets attributes for configuring the wrapped cookbooks
> - sometimes adds addional glue code
> - locks the whole cookbook dependency graph via metadata.rb (so I can  
> do it per node here and not need to use an environment for that)
> - defines the interface for the user (i.e. README, attributes, etc..)
> 
> - the environments should contain only environment specific attribute  
> overrides + the versions of the "top-level" cookbooks
> 
> Since I'm wrapping other cookbooks and setting their attributes in (the  
> "top-level" cookbook's) recipe, I'm sometimes faced with the "computed  
> attributes problem". I tackle that by reloading the wrapped attributes file  
> between setting the attributes and including the recipe, e.g. here:
> 
> [https://docs.chef.io/chef/essentials\_cookbook\_recipes.html#reload-attributes](https://docs.chef.io/chef/essentials_cookbook_recipes.html#reload-attributes)
> 
> Also, my environments often share the same data, i.e. common attributes  
> that are environmental data but still the same for many or even all of my  
> environments. Ranjib recently posted a nice way on how to deal with that:  
> [Consuming common datra across environments using Chef's ruby environment DSL · GitHub](https://gist.github.com/ranjib/2f7e1482a3ac8f6e5bfc)
> 
> Hope that helps or at least gives you some more ideas. There are many ways  
> and even more opinions 😉
> 
> Cheers,  
> Torben
> 
> On Fri, Jun 19, 2015 at 4:22 PM, Douglas Garstang \<[doug.garstang@gmail.com](mailto:doug.garstang@gmail.com)
> 
> > wrote:
> 
> > If I was going to put move my environmental attributes into cookbooks...
> > 
> > When deployed to an instance, the top level run list would need to  
> > include the environmental run list. That's ok.
> > 
> > However, when testing, this would mean that each cookbook would need to  
> > either include the environment cookbook (ie #include\_recipe "env-dev") and  
> > refer to it in the metadata.rb and Berksfile files, OR I'd have to  
> > specifically put each attribute into the Vagrantfile's json data.
> > 
> > This might work for simple cookbooks, but it would mean the cookbook is  
> > not being effectively tested. The attributes I'm testing against aren't  
> > what really gets deployed to an instance. I also have to maintain two  
> > copies of the attributes and the worst case scenario is where the attribute  
> > is set in both places but the value in the Vagranrfile is incorrect and  
> > therefore leads to the incorrect assumption that the cookbook is working  
> > correctly.
> > 
> > For my base cookbook it gets even worse. It would need to have every  
> > single attribute from every cookbook it includes put into the Vagrantfile's  
> > json data. This just does not scale.
> > 
> > It doesn't seem like the benefits of gaining some revision control  
> > outweigh the maintenance disadvantages here. For all those that espouse the  
> > use of putting environment attributes into a cookbook how do you get around  
> > this?
> > 
> > Doug

--  
Yoshi Spendiff  
Ops Engineer  
Indochino  
Mobile: +1 778 952 2025  
Email: [yoshi.spendiff@indochino.com](mailto:yoshi.spendiff@indochino.com)

---

<div class="post-metadata">

**Author:** ![Douglas\_Garstang](https://avatars.discourse-cdn.com/v4/letter/d/c2a13f/32.png) [@Douglas\_Garstang](https://discourse.chef.io/u/Douglas_Garstang)\
**Post date:** [June 22, 2015, 3:51pm UTC](https://discourse.chef.io/t/environment-attributes-in-cookbooks/6680/4 "2015-06-22T15:51:46Z")

</div>

Torben,

We're definitely going along the path of using environments for dev, qa,  
stage, prod etc. What you posted above was really useful, except that it  
doesn't help with the testing issue which is kinda the blocker here. If I  
can't test it, well I can't really use it. ☹

Doug.

On Sun, Jun 21, 2015 at 6:39 AM, Torben Knerr [mail@tknerr.de](mailto:mail@tknerr.de) wrote:

> Hey Doug,
> 
> I believe you first have to decide for what purpose you actually want to  
> use Chef environments, and this decision then limits the options for  
> technically implementing this.
> 
> For me the key decision is:  
> a) if you are going to use the berkflow / the environment cookbook pattern  
> with `berks apply environment`, then this means you will end up with one  
> environment per node  
> b) if you are going to use environments for dev / test / staging / prod  
> stages, you probably want to share environmental attributes across many  
> nodes
> 
> Personally, I prefer b) and try to stick to the following principles:
> 
> - use environments only for supplying environment specific data
> - don't use environment for composing a node's run list or other node  
> specific internals
> - instead I use a single "top-level" wrapper cookbook per node, which
> - glues together the run list
> - sets attributes for configuring the wrapped cookbooks
> - sometimes adds addional glue code
> - locks the whole cookbook dependency graph via metadata.rb (so I can  
> do it per node here and not need to use an environment for that)
> - defines the interface for the user (i.e. README, attributes, etc..)
> 
> - the environments should contain only environment specific attribute  
> overrides + the versions of the "top-level" cookbooks
> 
> Since I'm wrapping other cookbooks and setting their attributes in (the  
> "top-level" cookbook's) recipe, I'm sometimes faced with the "computed  
> attributes problem". I tackle that by reloading the wrapped attributes file  
> between setting the attributes and including the recipe, e.g. here:
> 
> [https://docs.chef.io/chef/essentials\_cookbook\_recipes.html#reload-attributes](https://docs.chef.io/chef/essentials_cookbook_recipes.html#reload-attributes)
> 
> Also, my environments often share the same data, i.e. common attributes  
> that are environmental data but still the same for many or even all of my  
> environments. Ranjib recently posted a nice way on how to deal with that:  
> [Consuming common datra across environments using Chef's ruby environment DSL · GitHub](https://gist.github.com/ranjib/2f7e1482a3ac8f6e5bfc)
> 
> Hope that helps or at least gives you some more ideas. There are many ways  
> and even more opinions 😉
> 
> Cheers,  
> Torben
> 
> On Fri, Jun 19, 2015 at 4:22 PM, Douglas Garstang \<[doug.garstang@gmail.com](mailto:doug.garstang@gmail.com)
> 
> > wrote:
> 
> > If I was going to put move my environmental attributes into cookbooks...
> > 
> > When deployed to an instance, the top level run list would need to  
> > include the environmental run list. That's ok.
> > 
> > However, when testing, this would mean that each cookbook would need to  
> > either include the environment cookbook (ie #include\_recipe "env-dev") and  
> > refer to it in the metadata.rb and Berksfile files, OR I'd have to  
> > specifically put each attribute into the Vagrantfile's json data.
> > 
> > This might work for simple cookbooks, but it would mean the cookbook is  
> > not being effectively tested. The attributes I'm testing against aren't  
> > what really gets deployed to an instance. I also have to maintain two  
> > copies of the attributes and the worst case scenario is where the attribute  
> > is set in both places but the value in the Vagranrfile is incorrect and  
> > therefore leads to the incorrect assumption that the cookbook is working  
> > correctly.
> > 
> > For my base cookbook it gets even worse. It would need to have every  
> > single attribute from every cookbook it includes put into the Vagrantfile's  
> > json data. This just does not scale.
> > 
> > It doesn't seem like the benefits of gaining some revision control  
> > outweigh the maintenance disadvantages here. For all those that espouse the  
> > use of putting environment attributes into a cookbook how do you get around  
> > this?
> > 
> > Doug

--  
Regards,

Douglas Garstang  
[http://www.linkedin.com/in/garstang](http://www.linkedin.com/in/garstang)  
Email: [doug.garstang@gmail.com](mailto:doug.garstang@gmail.com)  
Cell: +1-805-340-5627

---

<div class="post-metadata">

**Author:** ![Tensibai](https://sea2.discourse-cdn.com/flex016/user_avatar/discourse.chef.io/tensibai/32/29_2.png) [@Tensibai](https://discourse.chef.io/u/Tensibai)\
**Post date:** [June 22, 2015, 4:33pm UTC](https://discourse.chef.io/t/environment-attributes-in-cookbooks/6680/5 "2015-06-22T16:33:51Z")

</div>

May you explain why you can't have multiple chef.add\_recipe in your  
vagrant file ?

I really don't understand where you're stuck.

Le 2015-06-22 17:51, Douglas Garstang a écrit :

> Torben,
> 
> We're definitely going along the path of using environments for dev, qa, stage, prod etc. What you posted above was really useful, except that it doesn't help with the testing issue which is kinda the blocker here. If I can't test it, well I can't really use it. ☹
> 
> Doug.
> 
> On Sun, Jun 21, 2015 at 6:39 AM, Torben Knerr [mail@tknerr.de](mailto:mail@tknerr.de) wrote:
> 
> Hey Doug,
> 
> I believe you first have to decide for what purpose you actually want to use Chef environments, and this decision then limits the options for technically implementing this.
> 
> For me the key decision is:  
> a) if you are going to use the berkflow / the environment cookbook pattern with `berks apply environment`, then this means you will end up with one environment per node  
> b) if you are going to use environments for dev / test / staging / prod stages, you probably want to share environmental attributes across many nodes
> 
> Personally, I prefer b) and try to stick to the following principles: - use environments only for supplying environment specific data
> 
> - don't use environment for composing a node's run list or other node specific internals
> - instead I use a single "top-level" wrapper cookbook per node, which
> 
> - glues together the run list
> - sets attributes for configuring the wrapped cookbooks
> - sometimes adds addional glue code
> - locks the whole cookbook dependency graph via metadata.rb (so I can do it per node here and not need to use an environment for that)
> - defines the interface for the user (i.e. README, attributes, etc..)
> 
> - the environments should contain only environment specific attribute overrides + the versions of the "top-level" cookbooks
> 
> Since I'm wrapping other cookbooks and setting their attributes in (the "top-level" cookbook's) recipe, I'm sometimes faced with the "computed attributes problem". I tackle that by reloading the wrapped attributes file between setting the attributes and including the recipe, e.g. here:  
> [https://docs.chef.io/chef/essentials\_cookbook\_recipes.html#reload-attributes](https://docs.chef.io/chef/essentials_cookbook_recipes.html#reload-attributes) [1]
> 
> Also, my environments often share the same data, i.e. common attributes that are environmental data but still the same for many or even all of my environments. Ranjib recently posted a nice way on how to deal with that:  
> [Consuming common datra across environments using Chef's ruby environment DSL · GitHub](https://gist.github.com/ranjib/2f7e1482a3ac8f6e5bfc) [2]
> 
> Hope that helps or at least gives you some more ideas. There are many ways and even more opinions 😉
> 
> Cheers,  
> Torben
> 
> On Fri, Jun 19, 2015 at 4:22 PM, Douglas Garstang [doug.garstang@gmail.com](mailto:doug.garstang@gmail.com) wrote:
> 
> If I was going to put move my environmental attributes into cookbooks...
> 
> When deployed to an instance, the top level run list would need to include the environmental run list. That's ok.
> 
> However, when testing, this would mean that each cookbook would need to either include the environment cookbook (ie #include\_recipe "env-dev") and refer to it in the metadata.rb and Berksfile files, OR I'd have to specifically put each attribute into the Vagrantfile's json data.
> 
> This might work for simple cookbooks, but it would mean the cookbook is not being effectively tested. The attributes I'm testing against aren't what really gets deployed to an instance. I also have to maintain two copies of the attributes and the worst case scenario is where the attribute is set in both places but the value in the Vagranrfile is incorrect and therefore leads to the incorrect assumption that the cookbook is working correctly.
> 
> For my base cookbook it gets even worse. It would need to have every single attribute from every cookbook it includes put into the Vagrantfile's json data. This just does not scale.
> 
> It doesn't seem like the benefits of gaining some revision control outweigh the maintenance disadvantages here. For all those that espouse the use of putting environment attributes into a cookbook how do you get around this?
> 
> Doug

--

Regards,

Douglas Garstang  
[http://www.linkedin.com/in/garstang](http://www.linkedin.com/in/garstang) [3]  
Email: [doug.garstang@gmail.com](mailto:doug.garstang@gmail.com)  
Cell: +1-805-340-5627

## Links:

[1]  
[https://docs.chef.io/chef/essentials\_cookbook\_recipes.html#reload-attributes](https://docs.chef.io/chef/essentials_cookbook_recipes.html#reload-attributes)  
[2] [Consuming common datra across environments using Chef's ruby environment DSL · GitHub](https://gist.github.com/ranjib/2f7e1482a3ac8f6e5bfc)  
[3] [http://www.linkedin.com/in/garstang](http://www.linkedin.com/in/garstang)

---

<div class="post-metadata">

**Author:** ![tknerr](https://sea2.discourse-cdn.com/flex016/user_avatar/discourse.chef.io/tknerr/32/21_2.png) [@tknerr](https://discourse.chef.io/u/tknerr)\
**Post date:** [June 23, 2015, 5:30am UTC](https://discourse.chef.io/t/environment-attributes-in-cookbooks/6680/6 "2015-06-23T05:30:56Z")

</div>

Hey Doug,

as for the testing thing: if you'd specify environmental attributes in an  
environment json / rb file, you could also refer to this in your  
Vagrantfile instead of using an env recipe or json attributes directly (see  
"environment" property):

> **[Common Chef Options - Provisioning | Vagrant | HashiCorp Developer](https://developer.hashicorp.com/vagrant/docs/provisioning/chef_common)**
>
> The following options are available to all Vagrant Chef provisioners. Many of
> these options are for advanced users only and should not be used unless you
> understand their purpose.

That way you wouldn't need to duplicate them.

HTH,  
Torben

On Mon, Jun 22, 2015 at 5:51 PM, Douglas Garstang [doug.garstang@gmail.com](mailto:doug.garstang@gmail.com)  
wrote:

> Torben,
> 
> We're definitely going along the path of using environments for dev, qa,  
> stage, prod etc. What you posted above was really useful, except that it  
> doesn't help with the testing issue which is kinda the blocker here. If I  
> can't test it, well I can't really use it. ☹
> 
> Doug.
> 
> On Sun, Jun 21, 2015 at 6:39 AM, Torben Knerr [mail@tknerr.de](mailto:mail@tknerr.de) wrote:
> 
> > Hey Doug,
> > 
> > I believe you first have to decide for what purpose you actually want to  
> > use Chef environments, and this decision then limits the options for  
> > technically implementing this.
> > 
> > For me the key decision is:  
> > a) if you are going to use the berkflow / the environment cookbook  
> > pattern with `berks apply environment`, then this means you will end up  
> > with one environment per node  
> > b) if you are going to use environments for dev / test / staging / prod  
> > stages, you probably want to share environmental attributes across many  
> > nodes
> > 
> > Personally, I prefer b) and try to stick to the following principles:
> > 
> > - use environments only for supplying environment specific data
> > - don't use environment for composing a node's run list or other node  
> > specific internals
> > - instead I use a single "top-level" wrapper cookbook per node, which
> > - glues together the run list
> > - sets attributes for configuring the wrapped cookbooks
> > - sometimes adds addional glue code
> > - locks the whole cookbook dependency graph via metadata.rb (so I can  
> > do it per node here and not need to use an environment for that)
> > - defines the interface for the user (i.e. README, attributes, etc..)
> > 
> > - the environments should contain only environment specific attribute  
> > overrides + the versions of the "top-level" cookbooks
> > 
> > Since I'm wrapping other cookbooks and setting their attributes in (the  
> > "top-level" cookbook's) recipe, I'm sometimes faced with the "computed  
> > attributes problem". I tackle that by reloading the wrapped attributes file  
> > between setting the attributes and including the recipe, e.g. here:
> > 
> > [https://docs.chef.io/chef/essentials\_cookbook\_recipes.html#reload-attributes](https://docs.chef.io/chef/essentials_cookbook_recipes.html#reload-attributes)
> > 
> > Also, my environments often share the same data, i.e. common attributes  
> > that are environmental data but still the same for many or even all of my  
> > environments. Ranjib recently posted a nice way on how to deal with that:  
> > [Consuming common datra across environments using Chef's ruby environment DSL · GitHub](https://gist.github.com/ranjib/2f7e1482a3ac8f6e5bfc)
> > 
> > Hope that helps or at least gives you some more ideas. There are many  
> > ways and even more opinions 😉
> > 
> > Cheers,  
> > Torben
> > 
> > On Fri, Jun 19, 2015 at 4:22 PM, Douglas Garstang \<  
> > [doug.garstang@gmail.com](mailto:doug.garstang@gmail.com)\> wrote:
> > 
> > > If I was going to put move my environmental attributes into cookbooks...
> > > 
> > > When deployed to an instance, the top level run list would need to  
> > > include the environmental run list. That's ok.
> > > 
> > > However, when testing, this would mean that each cookbook would need to  
> > > either include the environment cookbook (ie #include\_recipe "env-dev") and  
> > > refer to it in the metadata.rb and Berksfile files, OR I'd have to  
> > > specifically put each attribute into the Vagrantfile's json data.
> > > 
> > > This might work for simple cookbooks, but it would mean the cookbook is  
> > > not being effectively tested. The attributes I'm testing against aren't  
> > > what really gets deployed to an instance. I also have to maintain two  
> > > copies of the attributes and the worst case scenario is where the attribute  
> > > is set in both places but the value in the Vagranrfile is incorrect and  
> > > therefore leads to the incorrect assumption that the cookbook is working  
> > > correctly.
> > > 
> > > For my base cookbook it gets even worse. It would need to have every  
> > > single attribute from every cookbook it includes put into the Vagrantfile's  
> > > json data. This just does not scale.
> > > 
> > > It doesn't seem like the benefits of gaining some revision control  
> > > outweigh the maintenance disadvantages here. For all those that espouse the  
> > > use of putting environment attributes into a cookbook how do you get around  
> > > this?
> > > 
> > > Doug
> 
> --  
> Regards,
> 
> Douglas Garstang  
> [http://www.linkedin.com/in/garstang](http://www.linkedin.com/in/garstang)  
> Email: [doug.garstang@gmail.com](mailto:doug.garstang@gmail.com)  
> Cell: +1-805-340-5627

---

<div class="post-metadata">

**Author:** ![tknerr](https://sea2.discourse-cdn.com/flex016/user_avatar/discourse.chef.io/tknerr/32/21_2.png) [@tknerr](https://discourse.chef.io/u/tknerr)\
**Post date:** [June 23, 2015, 5:43am UTC](https://discourse.chef.io/t/environment-attributes-in-cookbooks/6680/7 "2015-06-23T05:43:39Z")

</div>

Hi Yoshi,

ah, interesting, was not aware of the fact that it would apply the cookbook  
locks to an existing environment while keeping the env attributes. That  
gets me some new thoughts.

However, that would still mean I have one environment per node (or "role"  
at least), e.g.: "prod\_lb", "prod\_web", "prod\_db" etc.., right?

If so, that would also mean I have to duplicate the prod-specific  
attributes here (3x times in the example above), right?

I realize I may could get around this using the YAML include approach  
Ranjib shared, which would keep it single-sourced, but still I'd need to  
update each of the "prod\_\*" environments from that single source.

Last but not Ieast might have an impact on searches or environment checks  
as well, but that could be dealt with easily I guess, at least if it's  
happening in your own recipes where you are in control of it.

If there's a better way to work with berksflow / berks apply while keeping  
the intuitive environment semantics, I'd be happy to learn more about it.

Cheers,  
Torben

On Mon, Jun 22, 2015 at 5:33 PM, Yoshi Spendiff \<  
[yoshi.spendiff@indochino.com](mailto:yoshi.spendiff@indochino.com)\> wrote:

> Hi Torben,
> 
> Not sure if you know, but the A/B choice you stated above aren't actually  
> mutually exclusive. If you want to use berkflow/berks apply to apply  
> cookbook version locks to an environment that doesn't stop you supplying  
> normal environment variables to the environment. Berkflow/berks apply  
> doesn't change any attributes other than the version locks.
> 
> Cheers,  
> Yoshi
> 
> On Sun, Jun 21, 2015 at 6:39 AM, Torben Knerr [mail@tknerr.de](mailto:mail@tknerr.de) wrote:
> 
> > Hey Doug,
> > 
> > I believe you first have to decide for what purpose you actually want to  
> > use Chef environments, and this decision then limits the options for  
> > technically implementing this.
> > 
> > For me the key decision is:  
> > a) if you are going to use the berkflow / the environment cookbook  
> > pattern with `berks apply environment`, then this means you will end up  
> > with one environment per node  
> > b) if you are going to use environments for dev / test / staging / prod  
> > stages, you probably want to share environmental attributes across many  
> > nodes
> > 
> > Personally, I prefer b) and try to stick to the following principles:
> > 
> > - use environments only for supplying environment specific data
> > - don't use environment for composing a node's run list or other node  
> > specific internals
> > - instead I use a single "top-level" wrapper cookbook per node, which
> > - glues together the run list
> > - sets attributes for configuring the wrapped cookbooks
> > - sometimes adds addional glue code
> > - locks the whole cookbook dependency graph via metadata.rb (so I can  
> > do it per node here and not need to use an environment for that)
> > - defines the interface for the user (i.e. README, attributes, etc..)
> > 
> > - the environments should contain only environment specific attribute  
> > overrides + the versions of the "top-level" cookbooks
> > 
> > Since I'm wrapping other cookbooks and setting their attributes in (the  
> > "top-level" cookbook's) recipe, I'm sometimes faced with the "computed  
> > attributes problem". I tackle that by reloading the wrapped attributes file  
> > between setting the attributes and including the recipe, e.g. here:
> > 
> > [https://docs.chef.io/chef/essentials\_cookbook\_recipes.html#reload-attributes](https://docs.chef.io/chef/essentials_cookbook_recipes.html#reload-attributes)
> > 
> > Also, my environments often share the same data, i.e. common attributes  
> > that are environmental data but still the same for many or even all of my  
> > environments. Ranjib recently posted a nice way on how to deal with that:  
> > [Consuming common datra across environments using Chef's ruby environment DSL · GitHub](https://gist.github.com/ranjib/2f7e1482a3ac8f6e5bfc)
> > 
> > Hope that helps or at least gives you some more ideas. There are many  
> > ways and even more opinions 😉
> > 
> > Cheers,  
> > Torben
> > 
> > On Fri, Jun 19, 2015 at 4:22 PM, Douglas Garstang \<  
> > [doug.garstang@gmail.com](mailto:doug.garstang@gmail.com)\> wrote:
> > 
> > > If I was going to put move my environmental attributes into cookbooks...
> > > 
> > > When deployed to an instance, the top level run list would need to  
> > > include the environmental run list. That's ok.
> > > 
> > > However, when testing, this would mean that each cookbook would need to  
> > > either include the environment cookbook (ie #include\_recipe "env-dev") and  
> > > refer to it in the metadata.rb and Berksfile files, OR I'd have to  
> > > specifically put each attribute into the Vagrantfile's json data.
> > > 
> > > This might work for simple cookbooks, but it would mean the cookbook is  
> > > not being effectively tested. The attributes I'm testing against aren't  
> > > what really gets deployed to an instance. I also have to maintain two  
> > > copies of the attributes and the worst case scenario is where the attribute  
> > > is set in both places but the value in the Vagranrfile is incorrect and  
> > > therefore leads to the incorrect assumption that the cookbook is working  
> > > correctly.
> > > 
> > > For my base cookbook it gets even worse. It would need to have every  
> > > single attribute from every cookbook it includes put into the Vagrantfile's  
> > > json data. This just does not scale.
> > > 
> > > It doesn't seem like the benefits of gaining some revision control  
> > > outweigh the maintenance disadvantages here. For all those that espouse the  
> > > use of putting environment attributes into a cookbook how do you get around  
> > > this?
> > > 
> > > Doug
> 
> --  
> Yoshi Spendiff  
> Ops Engineer  
> Indochino  
> Mobile: +1 778 952 2025  
> Email: [yoshi.spendiff@indochino.com](mailto:yoshi.spendiff@indochino.com)

---

<div class="post-metadata">

**Author:** ![Yoshi\_Spendiff](https://sea2.discourse-cdn.com/flex016/user_avatar/discourse.chef.io/yoshi_spendiff/32/13_2.png) [@Yoshi\_Spendiff](https://discourse.chef.io/u/Yoshi_Spendiff)\
**Post date:** [June 23, 2015, 3:19pm UTC](https://discourse.chef.io/t/environment-attributes-in-cookbooks/6680/8 "2015-06-23T15:19:53Z")

</div>

In the demonstration that Jamie Windsor did for berkflow at Chefcon he used  
a role/environment cookbook with multiple roles rather than single role  
cookbooks.

[![](https://us1.discourse-cdn.com/flex016/uploads/chef/original/2X/0/029f09f15065aa6bf4dbd8caae6b4221ef1dff7c.jpeg "#ChefConf 2014: Jamie Winsor, "The Berkshelf Vision"") ](https://www.youtube.com/watch?v=Dq_vGxd-jps)

I think in your case if you have a cookbook per role then the only way you  
can make it work that way is if cookbooks common to your role cookbooks all  
have the same version requirement (or no specific version requirement).  
I.e. if your lb cookbook needs nginx 1.2.3 but your web cookbook needs  
1.2.4, and those versions are locked, then there's not much you can do as  
you'll have conflicting version locks in your environment.

If you don't have one role cookbook per role or you don't have these  
specific version requirements then it's pretty easy. You'd make a top level  
cookbook to wrap your role cookbooks which would be your environment  
cookbook (or if you have one role cookbook with multiple roles then this  
could be your environment cookbook) then just add the Berksfile.lock from  
the cookbook to source control, make sure it's not in chefignore and that's  
your one source of version locks which you can apply to all environments.  
You then add the recipes from the environment cookbooks to your nodes/roles.

As there's no actual logic in the environment cookbook whenever you want to  
update your environments you bump the metadata on the environment cookbook,  
run berks update and then upload it to your chef server. You can then use  
berkflow to apply the cookbook from your chef server to an environment,  
which will apply the locks only.

You can now use your environments for whatever attributes you want.

On Mon, Jun 22, 2015 at 10:43 PM, Torben Knerr [mail@tknerr.de](mailto:mail@tknerr.de) wrote:

> Hi Yoshi,
> 
> ah, interesting, was not aware of the fact that it would apply the  
> cookbook locks to an existing environment while keeping the env attributes.  
> That gets me some new thoughts.
> 
> However, that would still mean I have one environment per node (or "role"  
> at least), e.g.: "prod\_lb", "prod\_web", "prod\_db" etc.., right?
> 
> If so, that would also mean I have to duplicate the prod-specific  
> attributes here (3x times in the example above), right?
> 
> I realize I may could get around this using the YAML include approach  
> Ranjib shared, which would keep it single-sourced, but still I'd need to  
> update each of the "prod\_\*" environments from that single source.
> 
> Last but not Ieast might have an impact on searches or environment checks  
> as well, but that could be dealt with easily I guess, at least if it's  
> happening in your own recipes where you are in control of it.
> 
> If there's a better way to work with berksflow / berks apply while keeping  
> the intuitive environment semantics, I'd be happy to learn more about it.
> 
> Cheers,  
> Torben
> 
> On Mon, Jun 22, 2015 at 5:33 PM, Yoshi Spendiff \<  
> [yoshi.spendiff@indochino.com](mailto:yoshi.spendiff@indochino.com)\> wrote:
> 
> > Hi Torben,
> > 
> > Not sure if you know, but the A/B choice you stated above aren't actually  
> > mutually exclusive. If you want to use berkflow/berks apply to apply  
> > cookbook version locks to an environment that doesn't stop you supplying  
> > normal environment variables to the environment. Berkflow/berks apply  
> > doesn't change any attributes other than the version locks.
> > 
> > Cheers,  
> > Yoshi
> > 
> > On Sun, Jun 21, 2015 at 6:39 AM, Torben Knerr [mail@tknerr.de](mailto:mail@tknerr.de) wrote:
> > 
> > > Hey Doug,
> > > 
> > > I believe you first have to decide for what purpose you actually want to  
> > > use Chef environments, and this decision then limits the options for  
> > > technically implementing this.
> > > 
> > > For me the key decision is:  
> > > a) if you are going to use the berkflow / the environment cookbook  
> > > pattern with `berks apply environment`, then this means you will end up  
> > > with one environment per node  
> > > b) if you are going to use environments for dev / test / staging / prod  
> > > stages, you probably want to share environmental attributes across many  
> > > nodes
> > > 
> > > Personally, I prefer b) and try to stick to the following principles:
> > > 
> > > - use environments only for supplying environment specific data
> > > - don't use environment for composing a node's run list or other node  
> > > specific internals
> > > - instead I use a single "top-level" wrapper cookbook per node, which
> > > - glues together the run list
> > > - sets attributes for configuring the wrapped cookbooks
> > > - sometimes adds addional glue code
> > > - locks the whole cookbook dependency graph via metadata.rb (so I can  
> > > do it per node here and not need to use an environment for that)
> > > - defines the interface for the user (i.e. README, attributes, etc..)
> > > 
> > > - the environments should contain only environment specific attribute  
> > > overrides + the versions of the "top-level" cookbooks
> > > 
> > > Since I'm wrapping other cookbooks and setting their attributes in (the  
> > > "top-level" cookbook's) recipe, I'm sometimes faced with the "computed  
> > > attributes problem". I tackle that by reloading the wrapped attributes file  
> > > between setting the attributes and including the recipe, e.g. here:
> > > 
> > > [https://docs.chef.io/chef/essentials\_cookbook\_recipes.html#reload-attributes](https://docs.chef.io/chef/essentials_cookbook_recipes.html#reload-attributes)
> > > 
> > > Also, my environments often share the same data, i.e. common attributes  
> > > that are environmental data but still the same for many or even all of my  
> > > environments. Ranjib recently posted a nice way on how to deal with that:  
> > > [Consuming common datra across environments using Chef's ruby environment DSL · GitHub](https://gist.github.com/ranjib/2f7e1482a3ac8f6e5bfc)
> > > 
> > > Hope that helps or at least gives you some more ideas. There are many  
> > > ways and even more opinions 😉
> > > 
> > > Cheers,  
> > > Torben
> > > 
> > > On Fri, Jun 19, 2015 at 4:22 PM, Douglas Garstang \<  
> > > [doug.garstang@gmail.com](mailto:doug.garstang@gmail.com)\> wrote:
> > > 
> > > > If I was going to put move my environmental attributes into cookbooks...
> > > > 
> > > > When deployed to an instance, the top level run list would need to  
> > > > include the environmental run list. That's ok.
> > > > 
> > > > However, when testing, this would mean that each cookbook would need to  
> > > > either include the environment cookbook (ie #include\_recipe "env-dev") and  
> > > > refer to it in the metadata.rb and Berksfile files, OR I'd have to  
> > > > specifically put each attribute into the Vagrantfile's json data.
> > > > 
> > > > This might work for simple cookbooks, but it would mean the cookbook is  
> > > > not being effectively tested. The attributes I'm testing against aren't  
> > > > what really gets deployed to an instance. I also have to maintain two  
> > > > copies of the attributes and the worst case scenario is where the attribute  
> > > > is set in both places but the value in the Vagranrfile is incorrect and  
> > > > therefore leads to the incorrect assumption that the cookbook is working  
> > > > correctly.
> > > > 
> > > > For my base cookbook it gets even worse. It would need to have every  
> > > > single attribute from every cookbook it includes put into the Vagrantfile's  
> > > > json data. This just does not scale.
> > > > 
> > > > It doesn't seem like the benefits of gaining some revision control  
> > > > outweigh the maintenance disadvantages here. For all those that espouse the  
> > > > use of putting environment attributes into a cookbook how do you get around  
> > > > this?
> > > > 
> > > > Doug
> > 
> > --  
> > Yoshi Spendiff  
> > Ops Engineer  
> > Indochino  
> > Mobile: +1 778 952 2025  
> > Email: [yoshi.spendiff@indochino.com](mailto:yoshi.spendiff@indochino.com)

--  
Yoshi Spendiff  
Ops Engineer  
Indochino  
Mobile: +1 778 952 2025  
Email: [yoshi.spendiff@indochino.com](mailto:yoshi.spendiff@indochino.com)

---

<div class="post-metadata">

**Author:** ![tknerr](https://sea2.discourse-cdn.com/flex016/user_avatar/discourse.chef.io/tknerr/32/21_2.png) [@tknerr](https://discourse.chef.io/u/tknerr)\
**Post date:** [June 23, 2015, 3:44pm UTC](https://discourse.chef.io/t/environment-attributes-in-cookbooks/6680/9 "2015-06-23T15:44:33Z")

</div>

> I.e. if your lb cookbook needs nginx 1.2.3 but your web cookbook needs  
> 1.2.4, and those versions are locked, then there's not much you can do as  
> you'll have conflicting version locks in your environment.

That's exactly the freedom I want, and the reason why I settled with one  
"top-level" cookbook per role (guess I should call that "role cookbook"  
then ;-)) which locks it's downstream cookbooks on its own via its  
metadata.rb

Thanks for the summary though! Even though berkflow doesn't fit for my  
case, I still learned something new 🙂  
Am 23.06.2015 17:20 schrieb "Yoshi Spendiff" [yoshi.spendiff@indochino.com](mailto:yoshi.spendiff@indochino.com):

> In the demonstration that Jamie Windsor did for berkflow at Chefcon he  
> used a role/environment cookbook with multiple roles rather than single  
> role cookbooks.
> 
> [https://www.youtube.com/watch?v=Dq\_vGxd-jps](https://www.youtube.com/watch?v=Dq_vGxd-jps)
> 
> I think in your case if you have a cookbook per role then the only way you  
> can make it work that way is if cookbooks common to your role cookbooks all  
> have the same version requirement (or no specific version requirement).  
> I.e. if your lb cookbook needs nginx 1.2.3 but your web cookbook needs  
> 1.2.4, and those versions are locked, then there's not much you can do as  
> you'll have conflicting version locks in your environment.
> 
> If you don't have one role cookbook per role or you don't have these  
> specific version requirements then it's pretty easy. You'd make a top level  
> cookbook to wrap your role cookbooks which would be your environment  
> cookbook (or if you have one role cookbook with multiple roles then this  
> could be your environment cookbook) then just add the Berksfile.lock from  
> the cookbook to source control, make sure it's not in chefignore and that's  
> your one source of version locks which you can apply to all environments.  
> You then add the recipes from the environment cookbooks to your nodes/roles.
> 
> As there's no actual logic in the environment cookbook whenever you want  
> to update your environments you bump the metadata on the environment  
> cookbook, run berks update and then upload it to your chef server. You can  
> then use berkflow to apply the cookbook from your chef server to an  
> environment, which will apply the locks only.
> 
> You can now use your environments for whatever attributes you want.
> 
> On Mon, Jun 22, 2015 at 10:43 PM, Torben Knerr [mail@tknerr.de](mailto:mail@tknerr.de) wrote:
> 
> > Hi Yoshi,
> > 
> > ah, interesting, was not aware of the fact that it would apply the  
> > cookbook locks to an existing environment while keeping the env attributes.  
> > That gets me some new thoughts.
> > 
> > However, that would still mean I have one environment per node (or "role"  
> > at least), e.g.: "prod\_lb", "prod\_web", "prod\_db" etc.., right?
> > 
> > If so, that would also mean I have to duplicate the prod-specific  
> > attributes here (3x times in the example above), right?
> > 
> > I realize I may could get around this using the YAML include approach  
> > Ranjib shared, which would keep it single-sourced, but still I'd need to  
> > update each of the "prod\_\*" environments from that single source.
> > 
> > Last but not Ieast might have an impact on searches or environment checks  
> > as well, but that could be dealt with easily I guess, at least if it's  
> > happening in your own recipes where you are in control of it.
> > 
> > If there's a better way to work with berksflow / berks apply while  
> > keeping the intuitive environment semantics, I'd be happy to learn more  
> > about it.
> > 
> > Cheers,  
> > Torben
> > 
> > On Mon, Jun 22, 2015 at 5:33 PM, Yoshi Spendiff \<  
> > [yoshi.spendiff@indochino.com](mailto:yoshi.spendiff@indochino.com)\> wrote:
> > 
> > > Hi Torben,
> > > 
> > > Not sure if you know, but the A/B choice you stated above aren't  
> > > actually mutually exclusive. If you want to use berkflow/berks apply to  
> > > apply cookbook version locks to an environment that doesn't stop you  
> > > supplying normal environment variables to the environment. Berkflow/berks  
> > > apply doesn't change any attributes other than the version locks.
> > > 
> > > Cheers,  
> > > Yoshi
> > > 
> > > On Sun, Jun 21, 2015 at 6:39 AM, Torben Knerr [mail@tknerr.de](mailto:mail@tknerr.de) wrote:
> > > 
> > > > Hey Doug,
> > > > 
> > > > I believe you first have to decide for what purpose you actually want  
> > > > to use Chef environments, and this decision then limits the options for  
> > > > technically implementing this.
> > > > 
> > > > For me the key decision is:  
> > > > a) if you are going to use the berkflow / the environment cookbook  
> > > > pattern with `berks apply environment`, then this means you will end up  
> > > > with one environment per node  
> > > > b) if you are going to use environments for dev / test / staging / prod  
> > > > stages, you probably want to share environmental attributes across many  
> > > > nodes
> > > > 
> > > > Personally, I prefer b) and try to stick to the following principles:
> > > > 
> > > > - use environments only for supplying environment specific data
> > > > - don't use environment for composing a node's run list or other node  
> > > > specific internals
> > > > - instead I use a single "top-level" wrapper cookbook per node, which
> > > > - glues together the run list
> > > > - sets attributes for configuring the wrapped cookbooks
> > > > - sometimes adds addional glue code
> > > > - locks the whole cookbook dependency graph via metadata.rb (so I  
> > > > can do it per node here and not need to use an environment for that)
> > > > - defines the interface for the user (i.e. README, attributes, etc..)
> > > > 
> > > > - the environments should contain only environment specific attribute  
> > > > overrides + the versions of the "top-level" cookbooks
> > > > 
> > > > Since I'm wrapping other cookbooks and setting their attributes in (the  
> > > > "top-level" cookbook's) recipe, I'm sometimes faced with the "computed  
> > > > attributes problem". I tackle that by reloading the wrapped attributes file  
> > > > between setting the attributes and including the recipe, e.g. here:
> > > > 
> > > > [https://docs.chef.io/chef/essentials\_cookbook\_recipes.html#reload-attributes](https://docs.chef.io/chef/essentials_cookbook_recipes.html#reload-attributes)
> > > > 
> > > > Also, my environments often share the same data, i.e. common attributes  
> > > > that are environmental data but still the same for many or even all of my  
> > > > environments. Ranjib recently posted a nice way on how to deal with that:  
> > > > [Consuming common datra across environments using Chef's ruby environment DSL · GitHub](https://gist.github.com/ranjib/2f7e1482a3ac8f6e5bfc)
> > > > 
> > > > Hope that helps or at least gives you some more ideas. There are many  
> > > > ways and even more opinions 😉
> > > > 
> > > > Cheers,  
> > > > Torben
> > > > 
> > > > On Fri, Jun 19, 2015 at 4:22 PM, Douglas Garstang \<  
> > > > [doug.garstang@gmail.com](mailto:doug.garstang@gmail.com)\> wrote:
> > > > 
> > > > > If I was going to put move my environmental attributes into  
> > > > > cookbooks...
> > > > > 
> > > > > When deployed to an instance, the top level run list would need to  
> > > > > include the environmental run list. That's ok.
> > > > > 
> > > > > However, when testing, this would mean that each cookbook would need  
> > > > > to either include the environment cookbook (ie #include\_recipe "env-dev")  
> > > > > and refer to it in the metadata.rb and Berksfile files, OR I'd have to  
> > > > > specifically put each attribute into the Vagrantfile's json data.
> > > > > 
> > > > > This might work for simple cookbooks, but it would mean the cookbook  
> > > > > is not being effectively tested. The attributes I'm testing against aren't  
> > > > > what really gets deployed to an instance. I also have to maintain two  
> > > > > copies of the attributes and the worst case scenario is where the attribute  
> > > > > is set in both places but the value in the Vagranrfile is incorrect and  
> > > > > therefore leads to the incorrect assumption that the cookbook is working  
> > > > > correctly.
> > > > > 
> > > > > For my base cookbook it gets even worse. It would need to have every  
> > > > > single attribute from every cookbook it includes put into the Vagrantfile's  
> > > > > json data. This just does not scale.
> > > > > 
> > > > > It doesn't seem like the benefits of gaining some revision control  
> > > > > outweigh the maintenance disadvantages here. For all those that espouse the  
> > > > > use of putting environment attributes into a cookbook how do you get around  
> > > > > this?
> > > > > 
> > > > > Doug
> > > 
> > > --  
> > > Yoshi Spendiff  
> > > Ops Engineer  
> > > Indochino  
> > > Mobile: +1 778 952 2025  
> > > Email: [yoshi.spendiff@indochino.com](mailto:yoshi.spendiff@indochino.com)
> 
> --  
> Yoshi Spendiff  
> Ops Engineer  
> Indochino  
> Mobile: +1 778 952 2025  
> Email: [yoshi.spendiff@indochino.com](mailto:yoshi.spendiff@indochino.com)

---

<div class="post-metadata">

**Author:** ![Yoshi\_Spendiff](https://sea2.discourse-cdn.com/flex016/user_avatar/discourse.chef.io/yoshi_spendiff/32/13_2.png) [@Yoshi\_Spendiff](https://discourse.chef.io/u/Yoshi_Spendiff)\
**Post date:** [June 23, 2015, 4:08pm UTC](https://discourse.chef.io/t/environment-attributes-in-cookbooks/6680/10 "2015-06-23T16:08:38Z")

</div>

No worries mate, good to have the cards in your back pocket if you need  
them!

On Tue, Jun 23, 2015 at 8:44 AM, Torben Knerr [mail@tknerr.de](mailto:mail@tknerr.de) wrote:

> > I.e. if your lb cookbook needs nginx 1.2.3 but your web cookbook needs  
> > 1.2.4, and those versions are locked, then there's not much you can do as  
> > you'll have conflicting version locks in your environment.
> 
> That's exactly the freedom I want, and the reason why I settled with one  
> "top-level" cookbook per role (guess I should call that "role cookbook"  
> then ;-)) which locks it's downstream cookbooks on its own via its  
> metadata.rb
> 
> Thanks for the summary though! Even though berkflow doesn't fit for my  
> case, I still learned something new 🙂  
> Am 23.06.2015 17:20 schrieb "Yoshi Spendiff" \<[yoshi.spendiff@indochino.com](mailto:yoshi.spendiff@indochino.com)
> 
> > :
> 
> > In the demonstration that Jamie Windsor did for berkflow at Chefcon he  
> > used a role/environment cookbook with multiple roles rather than single  
> > role cookbooks.
> > 
> > [https://www.youtube.com/watch?v=Dq\_vGxd-jps](https://www.youtube.com/watch?v=Dq_vGxd-jps)
> > 
> > I think in your case if you have a cookbook per role then the only way  
> > you can make it work that way is if cookbooks common to your role cookbooks  
> > all have the same version requirement (or no specific version requirement).  
> > I.e. if your lb cookbook needs nginx 1.2.3 but your web cookbook needs  
> > 1.2.4, and those versions are locked, then there's not much you can do as  
> > you'll have conflicting version locks in your environment.
> > 
> > If you don't have one role cookbook per role or you don't have these  
> > specific version requirements then it's pretty easy. You'd make a top level  
> > cookbook to wrap your role cookbooks which would be your environment  
> > cookbook (or if you have one role cookbook with multiple roles then this  
> > could be your environment cookbook) then just add the Berksfile.lock from  
> > the cookbook to source control, make sure it's not in chefignore and that's  
> > your one source of version locks which you can apply to all environments.  
> > You then add the recipes from the environment cookbooks to your nodes/roles.
> > 
> > As there's no actual logic in the environment cookbook whenever you want  
> > to update your environments you bump the metadata on the environment  
> > cookbook, run berks update and then upload it to your chef server. You can  
> > then use berkflow to apply the cookbook from your chef server to an  
> > environment, which will apply the locks only.
> > 
> > You can now use your environments for whatever attributes you want.
> > 
> > On Mon, Jun 22, 2015 at 10:43 PM, Torben Knerr [mail@tknerr.de](mailto:mail@tknerr.de) wrote:
> > 
> > > Hi Yoshi,
> > > 
> > > ah, interesting, was not aware of the fact that it would apply the  
> > > cookbook locks to an existing environment while keeping the env attributes.  
> > > That gets me some new thoughts.
> > > 
> > > However, that would still mean I have one environment per node (or  
> > > "role" at least), e.g.: "prod\_lb", "prod\_web", "prod\_db" etc.., right?
> > > 
> > > If so, that would also mean I have to duplicate the prod-specific  
> > > attributes here (3x times in the example above), right?
> > > 
> > > I realize I may could get around this using the YAML include approach  
> > > Ranjib shared, which would keep it single-sourced, but still I'd need to  
> > > update each of the "prod\_\*" environments from that single source.
> > > 
> > > Last but not Ieast might have an impact on searches or environment  
> > > checks as well, but that could be dealt with easily I guess, at least if  
> > > it's happening in your own recipes where you are in control of it.
> > > 
> > > If there's a better way to work with berksflow / berks apply while  
> > > keeping the intuitive environment semantics, I'd be happy to learn more  
> > > about it.
> > > 
> > > Cheers,  
> > > Torben
> > > 
> > > On Mon, Jun 22, 2015 at 5:33 PM, Yoshi Spendiff \<  
> > > [yoshi.spendiff@indochino.com](mailto:yoshi.spendiff@indochino.com)\> wrote:
> > > 
> > > > Hi Torben,
> > > > 
> > > > Not sure if you know, but the A/B choice you stated above aren't  
> > > > actually mutually exclusive. If you want to use berkflow/berks apply to  
> > > > apply cookbook version locks to an environment that doesn't stop you  
> > > > supplying normal environment variables to the environment. Berkflow/berks  
> > > > apply doesn't change any attributes other than the version locks.
> > > > 
> > > > Cheers,  
> > > > Yoshi
> > > > 
> > > > On Sun, Jun 21, 2015 at 6:39 AM, Torben Knerr [mail@tknerr.de](mailto:mail@tknerr.de) wrote:
> > > > 
> > > > > Hey Doug,
> > > > > 
> > > > > I believe you first have to decide for what purpose you actually want  
> > > > > to use Chef environments, and this decision then limits the options for  
> > > > > technically implementing this.
> > > > > 
> > > > > For me the key decision is:  
> > > > > a) if you are going to use the berkflow / the environment cookbook  
> > > > > pattern with `berks apply environment`, then this means you will end up  
> > > > > with one environment per node  
> > > > > b) if you are going to use environments for dev / test / staging /  
> > > > > prod stages, you probably want to share environmental attributes across  
> > > > > many nodes
> > > > > 
> > > > > Personally, I prefer b) and try to stick to the following principles:
> > > > > 
> > > > > - use environments only for supplying environment specific data
> > > > > - don't use environment for composing a node's run list or other node  
> > > > > specific internals
> > > > > - instead I use a single "top-level" wrapper cookbook per node, which
> > > > > - glues together the run list
> > > > > - sets attributes for configuring the wrapped cookbooks
> > > > > - sometimes adds addional glue code
> > > > > - locks the whole cookbook dependency graph via metadata.rb (so I  
> > > > > can do it per node here and not need to use an environment for that)
> > > > > - defines the interface for the user (i.e. README, attributes,  
> > > > > etc..)
> > > > > 
> > > > > - the environments should contain only environment specific attribute  
> > > > > overrides + the versions of the "top-level" cookbooks
> > > > > 
> > > > > Since I'm wrapping other cookbooks and setting their attributes in  
> > > > > (the "top-level" cookbook's) recipe, I'm sometimes faced with the "computed  
> > > > > attributes problem". I tackle that by reloading the wrapped attributes file  
> > > > > between setting the attributes and including the recipe, e.g. here:
> > > > > 
> > > > > [https://docs.chef.io/chef/essentials\_cookbook\_recipes.html#reload-attributes](https://docs.chef.io/chef/essentials_cookbook_recipes.html#reload-attributes)
> > > > > 
> > > > > Also, my environments often share the same data, i.e. common  
> > > > > attributes that are environmental data but still the same for many or even  
> > > > > all of my environments. Ranjib recently posted a nice way on how to deal  
> > > > > with that:  
> > > > > [Consuming common datra across environments using Chef's ruby environment DSL · GitHub](https://gist.github.com/ranjib/2f7e1482a3ac8f6e5bfc)
> > > > > 
> > > > > Hope that helps or at least gives you some more ideas. There are many  
> > > > > ways and even more opinions 😉
> > > > > 
> > > > > Cheers,  
> > > > > Torben
> > > > > 
> > > > > On Fri, Jun 19, 2015 at 4:22 PM, Douglas Garstang \<  
> > > > > [doug.garstang@gmail.com](mailto:doug.garstang@gmail.com)\> wrote:
> > > > > 
> > > > > > If I was going to put move my environmental attributes into  
> > > > > > cookbooks...
> > > > > > 
> > > > > > When deployed to an instance, the top level run list would need to  
> > > > > > include the environmental run list. That's ok.
> > > > > > 
> > > > > > However, when testing, this would mean that each cookbook would need  
> > > > > > to either include the environment cookbook (ie #include\_recipe "env-dev")  
> > > > > > and refer to it in the metadata.rb and Berksfile files, OR I'd have to  
> > > > > > specifically put each attribute into the Vagrantfile's json data.
> > > > > > 
> > > > > > This might work for simple cookbooks, but it would mean the cookbook  
> > > > > > is not being effectively tested. The attributes I'm testing against aren't  
> > > > > > what really gets deployed to an instance. I also have to maintain two  
> > > > > > copies of the attributes and the worst case scenario is where the attribute  
> > > > > > is set in both places but the value in the Vagranrfile is incorrect and  
> > > > > > therefore leads to the incorrect assumption that the cookbook is working  
> > > > > > correctly.
> > > > > > 
> > > > > > For my base cookbook it gets even worse. It would need to have every  
> > > > > > single attribute from every cookbook it includes put into the Vagrantfile's  
> > > > > > json data. This just does not scale.
> > > > > > 
> > > > > > It doesn't seem like the benefits of gaining some revision control  
> > > > > > outweigh the maintenance disadvantages here. For all those that espouse the  
> > > > > > use of putting environment attributes into a cookbook how do you get around  
> > > > > > this?
> > > > > > 
> > > > > > Doug
> > > > 
> > > > --  
> > > > Yoshi Spendiff  
> > > > Ops Engineer  
> > > > Indochino  
> > > > Mobile: +1 778 952 2025  
> > > > Email: [yoshi.spendiff@indochino.com](mailto:yoshi.spendiff@indochino.com)
> > 
> > --  
> > Yoshi Spendiff  
> > Ops Engineer  
> > Indochino  
> > Mobile: +1 778 952 2025  
> > Email: [yoshi.spendiff@indochino.com](mailto:yoshi.spendiff@indochino.com)

--  
Yoshi Spendiff  
Ops Engineer  
Indochino  
Mobile: +1 778 952 2025  
Email: [yoshi.spendiff@indochino.com](mailto:yoshi.spendiff@indochino.com)
