Kristof Willaert
2012-Oct-22 20:21 UTC
[Puppet Users] Duplicate class declaration because of counterintuitive class scoping
Hi, I bumped into the following this afternoon (on a 2.7.19 puppet master/agent combo): consider a class profile::tomcat in module profile with the following content: $ cat modules/profile/manifests/tomcat.pp class profile::tomcat { class { ''tomcat'': } notice(''Class profile::tomcat in module profile'') } and $ cat modules/tomcat/manifests/init.pp class tomcat { notice(''Class tomcat in module tomcat'') ... } When I include this class profile::tomcat in a node definition, I would expect it to apply the resources contained in the main class of the tomcat module (in modules/tomcat/manifests/init.pp). Instead I get: $ puppet apply --modulepath modules --verbose site.pp Duplicate declaration: Class[Profile::Tomcat] is already declared; cannot redeclare at /home/bkkrw/Desktop/test/modules/profile/manifests/tomcat.pp:3 on node XXXXXX If I instead use class profile::tomcat { include tomcat notice(''Class profile::tomcat in module profile'') } then the catalog compiles successfully, but instead of applying the tomcat class from modules/tomcat/manifests/init.pp, puppet applies the profile::tomcat class: $ puppet apply --modulepath modules --verbose site.pp notice: Scope(Class[Profile::Tomcat]): Class profile::tomcat in module profile info: Applying configuration version ''1350936327'' notice: Finished catalog run in 0.04 seconds So, apparently the tomcat class included in class profile::tomcat seems to resolve to the profile::tomcat class itself instead of the class defined in modules/tomcat/manifests/init.pp. I can force the behaviour I want by using: class { ''::tomcat'':} or include ::tomcat $ puppet apply --modulepath modules --verbose site.pp notice: Scope(Class[Tomcat]): Class tomcat in module tomcat notice: Scope(Class[Profile::Tomcat]): Class profile::tomcat in module profile info: Applying configuration version ''1350936684'' notice: Finished catalog run in 0.05 seconds I haven''t come across this syntax for class declaration before, and although it seems to work, it is at least quite counterintuitive, and possibly a bug. Everything I find seems to confirm that a declaration like "include tomcat" should just apply the resources contained in the main class in module tomcat (in manifests/init.pp). What do you guys think ? Kind regards, k -- You received this message because you are subscribed to the Google Groups "Puppet Users" group. To post to this group, send email to puppet-users@googlegroups.com. To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en.
jcbollinger
2012-Oct-22 21:51 UTC
[Puppet Users] Re: Duplicate class declaration because of counterintuitive class scoping
On Monday, October 22, 2012 3:21:57 PM UTC-5, Kristof Willaert wrote:> > Hi, > > I bumped into the following this afternoon (on a 2.7.19 puppet > master/agent combo): > > consider a class profile::tomcat in module profile with the following > content: > > $ cat modules/profile/manifests/tomcat.pp > class profile::tomcat { > > class { ''tomcat'': } > notice(''Class profile::tomcat in module profile'') > } > > and > > $ cat modules/tomcat/manifests/init.pp > class tomcat { > > notice(''Class tomcat in module tomcat'') > ... > } > > When I include this class profile::tomcat in a node definition, I would > expect it to apply the resources > contained in the main class of the tomcat module (in > modules/tomcat/manifests/init.pp). > > Instead I get: > > $ puppet apply --modulepath modules --verbose site.pp > Duplicate declaration: Class[Profile::Tomcat] is already declared; cannot > redeclare at /home/bkkrw/Desktop/test/modules/profile/manifests/tomcat.pp:3 > on node XXXXXX > > If I instead use > > class profile::tomcat { > > include tomcat > notice(''Class profile::tomcat in module profile'') > } > > then the catalog compiles successfully, but instead of applying the tomcat > class from modules/tomcat/manifests/init.pp, > puppet applies the profile::tomcat class: > > $ puppet apply --modulepath modules --verbose site.pp > notice: Scope(Class[Profile::Tomcat]): Class profile::tomcat in module > profile > info: Applying configuration version ''1350936327'' > notice: Finished catalog run in 0.04 seconds > > So, apparently the tomcat class included in class profile::tomcat seems to > resolve to the profile::tomcat class itself > instead of the class defined in modules/tomcat/manifests/init.pp. > > I can force the behaviour I want by using: > > class { ''::tomcat'':} > > or > > include ::tomcat > > $ puppet apply --modulepath modules --verbose site.pp > notice: Scope(Class[Tomcat]): Class tomcat in module tomcat > notice: Scope(Class[Profile::Tomcat]): Class profile::tomcat in module > profile > info: Applying configuration version ''1350936684'' > notice: Finished catalog run in 0.05 seconds > > I haven''t come across this syntax for class declaration before, and > although it seems to work, it is at least > quite counterintuitive, and possibly a bug. > Everything I find seems to confirm that a declaration like "include > tomcat" should just apply the resources > contained in the main class in module tomcat (in manifests/init.pp). > > What do you guys think ? > >I think the behavior you discovered is a natural and expected consequence of Puppet''s name scoping and resolution rules. The current namespace is searched first for unqualified class names. Only if no matching class is found there will other namespaces be considered. The difference between the behavior with parametrized-class syntax and ''include'' for declaring the tomcat class is also normal. It turned out well in your case by alerting you to the problem, but usually it is a problem that you need to work around. It is only a bug to declare a class multiple times when the second or some later declaration is made in the parametrized style, and then only because of the possibility of inconsistent parametrization. You can ''include'' a class as many times as you want. Finally, although it is usually unnecessary to use absolute class names (e.g. "::tomcat") to declare classes, that''s because name clashes are fairly rare. Although you found Puppet''s behavior surprising, I wouldn''t call it buggy. John -- You received this message because you are subscribed to the Google Groups "Puppet Users" group. To view this discussion on the web visit https://groups.google.com/d/msg/puppet-users/-/uIGHSv7XSZ0J. To post to this group, send email to puppet-users@googlegroups.com. To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en.
Kristof Willaert
2012-Oct-22 23:01 UTC
Re: [Puppet Users] Re: Duplicate class declaration because of counterintuitive class scoping
Hi John, I think the behavior you discovered is a natural and expected consequence> of Puppet''s name scoping and resolution rules. The current namespace is > searched first for unqualified class names. Only if no matching class is > found there will other namespaces be considered. > > The difference between the behavior with parametrized-class syntax and > ''include'' for declaring the tomcat class is also normal. It turned out > well in your case by alerting you to the problem, but usually it is a > problem that you need to work around. It is only a bug to declare a class > multiple times when the second or some later declaration is made in the > parametrized style, and then only because of the possibility of > inconsistent parametrization. You can ''include'' a class as many times as > you want. >I understand the difference between the parameterized style and the include syntax. That is something that is explained thoroughly in the documentation.> Finally, although it is usually unnecessary to use absolute class names > (e.g. "::tomcat") to declare classes, that''s because name clashes are > fairly rare. Although you found Puppet''s behavior surprising, I wouldn''t > call it buggy. >What I found surprising, was the fact that the "include tomcat" or "class { ''tomcat'': }" syntax is documented everywhere as the declaration of the main class of a module, without any mention of it possibly being "overridden" by this kind of namespace clash. For variables it seems to be well documented that we should use namespacing and top-scoping to avoid these clashes. I used a similar setup to what is described by Craig Dunn (now a Puppetlabs employee) at http://www.craigdunn.org/2012/05/239/, which happens to have the exact same invocation as I did: class profile::tomcat { class { "jdk": } class { "tomcat": } } As this is a blog post, it probably wasn''t tested, but it shows there are others who find this kind of invocation intuitive. While it is easy to work around this by top-scoping the class, some form of documented warning might prevent some hairpulling :) Kind regards, k -- You received this message because you are subscribed to the Google Groups "Puppet Users" group. To post to this group, send email to puppet-users@googlegroups.com. To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en.
Kristof Willaert
2012-Dec-17 21:39 UTC
Re: [Puppet Users] Re: Duplicate class declaration because of counterintuitive class scoping
[snip] While it is easy to work around this by top-scoping the class, some form of> documented warning might prevent some hairpulling :) >Mostly for posterity, this behaviour is indeed considered buggy ("a major outstanding design issue") and is in fact documented: * http://docs.puppetlabs.com/puppet/2.7/reference/lang_namespaces.html#relative-name-lookup-and-incorrect-name-resolution * https://projects.puppetlabs.com/issues/2053 Kind regards, k -- You received this message because you are subscribed to the Google Groups "Puppet Users" group. To post to this group, send email to puppet-users@googlegroups.com. To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en.