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.


Reply via email to