Thanks for the great response John, you've cleared up my confusion. I guess
for now, I'll just have to live with a parse-order-dependency in my
manifest, until I can get the time to fix the modules in question. At
least I know now that it can't be solved cleanly without modifying the
actual modules. Thanks again,
Adam
On Tuesday, July 30, 2013 1:17:24 AM UTC+10, jcbollinger wrote:
>
>
>
> 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.