How Run Cookbook with Dependencies in Chef

How run cookbook with dependencies in chef?

See here

Or just type knife cookbook upload --help and it will show you the following line (along others):

--include-dependencies Also upload cookbook dependencies

So knife cookbook upload myCookbook --include-dependencies is your answer

You'll need to have the maven cookbook on your workstation too, by knife cookbook site install maven or any other way to have a directory called maven in your local cookbook_path containing a cookbook where the metatada.rb file as a key name with value maven

Resolving chef-solo cookbook dependencies

Berkshelf is a popular tool in the Chef world to automate the installation of cookbook dependencies (the Berksfile you mentioned is related to this). If it isn't already, install berkshelf.

$ gem install berkshelf

Notice in your solo.rb file the line that says...

cookbook_path root + '/cookbooks'

...that's where Chef wants you to put the dependencies. Without Berkshelf, you would need to use knife to install apt into that cookbooks folder. (Note: cookbooks/ must be a git repo...)

$ knife cookbook site install apt

But since you have a Berksfile, you'll probable want to use the command below in the same folder your Berksfile is in...

$ berks vendor ../

That will install the dependencies for the current folder in the parent directory. You might need to specify a different location depending on where your root cookbooks folder is.

You might also be wondering why you have to specify the dependencies twice, once in your Berksfile and once in your metadata.rb file. Me too ;)

Chef cookbook dependency and recipe inclusion

This will work fine, but you don't NEED the third cookbook. You could create a recipe in cookbook B which is a no-op. Then add that recipe to the runlist of the node. This will cause the cookbook B to load on the node. You could alternatively set the node attribute inside that recipe rather than in node's attributes directly. Then, by putting said recipe in your runlist, you would get both done. So, either:

# recipe B::dummy.rb
# do nothing

OR

# recipe B::useme.rb
node['some']['attribute'] = 'B::dothis.rb'

Cookbook dependencies based on chef version

TL;DR

You're using a constraint from the Chef DSL in a way that it's not meant to be used. You need to branch based on a Boolean expression, not a metadata constraint. I provide a couple of ways to do that using String#to_f as examples (not recommended if you care about patch levels in semantic versioning), as well as the more accurate but often-overlooked Gem::Version.

Don't Use a Constraint for Branching

if chef_version '<= 12'

You're trying to use a constraint from the DSL. This constraint has a specific purpose: to declare the chef-client versions supported by the cookbook, not to provide logical branching. Without looking at the underlying Chef code for the DSL, I'd say it's unlikely that the expression is feeding your if-then expression the way you expect. Setting aside for the moment whether this is the right pattern to follow at all, you can try grabbing the current version of your Chef tools in a couple of different ways:

  1. Branching on the chef-client version, likely cast as a Float (it's normally a String). For instance:

    if Chef::VERSION.to_f <= 12
  2. Get the node value from ohai with something like:

    if node['chef_packages']['chef']['version'].to_f <= 12
  3. Parse the value directly from the client, e.g.:

    depends %x(chef-client --version).split[1].to_f <= 12 ? 'ypg_tomcat' : 'yp_tomcat'

However, in all cases, you're going to have to deal with the fact that you're being passed a String containing semantic versioning, not a Float or Integer. So, you'll have to figure out how you really want to parse the information, which is potentially error-prone (see below for a trick using Gem::Version, though). In any case, once you've parsed it the way you want, you can match it using a comparison operator to get the branching behavior you want.

Better Options

Rather than trying to make the metadata constraint hold business logic, you should probably move the data out to an attribute. Consider an attribute such as node['yp_linko']['tomcat_cookbook'], which you can set based on some other detectable node value other than semantic versioning.

Another approach would be to declare both cookbooks a dependency, and then include the one you want inside a recipe in your yp_linko cookbook. For example, assuming you haven't declared incompatible chef-client versions in the Tomcat cookbooks:

# metadata.rb
depends 'yp_tomcat'
depends 'ypg_tomcat'

# default.rb
if Chef::VERSION <= Gem::Version.new(12)
include ypg_tomcat::default
else
include yp_tomcat::default
end

And finally, you should consider whether it really makes sense to be running different versions of your Chef clients within the infrastructure in the first place. There may be a business need to do that, but it's the real problem you're actually trying to solve for. Branching in your cookbooks is an X/Y solution to an infrastructure issue. It seems likely that you'd have other cookbooks with similar issues, so it's at least worth considering whether it makes more sense to get all your clients on the same version rather than solving the problem at the cookbook level.

Adding Dependencies to Chef Cookbooks

Check out http://berkshelf.com. It allows you to create a Berksfile where you specify the gems you will need, and handles dependency resolution.

Trying to run Chef-client without using dependencies of a certain cookbook

Chef does not support optional dependencies.



Related Topics



Leave a reply



Submit