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+unsubscribe@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.