Search code examples
chef-infrachefspec

Verify package from node attributes was installed


I have a cookbook that installs a list of packages provided by node attributes. Is it possible to test this type of package installation with chefspec? As it is now, I receive an error:

1) foo::default installs test-package-1
 Failure/Error: expect(chef_run).to install_package(pkg)
   expected "package[test-package-1]" with action :install to be in Chef run. Other package resources:
     package[["test-package-1", "1.0.0"]]
     package[["test-package-2", "1.2.3"]]

Chefspec isn't seeing that the package is being installed, even though it's listed right there! Surely I'm missing something obvious here.

Here's the relevant cookbook files:

attributes/default.rb

node.default['foo']['packages'] = {
  'test-package-1' => '1.0.0',
  'test-package-2' => '1.2.3'
}

recipes/default.rb

node['foo']['packages'].each do |pkg|
  package pkg do
    version node['foo']['packages'][pkg]
    action :install
  end
end

spec/default_spec.rb

describe "foo::default" do
  let(:chef_run) { ChefSpec::SoloRunner.converge(described_recipe) }

  %w(
    test-package-1
    test-package-2
  ).each do |pkg|
    it "installs #{pkg}" do
      expect(chef_run).to install_package(pkg)
    end
  end
end

Solution

  • Ruby's Hash#each is an alias for each_pair, not each_key. This is different from languages like Python and JavaScript which default to iterating over the keys. In this case your test is correct in showing you that your recipe code is wrong :-)

    node['foo']['packages'].each do |pkg, pkg_ver|
      package pkg do
        version pkg_ver
        action :install
      end
    end