[chef] Re: Re: Re: Re: More on Cookbook Design Patterns


Chronological Thread 
  • From: Jay Perry < >
  • To:
  • Cc: " " < >
  • Subject: [chef] Re: Re: Re: Re: More on Cookbook Design Patterns
  • Date: Thu, 3 Apr 2014 10:29:05 -0400

Thanks Tom.  So let me make sure I'm following you correctly about the base cookbook.  It would look something like:

base cookbook
  recipes
    default.rb
    monitoring.rb
    chef-cleint.rb
    etc

and the default.rb includes all the others which we would want all Acme Co, servers to have right? and if we have an oracle server that needs to have a different base we could either create an oracle recipe in the base cookbook (that pieces the other sub-recipes together) or have another cookbook responsible for bring up our oracle server define it's base list.  I like this suggested break up and yes our base cookbook has too much in it like you noticed :).  If I took this approach would you suggest each application cookbook has a depends on the base cookbook and does an include_recipe 'base::default'.  I feel this is necessary since a role wouldn't live with the cookbook and makes testing more difficult and having the application cookbook know what it needs to get up and running is the best approach.  We still use roles but more so to add to a runlist and for searching (I think this could eventually be replaced by tags if we wanted to ditch roles all together).  

Also back to your recommendation about a particular pattern for creating users.  Currently we have a "users" cookbook that defines all the different types of users we create and they each have their own recipe (for example it pulls in keys from databags, sets permissions, sudo rights etc).  This seems like this cookbook is taking on too much responsibility and that we could provide a "users" platform cookbook that exposes this but then my question is should the application cookbook use that resource exposed by the "users" cookbook to create the user?  My guess is yes rather than calling say the "users::tomcat" recipe like we do today.  Thoughts?

Thanks again, this has been a great discussion.


On Thu, Apr 3, 2014 at 9:55 AM, Tom Duffield < " target="_blank"> > wrote:
Hey Jay, 
A wrapper cookbook around an existing infrastructure or platform cookbook like java or apache is technically still a infrastructure or platform cookbook. Application cookbooks are unique to a specific application while java and apache cookbooks can be used for more than one application. Infrastructure and Platform Cookbooks are designed to be shared (even if just within a single organization) and used by multiple application cookbooks, so if your java or apache wrapper cookbooks could be used for more than one application then they are still infrastructure or platform cookbooks. If they cannot be used by more than one application cookbook, then the wrapper code for java or apache should probably be part of the cookbook for the application in question and not a separate cookbook. 

I would argue that your "base" cookbook (as it stands) doesn't fall into any of the cookbook patterns because it is simply a role. Role cookbooks are outside the infra/platform/app cookbook paradigm because your using a cookbook to accomplish what a Chef Role will already do. Now I understand the dislike/distrust of Chef roles (versioning and what have you) and I wont feed the fire of that debate but I think the solution here is to shift your thinking about your "base" cookbook. In your role above, you have an "unless" statement checking for 'role[oracle]'. That statement right away tells me that this configuration is not global. You also have 'yum::client' which tells me that you have RH systems and 'users::ubuntu' which I assume is a custom cookbook to manage users on ubuntu systems. 

I would rethink your approach to this base role and ask yourself this question: what are you trying to provide to the chef-developer downstream? What is this a base for? Are you providing a one size fits all solution for all applications? That rarely works and as you grow, your "unless" statements will multiple like rabbits. My goal when I came up with the infra/platform/app paradigm was to provide a framework that lent itself to helping cookbooks become more modular. People should be able to pull the bits and pieces that they need and only the pieces that they need. 

This is what I think you should do - rebrand your base cookbook as an platform cookbook for your organization. Tell yourself "this is the cookbook for the platform that is an Acme, Co server." Next I would split that big chunk of include_recipes into smaller, closely related chunks and put those chunks into "sub-recipes" (i.e. monitoring, users, chef-client, etc). Have your default recipe include all the sub-recipes by if you want but at least now, if you have a one off app like oracle, your base cookbook doesn't have to be changed to accommodate it or the app cookbook doesn't need to completely rebuild the base cookbook to avoid the problem.

Also, with the platform cookbook pattern, if Acme, Co has a particular pattern for creating users you could expose a custom Acme, Co user resource. If there a common patterns to how Acme, Co creates their nagios alerts, wrap that up into a custom resource and expose those to the end users! Maybe your nagios alert can automatically detect which server it needs to send alerts to so the end users dont have to worry about specifying that! When your infrastructure becomes a platform, the opportunities are endless :) 

2014-04-02 19:24 GMT-05:00 JayP < " target="_blank"> >:

Thanks Tom for the slide deck and recommendation.  I think this could be a
viable solution and breaks up the different cookbooks nicely.  Would a wrapper
cookbook fall under application cookbook where the purpose is wrapping say a
java cookbook or an apache2 cookbook?  About the base cookbook being an
application cookbook currently our base cookbook is mainly used for defining a
base run list instead of using a role.  For example this is what our
base::default recipe looks like:

```
# Attributes
node.normal['chef_client']['cron']['minute'] = '0,15,30,45'
node.normal['chef_client']['cron']['hour'] = '*'
node.normal['chef_client']['cron']['log_file'] = '/dev/null'
node.normal['chef_client']['cron']['use_cron_d'] = false
node.normal['chef_client']['splay'] = 900
node.normal['chef_client']['log_file'] = 'client.log'

# Run List
include_recipe 'debug::before'
include_recipe 'chef_handler'
include_recipe 'chef_handler::register_handlers'
include_recipe 'chef-client::delete_validation'
include_recipe 'ohai'
include_recipe 'chef-client::config'
include_recipe 'chef_data_bags'
include_recipe 'chef_helpers'
include_recipe 'chef-client::cron'
include_recipe 'yum::client'
include_recipe 'cron'
include_recipe 'users::root'
include_recipe 'users::ubuntu'
include_recipe 'users::screen_session'
include_recipe 'users::scrub'
include_recipe 'users::pkg_action'
include_recipe 'openssh'
include_recipe 'apparmor::disable'
include_recipe 'sendmail::disable'
include_recipe 'dns::hosts' unless node.run_list.include?("role[oracle]")
include_recipe 'dns::resolv.conf'
include_recipe 'dns::nsupdate'
include_recipe 'hostname'
include_recipe 'motd'
include_recipe 'bash'
include_recipe 'pkgutil'
include_recipe 'ntp'
include_recipe 'openldap::client'
include_recipe 'python'
include_recipe 'python::common_modules'
include_recipe 'diamond'
include_recipe 'zip'
include_recipe 'sudoers'
include_recipe 'ulimit'
include_recipe 'acpi'
include_recipe 'nagios::nrpe'
include_recipe 'nagios::send_nsca'
include_recipe 'diamond::nrpe'
include_recipe 'genders'
include_recipe 'sysstat'
include_recipe 'syslog'
include_recipe 'xml'
include_recipe 'postfix'
include_recipe 'mail::client'
include_recipe 'tmpreaper'
include_recipe 'ncftp::client'
include_recipe 'bash-completion'
include_recipe 'chef-registration'
include_recipe 'chef-registration::client'
include_recipe 'debug::after'
include_recipe 'omnibus_updater'
```

I was also wondering with your layout is it okay if an application cookbook
depend on another application cookbook?  I guess what I'm asking if I had a
base cookbook would you include the recipe it in an application cookbook or
have it be part of a role run_list which is something we have avoided due to
roles being global.  Thanks in advance.

- Jay





Archive powered by MHonArc 2.6.16.

§