diff --git a/lib/puppet/resource/type.rb b/lib/puppet/resource/type.rb index afd66f2bc2..b414377ddf 100644 --- a/lib/puppet/resource/type.rb +++ b/lib/puppet/resource/type.rb @@ -34,13 +34,13 @@ class Puppet::Resource::Type EMPTY_ARRAY = [].freeze LOOKAROUND_OPERATORS = { - "(" => 'LP', - "?" => "QU", - "<" => "LT", - ">" => "GT", - "!" => "EX", - "=" => "EQ", - ")" => 'RP' + "(" => 'lp', + "?" => "qu", + "<" => "lt", + ">" => "gt", + "!" => "ex", + "=" => "eq", + ")" => 'rp' }.freeze attr_accessor :file, :line, :doc, :code, :parent, :resource_type_collection, :override @@ -206,7 +206,7 @@ def instantiate_resource(scope, resource) def name if type == :node && name_is_regex? - # Normalize lookarround regex patthern + # Normalize lookaround regex pattern to a unique, lookup-safe lowercase string. internal_name = @name.source.downcase.gsub(/\(\?[^)]*\)/) do |str| str.gsub(/./) { |ch| LOOKAROUND_OPERATORS[ch] || ch } end diff --git a/spec/integration/parser/node_spec.rb b/spec/integration/parser/node_spec.rb index b5fa1afbd8..571e760beb 100644 --- a/spec/integration/parser/node_spec.rb +++ b/spec/integration/parser/node_spec.rb @@ -85,7 +85,7 @@ class foo { end.not_to raise_error end - it 'does not raise an error with 2 regex node names are the same due to lookarround pattern' do + it 'does not raise an error with 2 regex node names are the same due to lookaround pattern' do expect do compile_to_catalog(<<-MANIFEST, Puppet::Node.new("async")) node /(? + # e.g. db01.example.com matches, db01.hosts.example.com does not + catalog = compile_to_catalog(<<-MANIFEST, Puppet::Node.new("db01.example.com")) + node /^(db01)\.(?!hosts).*$/ { notify { matched: } } + node default { notify { unmatched: } } + MANIFEST + + expect(catalog).not_to have_resource('Notify[unmatched]') + expect(catalog).to have_resource('Notify[matched]') + end + + it 'does not match a node excluded by a negative lookahead' do + catalog = compile_to_catalog(<<-MANIFEST, Puppet::Node.new("db01.hosts.example.com")) + node /^(db01)\.(?!hosts).*$/ { notify { matched: } } + node default { notify { unmatched: } } + MANIFEST + + expect(catalog).not_to have_resource('Notify[matched]') + expect(catalog).to have_resource('Notify[unmatched]') + end + it 'provides captures from the regex in the node body' do catalog = compile_to_catalog(<<-MANIFEST, Puppet::Node.new("nodename")) node /(.*)/ { notify { "$1": } } diff --git a/spec/unit/resource/type_spec.rb b/spec/unit/resource/type_spec.rb index 7120b447ff..3f5fdc3ebc 100644 --- a/spec/unit/resource/type_spec.rb +++ b/spec/unit/resource/type_spec.rb @@ -67,6 +67,21 @@ expect(Puppet::Resource::Type.new(:node, /W/).name).to eq("__node_regexp__w") end + # Regression coverage for issue #14: lookaround syntax must be encoded into a + # lowercase synthetic name so node lookups can find the stored regex node again. + it "should normalize lookaround syntax into a lowercase synthetic name" do + expect(Puppet::Resource::Type.new(:node, /(?