2

I am writting a custom puppet module which includes an ::apache::vhost resource, and would like to verify in my rspec tests that the directories parameter contains a certain value, without reproducing the entire directories configuration which is mostly hardcoded in the spec test.

class foo::apache {

  # prepend 'from ' to each element in array of subnets
  # Change this ugliness to use map once we've upgraded to puppet v4
  # open to suggetions on better way to do this too...
  $subnets = $::foo::subnets
  $subnets_yaml = inline_template('<%= subnets.map {|s| "from " +s}.to_yaml %>')
  $allowed_subnets_directives = parseyaml($subnets_yaml)

  ::apache::vhost { 'foo_vhost':
    directories => [
       -- snip --
        ##### How can I check just the path & allow keys of this element?
      { 'path' => '~^.*$',
        'Order' => 'deny,allow',
        'allow' => concat(['from localhost'],
                   $allowed_subnets_directives),
        'provider' => 'location',
      },
    ]
  } # foo_vhost
} # foo::apache

I've removed most of the manifest for brevity.

I can test the entire directives parameter with something along the lines of

describe 'foo::apache' do
  it { is_expected.to contain_apache__vhost('foo_vhost').with(
    'directories' => [{'path' => '~^.*$',
                       'allow' => ['from localhost',
                                   'from 10.20.30/24',
                                  ],},
                     ]

but the directories parameter is long and static, and I'm keen to avoid that.

The rspec include matcher looks like what I need, but I can't work out how to use it to verify the parameter, or the $allowed_subnets_directives variable

1
  • 2
    FWIW, prepending stuff to everything in an array can be done in older versions using the regsubst function. Commented Jul 14, 2015 at 20:32

2 Answers 2

1

I recently stumbled onto this same problem. There isn't a clean way to directly access the inner part of a parameter.

I was talking with dev_el_ops in the voxpupuli channel on freenode and he said "one of the design problems of rspec-pupet is that it doesn't expose property values to the regular rspec matchers"

I'm not sure on the best way to 'find a hash with a key in an array' in ruby, so I'm referencing this answer The way that I would test the above is something like this

it do
  vhost_directories = catalogue.resource('apache__vhost', 'foo_vhost').send(:parameters)[:directories]
  expect(vhost_directories.find {|x| x[:path] == '~^.*$'}).to be_truthy
end

If you make the assumption that it is in the first entry in the array, you could use a slightly more readable 'include' matcher on the hash.

it do
  vhost_directories = catalogue.resource('apache__vhost', 'foo_vhost').send(:parameters)[:directories]
  expect(vhost_directories.first).to include(:path => '~^.*$')
end
Sign up to request clarification or add additional context in comments.

Comments

0

This request is some what old, however it is still relevant with rspec-puppet and puppet 5+. At least for simple (top-level) arrays, its possible to use regex values to test whether the value is contained in the parameters.

As an example, for the simple puppet class:

# simple test with array parameter
class array_test(
  Array[String] $values = [],
) {
  notify{"And the values are: ${values}": }
}

The following test includes regex checks for the expected values:

# frozen_string_literal: true

require 'spec_helper'
describe 'array_test' do

  context 'with default values for all parameters' do
    it { is_expected.to compile.with_all_deps }
    it { is_expected.to contain_class('array_test') }
  end
  context 'with there parameters' do
    let(:params) {{
      'values' => ['a','b','c','abcd']
    }}

    it { is_expected.to contain_class('array_test').with('values' => %r{"a"}) }
    it { is_expected.to contain_class('array_test').with('values' => %r{"b"}) }
    it { is_expected.to contain_class('array_test').with('values' => %r{"c"}) }
    it { is_expected.to contain_class('array_test').with('values' => %r{"abcd"}) }
    it { is_expected.not_to contain_class('array_test').with('values' => %r{"d"}) }
  end
end

Which, when ran, results in the following output:

$ bundle exec rake spec
(in /home/vagrant/git/array_test)
I, [2019-08-01T15:35:28.987120 #6373]  INFO -- : Creating symlink from spec/fixtures/modules/array_test to /home/vagrant/git/array_test
/home/vagrant/.rvm/rubies/ruby-2.4.4/bin/ruby -I/home/vagrant/.rvm/gems/ruby-2.4.4/gems/rspec-core-3.8.2/lib:/home/vagrant/.rvm/gems/ruby-2.4.4/gems/rspec-support-3.8.2/lib /home/vagrant/.rvm/gems/ruby-2.4.4/gems/rspec-core-3.8.2/exe/rspec --pattern spec/\{aliases,classes,defines,functions,hosts,integration,plans,tasks,type_aliases,types,unit\}/\*\*/\*_spec.rb

array_test
  with default values for all parameters
    should compile into a catalogue without dependency cycles
    should contain Class[array_test]
  with there parameters
    should contain Class[array_test] with values =~ /"a"/
    should contain Class[array_test] with values =~ /"b"/
    should contain Class[array_test] with values =~ /"c"/
    should contain Class[array_test] with values =~ /"abcd"/
    should not contain Class[array_test] with values =~ /"d"/

Finished in 1.03 seconds (files took 4.26 seconds to load)
7 examples, 0 failures


Code coverage
  must cover at least 0% of resources
Total resources:   2
Touched resources: 0
Resource coverage:  0.00%

Untouched resources:
  Notify[And the values are: []]
  Notify[And the values are: [a, b, c, abcd]]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.