Issue #8040 has been updated by John Bollinger.

Nick Fagerlund wrote:
> A proposed solution has come up a few times in convo w/ Dan Bode, and I want 
> to make sure it's captured here:
> 
> Why not just say that resource-like declarations (`class {'myclass':}`) 
> always cause containment? This should be possible without conflicting with 
> any existing semantics.


I guess I wasn't paying attention to this issue, or maybe I overlooked the 
suggestion above, so I apologize for throwing in my own two cents so long after 
the suggestion was originally posted.

I take the suggestion to be that if a class declares another via the 
parameterized-style syntax then that implies containment of the declared class 
by the declaring one.  I disagree that that avoids conflict with existing 
semantics, because the fact that containment is NOT currently implied by 
parameterized-style class declarations must be considered part of their 
semantics.  For example, the following currently works, but would produce a 
cycle under the proposed change:

class a { }

class b {
  class { 'a': }
}

class c {
  include 'a'

  anchor { 'c_start': before  => Class['a'] }
  anchor { 'c_end':   require => Class['a'] }
}

node foo {
  include 'b'
  include 'c'
  Class['b'] -> Class['c']
}


That the change could break existing code contradicts the premise that it does 
not involve any change to existing semantics.

> 
> - Multiple non-nested containment is scary because of dependency cycles, and 
> we don't want to allow it. Fine: Resource-like declarations already only 
> allow you to declare a class once, so that's taken care of for free. 


That's a fair point, but perhaps it would be ok for Puppet to be a little less 
obstructionist.  That multiple non-nested containment is indeed scary and may 
easily contribute to dependency cycles does not mean that Puppet must actively 
prevent people from declaring it.


> - Include should continue to not cause containment, and I think that's sane.


Thank you, I think that's sane, too.


> - I've tried and tried to come up with a situation where you'd want to cause 
> a class to be contained but NOT have the class be wholly "owned" by its 
> container. I can't think of one. 


"Ownership" meaning that the owned class should not be declared by other 
classes?  You may be right -- though I'm not persuaded -- but if the proposal 
is implemented then you'll suddenly have a lot of contained classes that don't 
need to be owned, but are so simply because parameterized-style class 
declarations are popular.


> - This would also make resource-like declarations act more like normal 
> resources, which is cool.


I can see the attraction.  On the other hand, I'm not sure it's such a good 
idea to make class declarations more like ordinary resource declarations while 
not making them *exactly* like ordinary resource declarations.  It trades off 
user surprise in one area for user surprise in another, and it's not clear to 
me that there is any net gain.


> (This would almost definitely reveal currently hidden dependency cycles in 
> peoples' code. That means we should implement it in a major version with a 
> temporary pref to turn the behavior off, just so people can upgrade and start 
> fixing their breakages one at a time. Ideally, the deactivated version of the 
> behavior would log warnings when it sees things that would be cyclic.)


I guess I would put that differently: the proposal would *create* dependency 
cycles in people's code that are not there now.  Perhaps the result would be 
worth it, but I'm inclined to think not.  Indeed, I think overloading the 
desired containment declaration semantics on top of existing syntax seems 
unwise.  Whether a class needs to be contained or not is a separate concern 
from whether parameterized-style class declaration syntax can or should be 
used.  What do you intend to say to those users who want to user the 
parameterized syntax, but need non-containment semantics?  Why shouldn't they 
be able to have both?

I'm sure I suggested this on puppet-users before, but what about a new built-in 
function instead?  We already have the require() function, which does two 
thirds of the job (declares the class and establishes a relationship between 
declaring and declared classes).  Why not add a built-in contains() function in 
the same mold?  That would be a lot simpler for people to use than is the 
anchor pattern.  It would be a straight substitution where people already use 
'include' or 'require' to declare classes, but it could also be used easily 
with parameterized-style declarations, requiring only that users observe the 
restriction that the parameterized-style declaration comes before any other 
declaration of the same class (such as the contains() function would provide).  
And this wouldn't need to wait for Puppet 4.


----------------------------------------
Bug #8040: Classes should be able to contain other classes to provide a self 
contained module
https://projects.puppetlabs.com/issues/8040#change-96668

* Author: Jeff McCune
* Status: Accepted
* Priority: Immediate
* Assignee: Patrick Carlisle
* Category: compiler
* Target version: 3.x
* Affected Puppet version: 2.6.0
* Keywords: anchor containment contain graph modules module self-contained 
dependency reuse usability forge backlog customer
* Branch: 
----------------------------------------
# Overview #

As a module author, I want to build collections of classes for end users 
shipped as a module.

As a module end-user, I want to manage resources before and that require the 
collection of classes as a self contained unit of functionality.

For example, the end user wants to use a module I write in the following way:

<pre>
node default {
  class { 'java': }
  ->
  class { 'activemq': }
  ->
  class { 'mcollective: }
}
</pre>

Where java, activemq, and mcollective are all discrete modules with multiple 
classes each.  For example, a each module has a class for the packages, a class 
for the configuration files, and a class for the running service if there is a 
service.

With Puppet 2.6, when a class declares another class, the classes are not 
related to each other in any way, containment or dependency.

# Expected Behavior #

The example illustrates the expectation that all resources in the activemq 
module are managed after all resources in the java module and before all 
resources in the mcollective module.

# Actual Behavior #

Without the Anchor Pattern, when class activemq::service is declared from 
within class activemq, the resources float away and are not transitively 
related to java or mcollective.

# Suggested Implementation #

It has been expressed that it may be a viable solution for module authors to be 
able to specify containment edges in the graph from within the Puppet DSL.  
With Puppet 2.6.x and 2.7.x this is not possible.  The Anchor Pattern works 
around this problem by specifying relationship edges to a resource contained 
within the composite class.

# Work Around #

The Anchor Pattern is the current work around for Puppet 2.6.x  When a class 
declares other classes, it should contain them using this pattern:

<pre>
class activemq {

  anchor { 'activemq::begin': }
  anchor { 'activemq::end': }

  class { 'activemq::package':
    require => Anchor['activemq::begin'],
  }
  class { 'activemq::config':
    require => Class['activemq::config'],
    notify => Class['activemq::service'],
  }
  class { 'activemq::service':
    before => Anchor['activemq::end'],
  }

}
</pre>

-- 
Jeff McCune
Puppet Labs
@0xEFF



-- 
You have received this notification because you have either subscribed to it, 
or are involved in it.
To change your notification preferences, please click here: 
http://projects.puppetlabs.com/my/account

-- 
You received this message because you are subscribed to the Google Groups 
"Puppet Bugs" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to puppet-bugs+unsubscr...@googlegroups.com.
To post to this group, send email to puppet-bugs@googlegroups.com.
Visit this group at http://groups.google.com/group/puppet-bugs.
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to