On Wednesday, October 5, 2016 at 4:15:21 PM UTC+2, jcbollinger wrote:
>
>
>
> On Tuesday, October 4, 2016 at 6:55:36 AM UTC-5, Prunk Dump wrote:
>>
>> Hello puppet users !
>>
>> My problem is simple. I use the following classes in three different
>> stages (setup/main/runtime) :
>>
>> class { 'apt::client':
>> stage => 'setup',
>> }
>> ...
>> ...
>> class { 'hostpkg': }
>> ...
>> ...
>> class { 'extrapkg':
>> stage => 'runtime',
>> }
>>
>> The idea is that the "apt::client" class configure the Debian apt tools.
>> Next the "hostpkg" class install and configure the important packages (ex:
>> those needed to allow the connexion of users). And finally the "extrapkg"
>> class install the secondary packages (internet browser etc ...). But
>> sometimes the "hostpkg" or "extrapkg" packages need some extra apt sources,
>> some apt-pinning or the multiarch. So I created three resources/class :
>>
>>
>
> Do take care to distinguish between operational relationships and
> management relationships. Puppet class and resource ordering is about
> satisfying *management* relationships -- that is, situations where Puppet
> can manage resource B only after first ensuring that resource A is in its
> intended target state. Avoid declaring unnecessary relationships, for
> there is no upside at all to having such relationships, and it incurs added
> risk of problems, such dependency cycles. In particular, just because
> package B uses or interacts with package A does not necessarily imply that
> A must be managed before B, or vise versa.
>
> Especially take care with run stages, for they are nothing more than a
> convenient mechanism to apply relationships to many pairs of classes at
> once. Almost inevitably they apply a lot of unneeded relationships, but
> they may nevertheless be the best tool for a select few jobs. Indeed, the
> Puppet docs
> <https://docs.puppet.com/puppet/latest/reference/lang_run_stages.html#limitations-and-known-issues>
>
> say this:
>
> [...] *stages should only be used with the simplest of classes,* and only
>> when absolutely necessary. Mass dependencies like package repositories are
>> effectively the only valid use case.
>>
>
> I'm inclined to suppose that there may be other valid use cases at certain
> sites, and I don't think the docs are saying that stages are always the
> best solution for ensuring that package repositories are managed before all
> packages, but do take the docs' remark in the spirit in which I think it
> was intended: run stages are the wrong tool for almost every job.
>
> In your particular case, it may be that class apt::client is indeed one of
> those rare classes that make sense in a non-default stage, but class
> extrapkg seems very unlikely to be such a class. In the unlikely event
> that you need any puppet-application-ordering relationships between
> resources declared in class extrapkg and (other) classes and resources in
> stage main, I see no barrier to declaring those relationships explicitly.
> Relying on doing so instead of needlessly placing class extrapkg in a
> separate stage may solve some of your problems.
>
>
>
>> define apt::client::pinning( $package = $title, $pin, $priority, $ensure
>> = present)
>> define apt::client::source( $sourcename = $title, $type = 'deb', $uri,
>> $distribution = $apt::client::distribution, $components, $ensure = present)
>> class apt::client::multiarch
>>
>> There three resources are contained in the "apt::client" class as they
>> must be run before "apt-get update" (near "apt::client::end").
>>
>
>
> What resources? I see (definitions of) two resource *types* and one
> class. Class apt::client may declare instances of the two types; those
> *instances* are then contained by the class. It might also declare and
> even also contain (in the relationship sense) class apt::client::multiarch,
> but the declaring and containing are separate considerations. *Under no
> circumstances*, however, should the *definitions* of these types and this
> class be lexically contained within the definition of class apt::client.
> Each definition should appear in its own file.
>
>
>
>> The problem come when a package in "extrapkg" need for example the
>> multiarch :
>>
>> -> From the "extrapkg" class I include the "apt::client::multiarch" class
>> to get the multiarch activated
>>
>
>
> Ok.
>
>
>
>> -> As the "extrapkg" class is in the "runtime" stage, the
>> "apt::client::multiarch" is contained in the stage
>>
>
>
> Only if class extrapkg contains (relationship sense) class
> apt::client::multiarch, unless I've missed a change somewhere. Indeed,
> lack of the behavior you describe was once cited as a bug, and that bug
> report was rejected.
>
> If you do this ...
>
> # This should be ok:
> include "apt::client::multiarch"
>
> ... then you do not automatically put that class in the same run stage as
> the class declaring it. If, on the other hand, you ...
>
> # Don't do this with a class that may also be
> # declared by other classes in different run stages:
> contain "apt::client::multiarch"
>
> ... then you indeed do create a risk of dependency cycles such as you
> describe next. The run stages docs warn about this specifically.
>
>
>
>> -> I get a circular dependency as "apt::client::multiarch" need to be run
>> before "apt::client::end" and so after the beginning of the runtime stage
>> as it is included in the "runtime" stage.
>>
>> How I can declare, inside a stage, a resource or a class that must not be
>> contained in the stage. It is just "required" and must be run inside it's
>> corresponding stage.
>>
>
>
> A resource is always contained by the class that declares it, and will
> therefore be applied in the same stage as that class. Run stage assignment
> is not transitive, except for contained classes. Other classes' run
> stages are determined independently of the stage to which the declaring
> class, if any, is assigned.
>
> If you can rely on apt::client::multiarch to be declared independently of
> anything in class extrapkg, as it seems maybe you can do, then one
> alternative is for class extrapkg simply to ignore it. On the other hand,
> if you must permit multiple classes to declare that class, and especially
> if it self-declares containment within apt::client, which appears may be
> the case, then you should set its 'stage' metaparameter as needed via
> automated data binding.
>
>
> John
>
>
A big thank-you John ! You reply is very precise. I learn a lot of things !
In the case of apt::client::multiarch it may be a bug. Because I only
"include" the class. Not contain. And I get this dependency cycle :
Error: Could not apply complete catalog: Found 1 dependency cycle:
(Anchor[apt::client::end] => Class[Apt::Client] => Stage[setup] =>
Stage[main] => Class[Settings] => Class[Settings] => Stage[main] =>
Stage[runtime] => Class[Apt::Client::Multiarch] => Exec[add arch i386] =>
Class[Apt::Client::Update] => Exec[aptitude update] =>
Class[Apt::Client::Update] => Stage[setup])
It is true that :
Class[Apt::Client::Multiarch] => Exec[add arch i386] =>
Class[Apt::Client::Update] => Exec[aptitude update] =>
Class[Apt::Client::Update]
But there is no reason that (as it's just included) :
Stage[runtime] => Class[Apt::Client::Multiarch]
Can you help me on a more simpler and concrete example ?
1) My apt::client class have a defined type :
define apt::client::source
that allow to add sources to /etc/apt/sources.list.d. As an "apt-get
update" is needed after adding sources, all the resources defined in my
apt::client::source type :
=> require Class['apt::client::audit'] (that check if there are not pending
install)
=> notify Class['apt::client::update'] (that run apt-get update)
There as no more dependencies. And the two class ( apt::client::audit and
apt::client::update ) are contained in the apt::client class.
2) Now I want to build a "wine" class that install wine from "backports".
=> the wine class require that apt is ready to install packages so
naturally wine class need to be run after the apt::client class.
=> But wine also need that the backports sources are added to sources.list.
So in the the wine::install class manifest I declare a
apt::client::source(...backports sources...) that is required by the
Package['wine'] resource.
3) Finally I got a dependency cycle :
apt::client::update => wine::install (because apt need to be ready)
wine::install => apt::client::source(...backports sources...) (because the
resource is declared inside the wine class and required by Package['wine'])
apt::client::source(...backports sources...) => apt::client::update (as the
source need to be added before apt-get update)
You can say to me that I can create a specific
apt::client::backports_source class and include it instead of declaring it.
But I have many other modules that need many other specific sources.
You can say that I can put the apt::client::source(...backports sources...)
in the apt module. But I don't want that this sources be added on node that
don't have wine.
I there a way to achieve what I want with puppet ? Maybe with class
parameters ?
Thanks !
--
You received this message because you are subscribed to the Google Groups
"Puppet Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/puppet-users/51b827ff-a5c7-40a0-a60d-d0a321e77493%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.