Take a look at the gist below for the code in question. Essentially it is taking a hash of packages with name and version key/value pairs, then iterating over them to populate the chef_gem resource.
We just discovered that this code is being run twice when executing chef-client on the node. After a bit of digging in the anatomy of a chef run wiki page, we discovered the following snippet that explained why this is happening.
http://wiki.opscode.com/display/chef/Anatomy+of+a+Chef+Run
Here:
Load Recipes
At this point, the Recipes themselves are evaluated. We are not taking any action on the resources in the recipes at this stage - we are taking each evaluated resource and putting it in the Resource Collection.
- This is essentially an Array of each evaluated resource, along with some helpful functions.
- Plain Ruby code outside of resources is evaluated, however.
- If you would like Ruby code executed with other resources, use a Ruby Block Resource.
- You can have Chef Evaluate and Run Resources at Compile Time, too.
This points out that plain old ruby code that is not part of a resource will be executed when a recipe is loaded, and then again later when convergence happens. That explains why it's running twice. My question is, what is the best practice for taking a list of dependencies (name and version) then running it through the chef resource to do the install only when chef converges on the node?