Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ChefSpec should not test included recipe

I have built a cookbook for installing Jenkins CI. It uses the key and repository resources from the yum cookbook, so I end up with the following recipe:

yum_key "RPM-GPG-KEY-jenkins" do
  url "http://pkg.jenkins-ci.org/redhat/jenkins-ci.org.key"
  action :add
end

yum_repository "jenkins" do
  description "Jenkins-CI 3rd party repository"
  url "http://pkg.jenkins-ci.org/redhat"
  key "RPM-GPG-KEY-jenkins"
  action :add
end

When I include this recipe in another recipe:

include_recipe 'sp_jenkins::default'

and I test this with the following ChefSpec test

it 'includes the `sp_jenkins::default` recipe' do
  expect(chef_run).to include_recipe('sp_jenkins::install')
end

my ChefSpec test fails with the following output:

NameError:
  Cannot find a resource for yum_key on chefspec version 0.6.1

(I'm not sure why it says version 0.6.1, gem list tells me it's using 3.0.2)

The sp_jenkins cookbook does depend on the yum cookbook (metadata.rb), and runs fine, however, the cookbook I'm currently writing does not depend on the yum cookbook and therefore doesn't have the yum_key and yum_repository methods available.

Is there a way to prevent ChefSpec from 'descending' into included recipes/cookbooks and just test the current cookbook?

like image 672
mtak Avatar asked Dec 12 '13 15:12

mtak


2 Answers

Ohai! Julian is correct - ChefSpec actually does a Chef Solo run in memory on your local machine. It rewrites the provider actions to be a noop, but creates a registry of all the actions taken (including those that would be taken if notifications were executed).

So just like you need the yum cookbook to converge this recipe on a real node, you need it to converge during your unit tests with ChefSpec. The easiest way to accomplish this is by using the Berkshelf or Librarian resolvers. To use the Berkshelf resolver, simply require 'chefspec/berkshelf' after requiring chefspec:

# spec_helper.rb
require 'chefspec'
require 'chefspec/berkshelf'

If you have Berkshelf installed on your system, it will pull all the cookbooks into a temporary directory and run ChefSpec for you.

You may also want to take a look at Strainer, which aims to solve a similar problem.


On a somewhat unrelated note, I am working on a fairly large refactor to the Jenkins cookbook that may better suit your needs.


Sources:

  • I wrote it...
like image 127
sethvargo Avatar answered Oct 18 '22 03:10

sethvargo


No, there's no way to prevent it from descending, because it's trying to converge an entire Chef run in memory.

However, if you use the Berkshelf functionality in ChefSpec, the Berkshelf dependency resolver will feed all dependent cookbooks to the in-memory Chef run, and you'll be golden.

like image 21
Julian Dunn Avatar answered Oct 18 '22 02:10

Julian Dunn