From 6df163b6c0de88306549ba73a77b97523d32af23 Mon Sep 17 00:00:00 2001 From: Kjetil Torgrim Homme Date: Wed, 5 Jul 2017 18:00:09 +0200 Subject: [PATCH] Add .tagged and .not_tagged methods for resource matcher --- README.md | 7 ++ lib/rspec-puppet/matchers/create_generic.rb | 78 +++++++++++++++++---- spec/fixtures/manifests/site.pp | 12 ++++ spec/hosts/tags_testing_spec.rb | 19 +++++ spec/unit/matchers/compile_spec.rb | 4 +- 5 files changed, 103 insertions(+), 17 deletions(-) create mode 100644 spec/hosts/tags_testing_spec.rb diff --git a/README.md b/README.md index cc47791d9..706126aa1 100644 --- a/README.md +++ b/README.md @@ -403,6 +403,13 @@ it { is_expected.to contain_service('keystone').without( )} ``` +You can test if the resource has the expected tags with the `tagged` and +`not_tagged` methods. + +```ruby +it { is_expected.to contain_service('keystone').tagged('site:cph') } +``` + #### Checking the number of resources You can test the number of resources in the catalogue with the diff --git a/lib/rspec-puppet/matchers/create_generic.rb b/lib/rspec-puppet/matchers/create_generic.rb index 971590e4c..9f9334c1c 100644 --- a/lib/rspec-puppet/matchers/create_generic.rb +++ b/lib/rspec-puppet/matchers/create_generic.rb @@ -20,6 +20,8 @@ def initialize(*args, &block) @subscribes = [] @requires = [] @befores = [] + @tagged = [] + @not_tagged = [] end def with(*args, &block) @@ -60,6 +62,16 @@ def that_comes_before(resource) self end + def tagged(resource) + @tagged.concat(Array(resource)) + self + end + + def not_tagged(resource) + @not_tagged.concat(Array(resource)) + self + end + def method_missing(method, *args, &block) if method.to_s =~ /^with_/ param = method.to_s.gsub(/^with_/, '') @@ -114,6 +126,8 @@ def matches?(catalogue) check_params(rsrc_hsh, @expected_params, :should) if @expected_params.any? check_params(rsrc_hsh, @expected_undef_params, :not) if @expected_undef_params.any? + check_tags(resource, @tagged, :should) if @tagged.any? + check_tags(resource, @not_tagged, :not) if @not_tagged.any? check_befores(@catalogue, resource) if @befores.any? check_requires(@catalogue, resource) if @requires.any? check_notifies(@catalogue, resource) if @notifies.any? @@ -132,8 +146,8 @@ def failure_message_when_negated end def description + tests = [] values = [] - value_str_prefix = "with" if @expected_params_count values << "exactly #{@expected_params_count} parameters" @@ -148,34 +162,39 @@ def description end if @notifies.any? - value_str_prefix = "that notifies" - values = @notifies + tests << english_list("that notifies", @notifies) end if @subscribes.any? - value_str_prefix = "that subscribes to" - values = @subscribes + tests << english_list("that subscribes to", @subscribes) end if @requires.any? - value_str_prefix = "that requires" - values = @requires + tests << english_list("that requires", @requires) end if @befores.any? - value_str_prefix = "that comes before" - values = @befores + tests << english_list("that comes before", @befores) + end + + if @tagged.any? + tests << english_list("that is tagged", @tagged) + end + + if @not_tagged.any? + tests << english_list("that is not tagged", @not_tagged, "nor") end unless values.empty? - if values.length == 1 - value_str = " #{value_str_prefix} #{values.first}" - else - value_str = " #{value_str_prefix} #{values[0..-2].join(", ")} and #{values[-1]}" - end + tests << english_list("with", values) end - "contain #{@referenced_type}[#{@title}]#{value_str}" + tests_str = "" + unless tests.empty? + tests_str = english_list("", tests, "and", true) + end + + "contain #{@referenced_type}[#{@title}]#{tests_str}" end def diffable? @@ -225,6 +244,16 @@ def generate_param_list(list, type) output end + def english_list(value_str_prefix, values, joiner='and', oxford_comma=false) + if values.length == 1 + "#{value_str_prefix} #{values.first}" + elsif oxford_comma + "#{value_str_prefix} #{values[0..-2].join(", ")}, #{joiner} #{values[-1]}" + else + "#{value_str_prefix} #{values[0..-2].join(", ")} #{joiner} #{values[-1]}" + end + end + def check_befores(catalogue, resource) @befores.each do |ref| unless precedes?(resource, canonicalize_resource(ref)) @@ -385,6 +414,25 @@ def check_params(resource, list, type) end end end + # @param resource [Puppet::Resource] The resource in the catalog + # @param list [Array] The expected tags for the resource + # @param type [:should, :not] Whether the given tags should/not be present + def check_tags(resource, list, type) + case type + when :should + list.each do |tag| + unless resource.tags.include? tag + @errors << "#{tag} is not set" + end + end + when :not + list.each do |tag| + if resource.tags.include? tag + @errors << "#{tag} is set" + end + end + end + end end end end diff --git a/spec/fixtures/manifests/site.pp b/spec/fixtures/manifests/site.pp index 171cd1329..abb5a48ae 100644 --- a/spec/fixtures/manifests/site.pp +++ b/spec/fixtures/manifests/site.pp @@ -48,3 +48,15 @@ path => "cert ${clientcert}" } } + +node 'tags_testing' { + tag 'keyword_tag' + include sysctl::common + file { '/tmp/a': + ensure => present + } + file { '/tmp/b': + ensure => present, + tag => 'metaparam_tag' + } +} diff --git a/spec/hosts/tags_testing_spec.rb b/spec/hosts/tags_testing_spec.rb new file mode 100644 index 000000000..fcc5f40a7 --- /dev/null +++ b/spec/hosts/tags_testing_spec.rb @@ -0,0 +1,19 @@ +require 'spec_helper' + +describe 'tags_testing' do + it { should compile } + it { should contain_class('sysctl::common') + .tagged('sysctl') + .tagged('keyword_tag') + .not_tagged('no_such_tag') + } + it { should contain_file('/tmp/a') + .tagged('keyword_tag') + .not_tagged('not_even_this') + .not_tagged('metaparam_tag') + } + it { should contain_file('/tmp/b') + .with_ensure('present') + .tagged(['keyword_tag', 'metaparam_tag']) + } +end diff --git a/spec/unit/matchers/compile_spec.rb b/spec/unit/matchers/compile_spec.rb index 969d0c773..bf405b6a1 100644 --- a/spec/unit/matchers/compile_spec.rb +++ b/spec/unit/matchers/compile_spec.rb @@ -152,9 +152,9 @@ before(:each) { subject.and_raise_error(expected_error) } if Puppet::Util::Package.versioncmp(Puppet.version, '5.3.4') >= 0 - let(:error_detail) { "failure (line: 52, column: 1)" } + let(:error_detail) { "failure (line: 64, column: 1)" } else - let(:error_detail) { "failure at line 52:1" } + let(:error_detail) { "failure at line 64:1" } end if Puppet.version.to_f >= 4.0