mickm
mickm

Reputation: 391

chefspec: setting global node attributes to be used in all tests in recipe

I'm currently writing a chefspec recipe which sets certain node attributes, which are necessary to complete my unit tests. I am currently setting these attributes in each test, which seems wasteful. I wish to carry this out in such a way that I am not repeating code, i.e. "global attributes?".

My current working recipe is as follows:

# encoding: UTF-8
require_relative '../spec_helper'

osd_device = '/ceph-1-osd'

describe 'ceph::per-host-osd' do
   let(:runner) { ChefSpec::Runner.new }
   let(:chef_run) { runner.converge(described_recipe) }
   let(:node) { runner.node }

    # Test whether directory is created with specifed attributes
    # Node attributes are necessary to satisfy logic of parent recipe
    it 'creates a directory with root ownership and permissions' do
     node.automatic['fqdn'] = 'ceph-1'
     node.set['ceph']['hosts']['ceph-1']
     node.set['ceph']['hosts']['ceph-1']['osd_devices'] = [{device: "/ceph-1-osd", journal: "/ceph-1-journal/journal", type: "directory"}]
    expect(chef_run).to create_directory("#{osd_device}").with(
      user:   'root',
      group:  'root',
    )
    end

   it 'executes ceph-disk-prepare and ceph-disk-activate' do
      node.automatic['fqdn'] = 'ceph-1'
      node.set['ceph']['hosts']['ceph-1']
      node.set['ceph']['hosts']['ceph-1']['osd_devices'] = [{device: "/ceph-1-osd", journal: "/ceph-1-journal/journal", type: "directory"}]
      expect(chef_run).to run_execute("ceph-disk-prepare on #{osd_device}")
      expect(chef_run).to run_execute("ceph-disk-activate #{osd_device}")
   end
end

This chefspec test passes without issue:

.....

Finished in 4.99 seconds (files took 8.13 seconds to load)
5 examples, 0 failures
Coverage report generated for RSpec to /Users/joe.bloggs/workspace/cookbook_ceph/build/report/coverage/coverage.xml

However, I wish to set the 'node.automatic' and 'node.set' statements only once (outside of the tests) and then to reuse them in the subsequent tests.

My efforts to set these attributes "globally" looks like this:

# encoding: UTF-8
require_relative '../spec_helper'

osd_device = '/ceph-1-osd'

describe 'ceph::per-host-osd' do
   let(:chef_run) do
     ChefSpec::Runner.new do |node|
       node.automatic['fqdn'] = 'ceph-1'
       node.set['ceph']['hosts']['ceph-1']
       node.set['ceph']['hosts']['ceph-1']['osd_devices'] = [{device: "/ceph-1-osd", journal: "/ceph-1-journal/journal", type: "directory"}]
     end
   end
    # Test whether directory is created with specifed attributes
    # Node attributes are necessary to satisfy logic of parent recipe
    it 'creates a directory with root ownership and permissions' do
      expect(chef_run).to create_directory("#{osd_device}").with(
        user:   'root',
        group:  'root',
      )
    end
    it 'executes ceph-disk-prepare and ceph-disk-activate' do
       expect(chef_run).to run_execute("ceph-disk-prepare on #{osd_device}")
       expect(chef_run).to run_execute("ceph-disk-activate #{osd_device}")
    end
end

It returns the following error:

...FF

Failures:

  1) ceph::per-host-osd creates a directory with root ownership and permissions
     Failure/Error: expect(chef_run).to create_directory("#{osd_device}").with(
     NoMethodError:
       undefined method `resource_collection' for nil:NilClass
     # ./spec/unit/per-host-osd_spec.rb:17:in `block (2 levels) in <top (required)>'

  2) ceph::per-host-osd executes ceph-disk-prepare and ceph-disk-activate
     Failure/Error: expect(chef_run).to run_execute("ceph-disk-prepare on #{osd_device}")
     NoMethodError:
       undefined method `resource_collection' for nil:NilClass
     # ./spec/unit/per-host-osd_spec.rb:23:in `block (2 levels) in <top (required)>'

Finished in 3.12 seconds (files took 8.46 seconds to load)
5 examples, 2 failures

Failed examples:

rspec ./spec/unit/per-host-osd_spec.rb:16 # ceph::per-host-osd creates a directory with root ownership and permissions
rspec ./spec/unit/per-host-osd_spec.rb:22 # ceph::per-host-osd executes ceph-disk-prepare and ceph-disk-activate
Coverage report generated for RSpec to /Users/joe.bloggs/workspace/cookbook_ceph/build/report/coverage/coverage.xml

I'm new to chefspec, so perhaps I'm missing something. Any help is greatly appreciated. Thanks.

Upvotes: 3

Views: 3129

Answers (1)

Tensibai
Tensibai

Reputation: 15784

In your second form you're never converging any recipe, so obviously there's no resource_collection to test against.

Add a converge(described_recipe) at the end of your runner definition.

let(:chef_run) do
     ChefSpec::Runner.new do |node|
       node.automatic['fqdn'] = 'ceph-1'
       node.set['ceph']['hosts']['ceph-1']
       node.set['ceph']['hosts']['ceph-1']['osd_devices'] = [{device: "/ceph-1-osd", journal: "/ceph-1-journal/journal", type: "directory"}]
     end.converge(described_recipe)
end

Upvotes: 4

Related Questions