Handling dependencies

A very nifty feature of Chef is the ability to include recipes from one cookbook with another. This way, we can create cookbooks with a purpose, like a product or an end result. An example of such a cookbook could be an application cookbook named MyCloudApp, with calls to, or inclusions of, other cookbooks such as Apache, MySQL, or any other cookbook it might need.

Until now, we added recipe after recipe to the run list of our host. This is not optimal, and less than desirable when managing a lot of nodes. The idea here is to create a new cookbook dedicated to an imaginary MySite application, that will reference and depend on all the other recipes, so we can only load this MySite cookbook and be done with it.

Getting ready

To work through this recipe, you will need the following:

  • A working Chef DK installation on the workstation
  • A working Chef client configuration on the remote host
  • Optionally, the Chef code from the previous recipes

How to do it…

We know we want to create a new cookbook named mysite so we can centralize everything related to making this application work in the same place. Let's use the chef command to do that:

$ chef generate cookbook cookbooks/mysite

To include a recipe from another cookbook with our default recipe, we'll use the include_recipe method in mysite/recipes/default.rb:

include_recipe "apache"
include_recipe "apache::virtualhost"
include_recipe "mariadb"
include_recipe "php"

This is telling Chef to load and execute the content of each recipe.

For Chef to know where this is to be found, we need to create a dependency to those cookbooks. This is done in the mysite/metadata.rb file:

depends "apache"
depends "mariadb"
depends "php"

Now, our MySite cookbook has a nice dependency graph: to fully work, it needs Apache, MariaDB, and PHP. The recipe details what exactly to run.

Since we have a dedicated cookbook for our app, let's try to add some customization to it. Remember the default sitename attribute in the apache cookbook? Let's override it to match our own value by adding the following at the top of the file, just before the apache recipes inclusion:

node.override["sitename"] = "mysite"

Upload the cookbook to the Chef server:

$ knife cookbook upload mysite

Remove previous recipes from our node's run list using knife node run_list remove <node name> <recipe name>:

$ knife node run_list remove vagrant "recipe[mariadb]" "recipe[php]" "recipe[apache]" "recipe[apache::virtualhost]"

The node's run list is now empty. Simply add the new mysite cookbook that includes everything it needs to run:

$ knife node run_list add vagrant mysite

The next Chef client run won't change anything, but it will be much easier to manage in the future!

There's more…

Using puppet, a module can be used in other modules. Based on previous examples, we could think about a mysite module, with the following manifest:

class mysite (
   $website,
   $docroot
){
    class {
      'apache':;
      'php':;
      'mariadb':;
    }
    apache::vhost {$website:
       website => $website,
       docroot => $docroot,
    }
    file { $docroot:
      ensure => directory,
      owner   => 'www-data',
      group   => 'www-data',
      mode    => '0755',
    }
    file {"$docroot/index.php":
      ensure => present,
      owner   => 'www-data',
      group   => 'www-data',
      mode    => '0644',
      content => "<?php phpinfo() ?>",
    }
}

The main manifest of our node would be as follows:

node 'web.pomes.pro' {
    class {
      'mysite':
         website     => $fqdn,
         docroot  => "/var/www/$fqdn",
    }
}

See also

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.141.199.243