Chained dependencies management


#1

Hello Chef Cookers,

I am looking for a way to manage cookbook dependencies, as our infrascture
grows and thus the complexity too, dependencies are becoming hard to manage.

We use include_recipe in cases where we only use a lightweight resource defined
by that particular cookbook. Since include_recipe only loads the direct cookbook
and not the includes that cookbook might contains.

Why it does not do this?
Is it a design option?
Or a limitation that is going to be completed in the future?

I would like to hear your opinion on this.


Regards
Alfredo Palhares


#2

include_recipe actually includes (and runs) a recipe. When used in the shorthand form, like

include_recipe "other_cookbook"

It runs the default recipe from that cookbook, just as including “recipe[other_cookbook]” in a role run_list would do. To have Chef manage dependencies for you, you should use the “depends” attribute in your cookbook metadata. For example, in metadata.rb, you would add:

depends "other_cookbook"

(There is a similar form if you are using metadata.json directly.) Now when Chef runs and realizes that it needs to include your current cookbook, it will also include other_cookbook.

To use an LWRP from another cookbook, I don’t believe you need to include_recipe at all (someone please correct me if I’m wrong), you just need to have that cookbook available on the system (which is what depends does). Note however that some LWRPs also expect a corresponding recipe to be run, either before or after – so read the instructions from that cookbook.

  • Dan

On Aug 9, 2012, at 10:00 AM, Alfredo Palhares wrote:

Hello Chef Cookers,

I am looking for a way to manage cookbook dependencies, as our infrascture
grows and thus the complexity too, dependencies are becoming hard to manage.

We use include_recipe in cases where we only use a lightweight resource defined
by that particular cookbook. Since include_recipe only loads the direct cookbook
and not the includes that cookbook might contains.

Why it does not do this?
Is it a design option?
Or a limitation that is going to be completed in the future?

I would like to hear your opinion on this.


Regards
Alfredo Palhares


#3

I just want include that the chef env will also help to manage n develop/enhance the production cookbook without messing with the running version of cookbook.

In the env file, u can specify the version of the cookbook.

Via Millisami’z iPhone

On Aug 9, 2012, at 8:05 PM, Dan Crosta dcrosta@late.am wrote:

include_recipe actually includes (and runs) a recipe. When used in the shorthand form, like

include_recipe “other_cookbook”

It runs the default recipe from that cookbook, just as including “recipe[other_cookbook]” in a role run_list would do. To have Chef manage dependencies for you, you should use the “depends” attribute in your cookbook metadata. For example, in metadata.rb, you would add:

depends “other_cookbook”

(There is a similar form if you are using metadata.json directly.) Now when Chef runs and realizes that it needs to include your current cookbook, it will also include other_cookbook.

To use an LWRP from another cookbook, I don’t believe you need to include_recipe at all (someone please correct me if I’m wrong), you just need to have that cookbook available on the system (which is what depends does). Note however that some LWRPs also expect a corresponding recipe to be run, either before or after – so read the instructions from that cookbook.

  • Dan

On Aug 9, 2012, at 10:00 AM, Alfredo Palhares wrote:

Hello Chef Cookers,

I am looking for a way to manage cookbook dependencies, as our infrascture
grows and thus the complexity too, dependencies are becoming hard to manage.

We use include_recipe in cases where we only use a lightweight resource defined
by that particular cookbook. Since include_recipe only loads the direct cookbook
and not the includes that cookbook might contains.

Why it does not do this?
Is it a design option?
Or a limitation that is going to be completed in the future?

I would like to hear your opinion on this.


Regards
Alfredo Palhares


#4

My opinion (and I don’t know if it’s a very popular one), is that
include_recipe is an anti-pattern when used between cookbooks. It deeply
couples the implementation details of two separate cookbooks. When using
open sourced cookbooks that use include_recipe, you often are required to
use the specific cookbooks that one was written against.

My solution has been that cookbooks and recipes are to be written in
isolation and be heavily managed by attributes. A piece of software and
all of it’s dependencies should be wrapped up in the run_lists in one
nice little role. That way anyone composing a new node merely has to choose
from the available roles and know full well that their dependencies are
encapsulated in that role. This pattern has been quite successful. Our
junior developers are able to pull in the roles they need, without being
concerned with the implementation details of the underlying cookbooks.

We have a role for every piece of infrastructure, even if it only has one
recipe in it’s run_list right now. The idea is that the cookbook may change
over time and introduce dependencies. If we composed the nodes with a
"role" per infrastructure component from the beginning, we merely have to
update the role and promote those cookbook changes to the production
environment.

If a cookbook supplies providers, I make a recipe called “providers” and
call it via something like “recipe[rabbitmq::providers]”. That makes it
explicit that I’m to be using the providers from a given cookbook for later
recipes in this role.

Keeps things clean, decoupled, and provides a higher level layer on top of
the cookbooks to compose infrastructure from.

Hope that helps!
-Kevin

On Fri, Aug 10, 2012 at 3:05 AM, Millisi millisami@gmail.com wrote:

