Issue #8040 has been updated by John Bollinger.
Chris Price wrote:
> We've had some discussions around this lately, so I'll try to update the
> ticket for posterity:
>
> * There seems to be general consensus that we should be able to get by with
> only two types of "inclusions"; a simple one-level dependency--ala existing
> "require" function--and a "contains" dependency, which basically means
> "anything that has a dependency relationship with me also has the same
> dependency relationship with everything that I am expressing that I
> 'contain'". For the sake of conversation, we've been using the term
> "require" to discuss the first type of dependency and the term "contain" to
> describe the second type of dependency.
Are you perhaps forgetting an important class of people when you declare a
"general consensus"?
Inasmuch as I don't recall anything about this idea having been discussed on
puppet-users, and in particular inasmuch as I personally disagree, it seems a
bit of a stretch. I am prepared to eat crow if somehow I missed this, but I
don't miss much that passes through the list.
> * The current semantics of the "include" keyword (basically: dump this object
> in the catalog without any ordering or dependency information) should not be
> necessary once we have a working implementation of the "require" and
> "contain" semantics. In fact, the current semantics of "include" probably
> lead to manifests that are not explicit enough, and are prone to causing
> ordering issues that can be difficult to resolve.
I beg to differ. Perhaps it would be possible to limp along without the
functionality currently provided by "include", but those semantics are
worthwhile. Among its more common uses, "include" may express
* a logical dependency arising because the class in which it appears refers to
variables or resources declared in the included class (which does not
inherently have order-of-application implications), or
* a client-side functional dependency without order-of-application constraints
Unneeded relationships should be avoided, because each relationship requires
Puppet to consume more memory to track the relationship and to expend more
effort to choose an application order, and because unneeded relationships may
create cycles that otherwise would not exist.
I particularly object to the premise that the semantics of "include" are prone
to causing ordering issues. Ordering issues arise because manifest authors
either under- **or** over-specify resource relationships. I don't see how one
can reasonably expect that reducing authors' expressive options will reduce
ordering problems. In any case, the semantics of "include" are not responsible
for any such problem. Every ordering problem can be laid squarely at the feet
of one or more manifest authors.
Moreover, I don't see how forcing manifest authors to express unneeded
relationships is likely to make ordering issues less frequent or easier to
resolve. With repeatable ordering it may be trickier to *detect* ordering
issues arising from missing relationships, but once they are detected they are
usually fairly easy to resolve. Certainly, they are no harder to resolve with
"include" being present than if it were unavailable, and I'm inclined to think
that "include" makes resolving such issues easier. On the other hand, resource
cycles, excessive memory usage, and excessive CPU usage arising from excess
relationships are more difficult problems.
I don't have sufficient visibility to confidently judge whether manifests tend
to under-specify relationships, but I don't think it's as simple as that.
Discussion on the user list leads me to believe that it's not so uncommon for
people to over-specify relationships as well. That seems to happen when
manifest authors confuse functional dependency (resource A must be configured
for resource B *to operate properly*) with order-of-application dependency
(resource A must be configured for resource B *to be configured*). The former
does not require any special treatment by Puppet.
> * In an ideal world we might like to overlay the new semantics on top of the
> existing terminology; in other words, "include" and the "class {'foo'}"
> syntax would simply change over to the new "contains" meaning. However,
> there is obvious concern about the backward compatibility issues that this
> would cause.
Surely you're joking. What would even be desirable about changing the
well-established semantics of an existing function to something markedly
different? Notwithstanding the loss of the useful functionality that would be
replaced, how is backward compatibility not an overriding concern? The usual
practice for this sort of thing is to *deprecate* old functionality prior to
removing it, and to introduce new functionality in a way that avoids conflict
with the old. Not that I want to see "include" deprecated, but I absolutely do
not want to see it replaced by something different under the same name.
----------------------------------------
Bug #8040: Classes should be able to contain other classes to provide a self
contained module
https://projects.puppetlabs.com/issues/8040#change-68410
Author: Jeff McCune
Status: Accepted
Priority: Normal
Assignee:
Category: compiler
Target version:
Affected Puppet version: 2.6.0
Keywords: anchor containment contain graph modules module self-contained
dependency reuse usability forge
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 post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/puppet-bugs?hl=en.