Can you specify which data bag items a recipe should use at runtime?

Hi,

I’m new with chef, and I apologize if this is an overly simplistic
question, but I can’t seem to find the best way to approach this
problem.

I’ve got several clients (e.g. Acme, and Big Inc) for whom I’ve build
web apps, and I’d like to use Chef to deploy these. I’m using Hosted
Chef, and I’ve described each app in a data bag, but I’m not sure of
the best route to configure a single client’s app on a single node.

Here’s some background:

Each client’s app is described in a data bag item:

  • data_bags
    – apps
    — acme.json
    — big_inc.json

Each item looks something like this:
{
“id”: “acme”,
“path”:"/home/acme/app",
“server_name”:“acme.example.com”,
“enable”: true
}

and

{
“id”: “big_inc”,
“path”:"/home/big_inc/app",
“server_name”:“big_inc.example.com”,
“enable”: true
}

I’ve got a recipe (mycookbook::default) that looks something like this:

search(:apps) do |app|

web_app(app[‘id’]) do
docroot app[‘path’]
server_name app[‘server_name’]
template "apache.conf.erb"
enable app[‘enable’]
end

end

And I create a new node using the rackspace plugin, like so:
knife rackspace server create -N acme01 -S acme01 -r
"recipe[mycookbook::default]" -I 112 -f 1

This would install both apps (acme and big_inc) on the node. What’s
the preferred method for specifying which app should be configured on
a single node?

Should I delete the data bag items from the Chef Server (in the above
case, remove big_inc.json before creating the node)?

Or should I write client-specific recipes that search for some
distinguishing information in the data bag (e.g. I include the
client’s name as a key)? This seems like it would result in a lot of
duplicate code.

Or is there a better way to do this?

Thanks in advance!

  • Brad

One might consider a cookbook attribute containing a list of
applications to deploy to a given node, such as:

mycookbook/attributes/default.rb:

default.mycookbook.deployment_targets = [ "default" ]

environments/staging.rb

default.mycookbook.deployment_targets = [ "acme" ]

... So on,

Then, in your recipe, either construct a search (not going to do this
off the top of my head) or #each through data-bags:

node.mycookbook.deployment_targets.each do |deployment_target|
search(:apps, "id:#{deployment_target}) do |app|
web_app(app['id']) do

...

node.mycookbook.deployment_targets.each do |deployment_target|
app = data_bag_item "apps", deployment_target
web_app(app['id') do

...

Cheers,

AJ
On 26 January 2012 08:38, Brad Montgomery brad@bradmontgomery.net wrote:

Hi,

I'm new with chef, and I apologize if this is an overly simplistic
question, but I can't seem to find the best way to approach this
problem.

I've got several clients (e.g. Acme, and Big Inc) for whom I've build
web apps, and I'd like to use Chef to deploy these. I'm using Hosted
Chef, and I've described each app in a data bag, but I'm not sure of
the best route to configure a single client's app on a single node.

Here's some background:

Each client's app is described in a data bag item:

  • data_bags
    -- apps
    --- acme.json
    --- big_inc.json

Each item looks something like this:
{
"id": "acme",
"path":"/home/acme/app",
"server_name":"acme.example.com",
"enable": true
}

and

{
"id": "big_inc",
"path":"/home/big_inc/app",
"server_name":"big_inc.example.com",
"enable": true
}

I've got a recipe (mycookbook::default) that looks something like this:

search(:apps) do |app|

web_app(app['id']) do
docroot app['path']
server_name app['server_name']
template "apache.conf.erb"
enable app['enable']
end

end

And I create a new node using the rackspace plugin, like so:
knife rackspace server create -N acme01 -S acme01 -r
"recipe[mycookbook::default]" -I 112 -f 1

This would install both apps (acme and big_inc) on the node. What's
the preferred method for specifying which app should be configured on
a single node?

Should I delete the data bag items from the Chef Server (in the above
case, remove big_inc.json before creating the node)?

Or should I write client-specific recipes that search for some
distinguishing information in the data bag (e.g. I include the
client's name as a key)? This seems like it would result in a lot of
duplicate code.

Or is there a better way to do this?

Thanks in advance!

  • Brad