The Puppet Labs Issue Tracker has Moved: https://tickets.puppetlabs.com

This issue tracker is now in read-only archive mode and automatic ticket export has been disabled. Redmine users will need to create a new JIRA account to file tickets using https://tickets.puppetlabs.com. See the following page for information on filing tickets with JIRA:

Bug #13349

Incorrect scope behavior: single include may load multiple classes

Added by Mark Dixon about 4 years ago. Updated over 3 years ago.

Status:ClosedStart date:03/23/2012
Priority:HighDue date:
Assignee:Jeff Weiss% Done:

0%

Category:language
Target version:3.0.0
Affected Puppet version:2.7.11 Branch:https://github.com/puppetlabs/puppet/pull/723
Keywords:

We've Moved!

Ticket tracking is now hosted in JIRA: https://tickets.puppetlabs.com


Description

I find that if I try and include manifest bar::something from within foo::test, puppet preferentially finds foo::bar::something instead of bar::something. Puppet 2.7.11.

Please consider the following puppet code which demonstrates this:

$ cat test.pp
class { 'foo::test': }

class foo::test {
   class { 'bar::something': }
}

# /.*bar::something/ manifests

# - This is the one I thought I'd get
class bar::something {
   notify { 'peep peep!': withpath => true }
}

# - This is the one that "wins"
class foo::bar::something {
   notify { 'poop poop!': withpath => true }  
}

Running it gives:

$ puppet apply test.pp
notice: /Stage[main]/Foo::Bar::Something/Notify[poop poop!]/message: poop poop!
notice: /Stage[main]/Foo::Bar::Something/Notify[poop poop!]/message: defined 'message' as 'poop poop!'
notice: Finished catalog run in 0.05 seconds

Is this a bug?

Thanks,

Mark

13349.pp (424 Bytes) Chris Price, 03/29/2012 09:39 am


Related issues

Related to Puppet - Bug #13323: Issues with variable scoping. Needs Decision 03/22/2012
Related to Puppet - Bug #2053: Relative namespacing of class/define names results in big... Accepted 03/06/2009
Duplicated by Puppet - Bug #16314: Evaluation of parameterized class deferred when class has... Duplicate 09/09/2012
Duplicated by Puppet - Bug #21432: Class declaration scope issue Duplicate

History

#1 Updated by Chris Price about 4 years ago

  • File 13349.pp added
  • Status changed from Unreviewed to Investigating

