On Monday, September 9, 2013 10:44:30 AM UTC-5, blalor wrote:
>
> As my previous email this morning probably indicated, I'm struggling with 
> the use of the defined( ) function.  The 
> documentation<http://docs.puppetlabs.com/references/latest/function.html#defined>
>  says 
> its operation is parse-order dependent; I'm trying to figure out how it's 
> usable at all.
>


It isn't.  Do not use it.

 

>  Since resource order with Puppet is nondeterministic (without explicitly 
> using chaining arrows or before/after),
>


'before', 'after', and chaining do not enter the picture.  They affect only 
the order in which resources are applied to the target, but what you need 
to worry about is the order in which declarations are evaluated during 
catalog compilation.

 

> how can I reliably test for the presence of a resource, like a package?
>


You should not test for the presence of a resource in the catalog.  You can 
use a custom fact to test for the presence of a resource on the target 
system, or you can design your manifest set so that you know whether a 
particular resource is supposed to be declared (even if the declaration has 
not yet been evaluated), but you should avoid testing the current state of 
the catalog.  Testing current catalog state during compilation is 
inherently evaluation-order dependent.

 

>  I see lots of instances of 
>
> if ! defined(Package['some-package']) { … }
>
>

Alas, the computing world is awash in poor code.  Its prevalence should not 
be taken as an indication of quality.

 

> in other peoples' code.  Maybe I'm not understanding what's meant by 
> "parse order", however.  Could someone explain?
>
>

"Parse order" is actually a bit of a misnomer, of which I am as guilty as 
anybody.  I'm trying to shift my personal usage to the term "evaluation 
order", though the difference is probably of little significance to most 
Puppet users.

The particular example you present seems to be a relatively common 
anti-pattern.  It attempts to address the problem that a particular class 
depends on a given package being present on the target system, but is 
uncertain whether that package is managed by another class.  It wants to 
declare the class if it is not managed by someone else, therefore it uses 
defined() to test for a declaration already present in the catalog.

That approach suffers from an insidious problem: it can subvert more 
specific, or even conflicting, declarations elsewhere in the manifest set 
without notification.  Worse, it may flip back and forth between doing so 
and not as the manifest set changes.  And that's not all.  The approach 
works reliably (in that catalog compilation succeeds) only if *all*declarations 
of the resource are guarded the same way.  If even one is not 
guarded, then whether catalog compilation succeeds or fails is 
evaluation-order dependent.

One alternative is to provide a virtual declaration of the relevant 
resource in some central class that is reliably included in the catalog, 
and have those classes that need the resource realize it (or collect it) 
instead of declaring it themselves.  Alternatively, a central class can 
provide a concrete declaration of the desired resource, and other classes 
that want the resource can 'include' the declaring class.

The main objections to any of these approaches involve modularity and 
module compatibility.  You would like to be able to use third-party modules 
without modifying them, and you would like your modules to avoid 
conflicting with each other.  Additionally, you would prefer for your 
modules to be self-contained, or at least to be insensitive to declarations 
elsewhere in your manifest set.  Unfortunately, *none* of the approaches 
above adequately address all those issues.  This is a longstanding issue in 
Puppet, and although we have discussed possible approaches, no good 
solution has made it into the product yet.


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 post to this group, send email to puppet-users@googlegroups.com.
Visit this group at http://groups.google.com/group/puppet-users.
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to