Newbie design related doubt

I know that attributes can be configured in cookbooks (attribute files and
recipes), roles, and environments.

Suppose I have a requirement on the following lines:

  • Two environments: alpha and beta
  • Two web servers: web-1, web-2
  • Apache should run on port 80 on web-1 in alpha
  • Apache should run on port 8080 on web-2 in alpha
  • Apache should run on port 8081 on web-1 and web-2 in beta

I can have two approaches:
SOLUTION 1. Write a role cookbook (using application/library pattern) and
override the apache[listen_ports] attribute in the role cookbook. Again
override the apache[listen_ports] attribute in my
chef-repo/environments/alpha.rb and chef-repo/environments/beta.rb file.
But this way the configuration for Apache is scattered in multiple places
(environment files, role cookbooks and the apache community cookbook).

SOLUTION 2. Write a wrapper cookbook over the community apache cookbook. In
the attribute file of my wrapper cookbook, I write logic like this:

apache[listen_ports] = 8080
if env is alpha
if role is web1
apache[listen_ports] = 80
elseif role is web2
apache[listen_ports] = 8080
end

This way all apache settings are consolidated in one place i.e. in the
cookbook.

I have seen all the blog posts suggest the first solution. Why is the
second solution a bad idea?

Le 2014-10-30 12:21, Varun Shankar a écrit :

I know that attributes can be configured in cookbooks (attribute files and recipes), roles, and environments.

Suppose I have a requirement on the following lines:

  • Two environments: alpha and beta
  • Two web servers: web-1, web-2
  • Apache should run on port 80 on web-1 in alpha
  • Apache should run on port 8080 on web-2 in alpha
  • Apache should run on port 8081 on web-1 and web-2 in beta

I can have two approaches:
SOLUTION 1. Write a role cookbook (using application/library pattern) and override the apache[listen_ports] attribute in the role cookbook. Again override the apache[listen_ports] attribute in my chef-repo/environments/alpha.rb and chef-repo/environments/beta.rb file. But this way the configuration for Apache is scattered in multiple places (environment files, role cookbooks and the apache community cookbook).

SOLUTION 2. Write a wrapper cookbook over the community apache cookbook. In the attribute file of my wrapper cookbook, I write logic like this:

apache[listen_ports] = 8080
if env is alpha
if role is web1
apache[listen_ports] = 80
elseif role is web2
apache[listen_ports] = 8080
end

This way all apache settings are consolidated in one place i.e. in the cookbook.

I have seen all the blog posts suggest the first solution. Why is the second solution a bad idea?

Usually, the second is a bad idea after a while, when you'll have a tree
of if/else with a 5 or 6 levels deep which become unmaintanable.

Second reason to avoid it: suppose you wish to make a change to some
parameter on web-1, then another parameter change on web-2 has to be
done (security fix for exemple) , you'll have two independent changes in
the same cookbook.

You probably don't wish to push both in production at the same time.

So you'll have a third change reverting the one not urgent before
promoting to production, with time it becomes a mess and a nightmare to
follow and ensure you psuh in production exactly what you expect.

Having things in different places (cookbooks) helps you promote one with
its own changes without needing to pull other unwanted/unexepected
changes.

Hope it helps understanding why the wrapper cookbook pattern is the
recomended choice.