Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Specifying which cookbooks to run with Chef Solo

Tags:

chef-infra

I'm using chef-solo to test my cookbooks locally, but I want to be able to only run the cookbook(s) that I'm testing. Currently, it seems like chef-solo will run all cookbooks in the cookbooks directory specified in solo.rb. I've specified the run list in the json attributes file and specified the location of the json file in solo.rb, but that doesn't seem to help. It at least parses the attributes for all the other cookbooks, because I have one that doesn't work for my local configuration and it fails the entire run.

The best solution I've found so far is to move the cookbook(s) I need for testing to a different directory and specify that in solo.rb. Is there a better way to do it?

like image 311
Joshua Clark Avatar asked Mar 12 '12 18:03

Joshua Clark


People also ask

Where do you need to specify a cookbook dependency?

When we are using chef-server, we need to know such dependencies in cookbooks which should be decelerated in the cookbooks metadata file. This file is located at the top on the cookbook directory structure. It provides hints to the Chef server which helps in deploying cookbooks on the correct node.

How do you run a cookbook in chef workstation?

Step 1 − Install the cookbook using the following command. Step 2 − Run the knife cookbook test commands on the working cookbook. Step 3 − Break something in the cookbook and test again. Step 4 − Run the knife test command again.

What is the difference between chef-solo and Chef zero?

Because Chef Zero runs in memory, it's super fast and lightweight. This makes it perfect for testing against a “real” Chef Server without mocking the entire Internet. chef-solo is an open source version of the chef-client that allows using cookbooks with nodes without requiring access to a Chef server.


2 Answers

Update: chef-solo is no longer a "separate" tool from chef-client. From the documentation:

chef-solo is a command that executes chef-client in a way that does not require the Chef server in order to converge cookbooks. chef-solo uses chef-client’s Chef local mode, and does not support the following functionality present in chef-client / server configurations

This change was implemented in Chef version 12.11, which fulfills the community RFC. This was released on June 8, 2016. The old behavior, which is described below (albeit from 4 years ago at this time), is available with the --legacy-mode argument to chef-solo.

For the most current and up to date information about Chef Solo, please read the official documentation

My original answer is below:

Chef (solo OR client) does not "run" all the cookbooks.

It loads all the cookbook's Ruby files in the following directories, in this order:

  • libraries/*.rb
  • providers/*.rb
  • resources/*.rb
  • attributes/*.rb
  • definitions/*.rb

Then, it loads all the recipes that are in the node's expanded run list. With chef-solo, this comes from a JSON file supplied with -j, or can be done in attributes files - however the latter is deprecated and not recommended.

Any recipes that are included by those in the expanded run list via include_recipe are also loaded. Chef loads recipes by evaluating them as Ruby code. When it encounters ruby code that it recognizes to be a resource, or a definition, it adds the resource to the Resource Collection, which is an numerically ordered indexed hash of all the resources. Definitions are special, in that Chef adds the resources they contain, not the definition itself, to the Resource Collection. Included recipes' resources via include_recipe are inserted in place, then Chef continues in the including recipe.

Once Chef has processed all the recipes for all their resources, it walks the resource collection taking the specified action on each in the order it was added to the collection.

I highly recommend reading the documentation on this process. It applies to Chef Solo; only the part where the cookbooks are downloaded from the server is skipped.

  • https://docs.chef.io/chef_client.html#the-chef-client-run

To ensure that only the recipes that you want to test are tested, include them in the node's run list via a JSON file. It looks like this:

{ "run_list": ["recipe[mything]", "recipe[anotherthing]"] }

The run list is just an array, and items can be recipe[cookbookname] or role[somerole]. You can read more about how to use Roles with Chef Solo on the Chef Solo documentation.

  • https://docs.chef.io/chef_solo.html

If you have system changes being made when Chef is loading the cookbook components (the ruby files in each cookbook), then "You're Doing It Wrong"(tm) and should refactor those things to be done in a resource called from a recipe.

like image 51
jtimberman Avatar answered Nov 07 '22 03:11

jtimberman


Also worth noting that when testing you can easily override the runlist

chef-solo --override-runlist "role["somerole"],recipe[mycookbook::recipe]"
like image 21
KCD Avatar answered Nov 07 '22 03:11

KCD