Yes, that is the expected behavior for current versions of puppet. I’ve attached a slightly updated manifest which demonstrates that if you prefer to be explicit about accessing something in the global scope, rather than starting from within the class scope, you can prefix it with a leading “::” (e.g.:

class { ‘::bar::something’: }

We may take steps to try to make the scope resolution more intuitive in the future, but this behavior does meet the current expectations.

Thanks!

#2 Updated by Chris Price about 4 years ago

  • Status changed from Investigating to Closed

#3 Updated by Mark Dixon about 4 years ago

  • Status changed from Closed to Re-opened

Hi,

Thanks for looking at this – but I notice that using ::bar::something causes something even stranger to occur! Consider:

$ cat test.pp
class { 'foo::test': }

class foo::test {
       class { '::bar::something': }
}

# /.*bar::something/ manifests

# - puppet gives me this one...
class bar::something {
       notify { 'peep peep!': withpath => true }
}

# - ... AND this one!
class foo::bar::something {
       notify { 'poop poop!': withpath => true }
}

Running this gives:

$ puppet apply test.pp 
notice: /Stage[main]/Bar::Something/Notify[peep peep!]/message: peep peep!
notice: /Stage[main]/Bar::Something/Notify[peep peep!]/message: defined 'message' as 'peep peep!'
notice: /Stage[main]/Foo::Bar::Something/Notify[poop poop!]/message: poop poop!
notice: /Stage[main]/Foo::Bar::Something/Notify[poop poop!]/message: defined 'message' as 'poop poop!'
notice: Finished catalog run in 0.04 seconds

Is it really correct behaviour for puppet to use both bar::something and foo::bar::something when you specify ::bar::something?

Thanks,

Mark

#4 Updated by Chris Price about 4 years ago

  • Category changed from modules to language
  • Status changed from Re-opened to Accepted
  • Priority changed from Normal to High
  • Target version set to 3.x

Wow, no. That is definitely a bug.

It appears to have been introduced in 2.6.3, the following commit:

commit 65ef24e5c1c33b7d42012891d368917fd6aaf68c
Date:   Fri Oct 8 15:26:28 2010 -0700

(#4534/#4778) -- Normalize parameterized classes

This is a reconciliation/melding of Paul's
    (#4534) Class inheritance with parameterized classes is no longer ignored
and Markus's
    Fix for #4778 -- evaluate parameterized classes when they are instantiated

Extracted the code from Resource::Type#mk_plain_resource that evaluates
parents and tags the catalog, and moved that into a new method called
instantiate_resource.  Instantiate_resource is now also called from
Parser::Ast::Resource#evaluate, so that the notation

    "class { classname: }"

now executes this code too.  Likewise adds class evaluation so that it behaves
the same (with regard to lazy / strict evaluation) as

    include classname

#5 Updated by Chris Price about 4 years ago

  • Subject changed from Odd search order for manifests when names partially match to Incorrect scope behavior: single include may load multiple classes

#6 Updated by Chris Price about 4 years ago

  • Status changed from Accepted to Needs Decision
  • Assignee set to Nigel Kersten

Changed the title of the ticket to more accurately reflect the bug that we narrowed it down to at the end.

This is a legitimate bug; need input on prioritization against existing Telly items.

#7 Updated by Chris Price about 4 years ago

  • Status changed from Needs Decision to Accepted
  • Assignee changed from Nigel Kersten to Chris Price

#8 Updated by Jeff Weiss about 4 years ago

  • Status changed from Accepted to Investigating
  • Assignee changed from Chris Price to Jeff Weiss

This seems to be related to the usage of class { '::bar::something': } }

This works as expected:

class { 'foo::test': }

class foo::test {
    include ::bar::something
}

class bar::something {
    notify { 'peep peep!': withpath => true }
}

class foo::bar::something {
    notify { 'poop poop!': withpath => true }
}

looking into what/where the difference is.

#9 Updated by Jeff Weiss about 4 years ago

We seem to be getting the wrong resource back from Puppet::Parser::Scope#find_hostclass. Digging into that now…

#10 Updated by Jeff Weiss about 4 years ago

The issue seems to be that the first time through Puppet::Resource::TypeCollection#resolve_namespaces strips off the leading :: that specifies that it’s top level. The next time through it’s just looking for bar::something instead of ::bar::something and finds foo::bar::something instead of the top level one.

That still doesn’t explain how it ends up with both though, only how it get the wrong one.

#11 Updated by Jeff Weiss about 4 years ago

I’ve figured out how we get both.

Puppet::Parser::AST::Resource#evaluate is add the Class[Bar::Something] resource to the compiler, and it then calls Puppet::Parser::Compiler#evaluate_classes with 'bar::something', which will then attempt to resolve it’s namespace again, resulting in Class[Foo::Bar::Something].

#12 Updated by Jeff Weiss about 4 years ago

Have fix complete. Writing spec and acceptance tests.

#13 Updated by Jeff Weiss about 4 years ago

  • Status changed from Investigating to In Topic Branch Pending Review
  • Branch set to https://github.com/puppetlabs/puppet/pull/723

#14 Updated by Anonymous about 4 years ago

  • Status changed from In Topic Branch Pending Review to Merged - Pending Release

Manually merged, fixing a couple of missed test stubs.

#15 Updated by Anonymous almost 4 years ago

  • Target version changed from 3.x to 3.0.0

#16 Updated by Matthaus Owens over 3 years ago

  • Status changed from Merged - Pending Release to Closed

Released in Puppet 3.0.0rc1

Also available in: Atom PDF