On Friday, September 11, 2015 at 4:31:40 PM UTC-5, Julian Meier wrote:
>
> Hi all 
>
> I’ve got three classes (example): 
>
> ``` 
> class mymodule ( 
>   $user = 'foobar', 
> ) {} 
>
> class mymodule::classone ( 
>   $foo = 'bar', 
> ) inherits ::mymodule::classone::params { 
>   require mymodule 
>   notify { "username: ${::mymodule::user}": } 
> } 
>
> class mymodule::classtwo ( 
>   $foo = 'bar', 
> ) inherits ::mymodule::classtwo::params { 
>   require mymodule 
>   notify { "username: ${::mymodule::user}": } 
> } 
>
> class mymodule::classone::params {} 
> class mymodule::classtwo::params {} 
> ``` 
>
> My idea is to have a class `mymodule` with parameters used by any other 
> class. If someone would like to change the default parameters of `mymodule` 
> he can do it like (or with hiera and autolookup): 
> ``` 
> class { ::mymodule: user => 'foo', } 
> class { ::mymodule::classone: } 
> ``` 
> And for `classtone` and `classtwo` there is a specific `params.pp` 
> (inherits)… 
>
> My problem: the declaration above can cause dependency cycles… If 
> `classone` gets used before class `mymodule`. :-( 
>
>

What you are observing is not a dependency cycle, it is an evaluation-order 
dependency.

 

> Do you have a better idea or design? 
>


Yes: never use a resource-like class declaration 
<http://docs.puppetlabs.com/puppet/4.2/reference/lang_classes.html#include-like-vs-resource-like>
 
to declare any public class of any module.

A "public class" is one that is intended to be declared from outside the 
module, which appears to include at least classes ::Mymodule and 
::Mymodule::Classone in your example.  Do not use a resource-like class 
declaration for such a class either outside its module or inside.  Instead 
use include-like declarations for such classes, and rely on automated data 
binding via Hiera to assign non-default class parameter values to them.

The particular problem in this case is that if the catalog builder 
evaluates a resource-like declaration of a given class, that declaration 
must be the very first declaration of the given class it sees.  The 'require 
mymodule' appearing in ::Mymodule::Classone and ::Mymodule::Classtwo is an 
include-like declaration of class ::Mymodule, and it is evaluated as part 
of evaluating the declaration of either of those classes.  When a 
resource-like declaration of the same class is encountered later, the 
catalog builder objects.

This constraint is basically about determining the applicable class 
parameter values: Puppet permits the same class to be declared multiple 
times, with the second and subsequent ones being no-ops.  Class parameter 
values must be determined at the first declaration.  And that's why you 
must avoid resource-like declarations of public classes -- it is very 
difficult to predict where another declaration of such a class may be 
(since it's public), or the relative order in which such a declaration may 
be evaluated.

As a secondary design consideration, it rarely makes sense to have one 
public class of a module that depends on another public class of the same 
module.  Many modules have only a single public class, and a few have 
multiple, independent public classes, but I can't name any off the top of 
my head that use the type of pattern you presented, with dependent public 
classes.  Those I can think of that have something like that provide 
defined resource types instead of dependent public classes.  Indeed, it may 
be that your Mymodule::Classone and Mymodule::Classtwo really want to be 
different instances of one defined type.  That's not going to get you 
around a class-declaration issue such as the one you presented, however.


John

-- 
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 puppet-users+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/puppet-users/3ab543f5-1b7b-412d-b942-1edf1f5d5c66%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to