I just want include that the chef env will also help to manage n
develop/enhance the production cookbook without messing with the running
version of cookbook.

In the env file, u can specify the version of the cookbook.

Via Millisami’z iPhone

On Aug 9, 2012, at 8:05 PM, Dan Crosta dcrosta@late.am wrote:

include_recipe actually includes (and runs) a recipe. When used in the
shorthand form, like

include_recipe “other_cookbook”

It runs the default recipe from that cookbook, just as including
"recipe[other_cookbook]" in a role run_list would do. To have Chef manage
dependencies for you, you should use the “depends” attribute in your
cookbook metadata. For example, in metadata.rb, you would add:

depends “other_cookbook”

(There is a similar form if you are using metadata.json directly.) Now
when Chef runs and realizes that it needs to include your current cookbook,
it will also include other_cookbook.

To use an LWRP from another cookbook, I don’t believe you need to
include_recipe at all (someone please correct me if I’m wrong), you just
need to have that cookbook available on the system (which is what depends
does). Note however that some LWRPs also expect a corresponding recipe to
be run, either before or after – so read the instructions from that
cookbook.

  • Dan

On Aug 9, 2012, at 10:00 AM, Alfredo Palhares wrote:

Hello Chef Cookers,

I am looking for a way to manage cookbook dependencies, as our
infrascture

grows and thus the complexity too, dependencies are becoming hard to
manage.

We use include_recipe in cases where we only use a lightweight resource
defined

by that particular cookbook. Since include_recipe only loads the direct
cookbook

and not the includes that cookbook might contains.

Why it does not do this?
Is it a design option?
Or a limitation that is going to be completed in the future?

I would like to hear your opinion on this.


Regards
Alfredo Palhares


#5

Kevin Nuckolls wrote:

My opinion (and I don’t know if it’s a very popular one), is that
include_recipe is an anti-pattern when used between cookbooks. It deeply
couples the implementation details of two separate cookbooks. When using
open sourced cookbooks that use include_recipe, you often are required to
use the specific cookbooks that one was written against.

Does that apply to internal cookbooks as well? I’ve found that I’m
increasingly refactoring, say, role[base] into a single run-list item that
calls recipe[mysite::role-base]. This lets me use the Ruby DSL, LWRPs,
normal-level attributes, and anything other API the “real” cookbook provides.

I hate the un-DRYness of specifying both include_recipe(‘postgresql’) in
mysite/roles/role-base.rb and depends(‘postgresql’) in mysite/metadata.rb,
but the purely declarative role syntax just doesn’t let me do a lot of things…

Jay


#6

Thanks for the input guys !


Regards,
Alfredo Palhares


#7

Alfredo, you might also be interested in librarian[1] or berkshelf[2].

They both follow a Bundler/Gemfile-like approach for managing cookbook
dependencies.

[1] https://github.com/applicationsonline/librarian
[2] https://github.com/RiotGames/berkshelf

Cheers,
Torben

On Mon, Aug 13, 2012 at 10:44 AM, Alfredo Palhares
masterkorp@masterkorp.net wrote:

Thanks for the input guys !


Regards,
Alfredo Palhares


#8

Does that apply to internal cookbooks as well?

In my opinion yes. I don’t use include_recipe anywhere and I feel like I’m
better for it. Everything’s dependencies are encapsulated in roles.

On Sun, Aug 12, 2012 at 2:11 PM, Jay Levitt jay.levitt@gmail.com wrote:

Kevin Nuckolls wrote:

My opinion (and I don’t know if it’s a very popular one), is that
include_recipe is an anti-pattern when used between cookbooks. It deeply
couples the implementation details of two separate cookbooks. When using
open sourced cookbooks that use include_recipe, you often are required to
use the specific cookbooks that one was written against.

Does that apply to internal cookbooks as well? I’ve found that I’m
increasingly refactoring, say, role[base] into a single run-list item that
calls recipe[mysite::role-base]. This lets me use the Ruby DSL, LWRPs,
normal-level attributes, and anything other API the “real” cookbook
provides.

I hate the un-DRYness of specifying both include_recipe(‘postgresql’) in
mysite/roles/role-base.rb and depends(‘postgresql’) in mysite/metadata.rb,
but the purely declarative role syntax just doesn’t let me do a lot of
things…

Jay


#9

On Fri, Aug 10, 2012 at 5:22 PM, Kevin Nuckolls
kevin.nuckolls@gmail.com wrote:

My opinion (and I don’t know if it’s a very popular one), is that
include_recipe is an anti-pattern when used between cookbooks. It deeply
couples the implementation details of two separate cookbooks. When using
open sourced cookbooks that use include_recipe, you often are required to
use the specific cookbooks that one was written against.

My solution has been that cookbooks and recipes are to be written in
isolation and be heavily managed by attributes. A piece of software and all
of it’s dependencies
should be wrapped up in the run_lists in one nice
little role. That way anyone composing a new node merely has to choose from

Hear, hear! I wholeheartedly agree.