# Role data in cookbooks

**URL:** https://discourse.chef.io/t/role-data-in-cookbooks/5112
**Category:** Chef Infra (archive)
**Created:** [March 14, 2014, 6:31am UTC](https://discourse.chef.io/t/role-data-in-cookbooks/5112 "2014-03-14T06:31:40Z")
**Posts on this page:** 4
**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: [March 14, 2014, 6:31am UTC](https://discourse.chef.io/t/role-data-in-cookbooks/5112/1 "2014-03-14T06:31:40Z")

</div>

We’re currently putting location specific attributes into roles. We have  
one role per location (multiple Amazon regions, us1, us2 etc). Examples of  
this location specific data might include things like the redis server, the  
apt-cache server address, amazon bucket names to use for various things and  
so on.

With our current approach, for any given node, the run list typically  
contains 1) the location role, 2) the base role added by our provisioning  
script, and 3) a role that defines what the node does, like this:

{  
“name”: “[dl01-us1.foo.net](http://dl01-us1.foo.net)”,  
…  
“run\_list”: [  
“role[role\_base]”,  
“role[role\_downloader\_app]”,  
“role[location\_us1\_prod]”  
]  
}

And, the functional role, role\_downloader\_app, would contain the actual  
recipe that does the work, e.g.:

// role\_downloader\_app.  
// A role for a download server.  
{  
“name”: “role\_downloader\_app”,  
…  
“run\_list”: [  
“recipe[bc-foo-downloader::dl]”  
],  
}

By not adding the base role until the node is provisioned on ec2, it allows  
for quicker testing with vagrant.

So, getting to the point…

If I take the location specific attributes and put it into a cookbook  
instead of a role, it’s going to become very messy. With a role, only the  
specific data for that role is added to the name space. If I use a  
cookbook, I have to put everything into the default/attributes file and  
qualify it for the location. Eg:

default[‘us1’] = { … }  
default[‘eu2’] = { … }

and so on. Then, to actually _use_ the attribute in a cookbook I have to  
qualify it again. Instead of saying node['some\_sever], I have to say  
node[‘us1’][‘some\_server’]. This is cumbersome. I could create one recipe  
per location, only include that recipe and then set the attributes in the  
recipe, but it seems like this may not be the best approach either.

There’s plenty of blogs out there on putting roles into cookbooks but they  
all seem to gloss over the details and not go beyond generally saying don’t  
put role data in roles.

Thanks,  
Doug.

---

<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: [March 14, 2014, 6:50am UTC](https://discourse.chef.io/t/role-data-in-cookbooks/5112/2 "2014-03-14T06:50:51Z")

</div>

I suppose, assuming that this entire approach is not folly, would be to use  
one cookbook per location, rather than one recipe (in a single cookbook)  
per location. Seems like a lot since we have a lot of locations, but I  
guess the number is still relatively small and manageable... half a dozen new  
cookbooks or so maybe.

Doug.

On Thu, Mar 13, 2014 at 11:31 PM, Douglas Garstang  
[doug.garstang@gmail.com](mailto:doug.garstang@gmail.com)wrote:

> We're currently putting location specific attributes into roles. We have  
> one role per location (multiple Amazon regions, us1, us2 etc). Examples of  
> this location specific data might include things like the redis server, the  
> apt-cache server address, amazon bucket names to use for various things and  
> so on.
> 
> With our current approach, for any given node, the run list typically  
> contains 1) the location role, 2) the base role added by our provisioning  
> script, and 3) a role that defines what the node does, like this:
> 
> {  
> "name": "[dl01-us1.foo.net](http://dl01-us1.foo.net)",  
> ...  
> "run\_list": [  
> "role[role\_base]",  
> "role[role\_downloader\_app]",  
> "role[location\_us1\_prod]"  
> ]  
> }
> 
> And, the functional role, role\_downloader\_app, would contain the actual  
> recipe that does the work, e.g.:
> 
> // role\_downloader\_app.  
> // A role for a download server.  
> {  
> "name": "role\_downloader\_app",  
> ...  
> "run\_list": [  
> "recipe[bc-foo-downloader::dl]"  
> ],  
> }
> 
> By not adding the base role until the node is provisioned on ec2, it  
> allows for quicker testing with vagrant.
> 
> So, getting to the point...
> 
> If I take the location specific attributes and put it into a cookbook  
> instead of a role, it's going to become very messy. With a role, only the  
> specific data for that role is added to the name space. If I use a  
> cookbook, I have to put everything into the default/attributes file and  
> qualify it for the location. Eg:
> 
> default['us1'] = { ... }  
> default['eu2'] = { ... }
> 
> and so on. Then, to actually _use_ the attribute in a cookbook I have to  
> qualify it again. Instead of saying node['some\_sever], I have to say  
> node['us1']['some\_server']. This is cumbersome. I could create one recipe  
> per location, only include that recipe and then set the attributes in the  
> recipe, but it seems like this may not be the best approach either.
> 
> There's plenty of blogs out there on putting roles into cookbooks but they  
> all seem to gloss over the details and not go beyond generally saying don't  
> put role data in roles.
> 
> Thanks,  
> 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: ![carmstrong](https://sea2.discourse-cdn.com/flex016/user_avatar/discourse.chef.io/carmstrong/32/346_2.png) [@carmstrong](https://discourse.chef.io/u/carmstrong)
#### Post date: [March 15, 2014, 10:06am UTC](https://discourse.chef.io/t/role-data-in-cookbooks/5112/3 "2014-03-15T10:06:58Z")

</div>

Any reason you're not using environments for location-specific attributes?

On Thu, Mar 13, 2014 at 11:50 PM, Douglas Garstang  
[doug.garstang@gmail.com](mailto:doug.garstang@gmail.com)wrote:

> I suppose, assuming that this entire approach is not folly, would be to  
> use one cookbook per location, rather than one recipe (in a single  
> cookbook) per location. Seems like a lot since we have a lot of locations,  
> but I guess the number is still relatively small and manageable... half a  
> dozen new cookbooks or so maybe.
> 
> Doug.
> 
> On Thu, Mar 13, 2014 at 11:31 PM, Douglas Garstang \<  
> [doug.garstang@gmail.com](mailto:doug.garstang@gmail.com)\> wrote:
> 
> > We're currently putting location specific attributes into roles. We have  
> > one role per location (multiple Amazon regions, us1, us2 etc). Examples of  
> > this location specific data might include things like the redis server, the  
> > apt-cache server address, amazon bucket names to use for various things and  
> > so on.
> > 
> > With our current approach, for any given node, the run list typically  
> > contains 1) the location role, 2) the base role added by our provisioning  
> > script, and 3) a role that defines what the node does, like this:
> > 
> > {  
> > "name": "[dl01-us1.foo.net](http://dl01-us1.foo.net)",  
> > ...  
> > "run\_list": [  
> > "role[role\_base]",  
> > "role[role\_downloader\_app]",  
> > "role[location\_us1\_prod]"  
> > ]  
> > }
> > 
> > And, the functional role, role\_downloader\_app, would contain the actual  
> > recipe that does the work, e.g.:
> > 
> > // role\_downloader\_app.  
> > // A role for a download server.  
> > {  
> > "name": "role\_downloader\_app",  
> > ...  
> > "run\_list": [  
> > "recipe[bc-foo-downloader::dl]"  
> > ],  
> > }
> > 
> > By not adding the base role until the node is provisioned on ec2, it  
> > allows for quicker testing with vagrant.
> > 
> > So, getting to the point...
> > 
> > If I take the location specific attributes and put it into a cookbook  
> > instead of a role, it's going to become very messy. With a role, only the  
> > specific data for that role is added to the name space. If I use a  
> > cookbook, I have to put everything into the default/attributes file and  
> > qualify it for the location. Eg:
> > 
> > default['us1'] = { ... }  
> > default['eu2'] = { ... }
> > 
> > and so on. Then, to actually _use_ the attribute in a cookbook I have to  
> > qualify it again. Instead of saying node['some\_sever], I have to say  
> > node['us1']['some\_server']. This is cumbersome. I could create one recipe  
> > per location, only include that recipe and then set the attributes in the  
> > recipe, but it seems like this may not be the best approach either.
> > 
> > There's plenty of blogs out there on putting roles into cookbooks but  
> > they all seem to gloss over the details and not go beyond generally saying  
> > don't put role data in roles.
> > 
> > Thanks,  
> > 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: ![Lamont\_Granquist\_OLD](https://avatars.discourse-cdn.com/v4/letter/l/7feea3/32.png) [@Lamont\_Granquist\_OLD](https://discourse.chef.io/u/Lamont_Granquist_OLD)
#### Post date: [March 15, 2014, 7:09pm UTC](https://discourse.chef.io/t/role-data-in-cookbooks/5112/4 "2014-03-15T19:09:53Z")

</div>

On 3/15/14 3:06 AM, Christopher Armstrong wrote:

> Any reason you're not using environments for location-specific attributes?

Hosts can only be in one environment. You can wind up with the cross  
product of all your locations with all your prod/int/test/dev  
application environments if you go down that road (us-west-1-prod,  
us-east-1-test, etc). If you've got a large company with multiple  
business units you might also want to mixin per-business-unit accounts  
as another dimension and this gets unwieldy to do as environments where  
you have to enumerate every cell and adding a new dimension is  
difficult. Its easier to have 'role[us-west-1],role[ecomm]' with  
environment = 'production'.

OTOH, if you're using pinned environments to do deployments you may want  
exceedingly fine grained environments, that are the cross product of  
(application-role)x(app-environment)x(datacenter)x(deployment-cell).  
You're going to need to carefully plan your automation around managing  
that right now since that will create a ton of environments and if  
you're doing that by hand it'll create a mess.
