On Monday, July 22, 2013 1:29:43 AM UTC-5, Adam C wrote:
>
> Thanks for the response Paul, I took a look at ensure_packages and it
> seems useful, but it of course has the same drawback as using defined, in
> that it'll only work if all modules use it.
>
> I've reduced my problem to the following. I created two modules, module1
> and module2 as follows:
>
> *modules/**module1/manifests/init.pp*:
>
> define module1::before { package { 'mod_ssl': ensure => present } }
>
> *modules/**module2/manifests/init.pp*:
>
> define module2::after { if ! defined(Package['mod_ssl']) { package {
> 'mod_ssl': ensure => present } } }
>
> and in my main manifest, I have the following which works:
>
> module1::before {'test': }
> module2::after {'test': }
>
> but if I change around the order, I receive an error:
>
> module2::after {'test': }
> module1::before {'test': }
>
> Error: Duplicate declaration: Package[mod_ssl] is already declared in file
> /tmp/vagrant-puppet/modules-0/mod2/manifests/init.pp at line 7; cannot
> redeclare on node vagrant
>
> of course this happens because module 2 performs a check to only require
> the mod_ssl package if it isn't defined, but module 1 has no such check, so
> if module 1 is included after module 2, it ends up duplicating the mod_ssl
> resource.
>
> I've tried resolving this by using the *require* directive, but it
> doesn't seem to work:
>
> module2::after {'test': require => Module1::Before['test'] }
> module1::before {'test': }
>
> Can anyone tell me how I can fix this, and have the code in module1
> included before module2, regardless of the order they appear in the file?
> I thought that's what the *require *directive would enforce, but I must
> be using it incorrectly, since it doesn't seem to work for me in this
> instance. if I can solve this small issue, I can fix my larger problem
> without needing to modify the code in either module, which is what I'd
> prefer. Thanks for any help
>
>
There is no solution to the problem as you have framed it. Resource
declarations, including for resources of defined types, are parsed in the
order in which they are encountered in Puppet's linear traversal of the
manifest file in which they appear. Similarly, classes are 'include'd in
the order they appear in the file, modulo a few caveats related to classes
that are declared in multiple files or via an ENC. The 'require'
metaparameter and its compatriots affect the relative order in which those
resources and classes are applied to the client, which is an entirely
separate question.
If you want one resource module1::before to be parsed before resource
module2::after when they are both declared by the same class, then the
declaration of the former must precede the declaration of the latter.
Inasmuch as that is easy to accomplish, it it not the usual problem in this
area. Instead, the problem is usually about controlling the relative order
in which declarations appearing in different classes are parsed, which
ultimately comes down to controlling the order in which classes are parsed.
A requirement of that kind is often described as a "parse-order
dependency", and it constitutes a serious problem in your manifests. You
will find a lot of discussion of parse-order issues in the archives of this
group. The best solution would be to solve the dependency, and the best
way to do that is to factor the duplicate resource declaration out into a
separate class, which each dependent then declares via an 'include'
statement. The class may be broader than just one resource, as seems
appropriate to you. Example:
class ssl {
package { 'mod_ssl': ensure => present }
}
define module1::foo {
include 'ssl'
# other stuff ...
}
define module2::bar {
include 'ssl'
# other stuff ...
}
This solves the problem because classes are singletons, so declaring the
same class multiple times is safe and idempotent(*).
(*) There is a caveat, however. Binding data or metaparameters to a class
via a parameterized-style class declaration (e.g. class { 'ssl': stage =>
'main' }, or even class { 'httpd': }) is *not* idempotent. Such a
declaration of a given class must be the first declaration of that class
parsed, thus making it another parse-order dependency. In Puppet 3 you can
use hiera data bindings to avoid that issue. You can also use direct hiera
calls in the class body instead of class parameters.
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 [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/puppet-users.
For more options, visit https://groups.google.com/groups/opt_out.