From cf7b3023d4a3348e37181ebe807deba97a598fcd Mon Sep 17 00:00:00 2001 From: Trevor Vaughan Date: Wed, 19 Aug 2020 17:35:57 -0400 Subject: [PATCH] [MODULES-10781] Fix defined type defined_with_params() An edge case was missed previously where calling the defined_with_params() function from inside a defined type on another instance of the same defined type would always return a match because it would match against itself. This updates the code to ignore itself and also adds a debug line output for any resource that was matched. MODULES-10781 #close --- .../parser/functions/defined_with_params.rb | 13 +++++++++--- spec/functions/defined_with_params_spec.rb | 20 +++++++++++++++++++ 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/lib/puppet/parser/functions/defined_with_params.rb b/lib/puppet/parser/functions/defined_with_params.rb index 42775849d..daac56799 100644 --- a/lib/puppet/parser/functions/defined_with_params.rb +++ b/lib/puppet/parser/functions/defined_with_params.rb @@ -54,12 +54,19 @@ [findresource(type, title)] end - resources.compact.each do |resource| + resources.compact.each do |res| + # If you call this from within a defined type, it will find itself + next if res.to_s == resource.to_s + matches = params.map do |key, value| # eql? avoids bugs caused by monkeypatching in puppet - resource_is_undef = resource[key].eql?(:undef) || resource[key].nil? + res_is_undef = res[key].eql?(:undef) || res[key].nil? value_is_undef = value.eql?(:undef) || value.nil? - (resource_is_undef && value_is_undef) || (resource[key] == value) + found_match = (res_is_undef && value_is_undef) || (res[key] == value) + + Puppet.debug("Matching resource is #{res}") if found_match + + found_match end ret = params.empty? || !matches.include?(false) diff --git a/spec/functions/defined_with_params_spec.rb b/spec/functions/defined_with_params_spec.rb index cc191a455..36a627d3a 100644 --- a/spec/functions/defined_with_params_spec.rb +++ b/spec/functions/defined_with_params_spec.rb @@ -94,6 +94,26 @@ } end + describe 'when called from within a defined type looking for a defined type of the same type' do + let :pre_condition do + <<-PRECOND + define test::deftype( + Optional $port = undef + ) { + if defined_with_params(Test::Deftype, { 'port' => $port }) { + fail('Ruh Roh Shaggy') + } + } + + test::deftype { 'foo': } + test::deftype { 'bar': port => 200 } + PRECOND + end + + # Testing to make sure that the internal logic handles this case via the pre_condition + it { is_expected.to run.with_params('NoOp[noop]', {}).and_return(false) } + end + describe 'when passed a class' do let :pre_condition do 'class test () { } class { "test": }'