On Tuesday, June 4, 2013 1:22:08 AM UTC-5, Tom Lanyon wrote:
>
> I'm testing a 'cleanup' stage which runs after Stage[main] and removes a 
> bunch of package resources. 
>
> To do this, I tried a simple check of defined(Package[<foo>]) combined 
> with a custom facter fact (called 'app_packages'): 
>
> > class app::package::cleaner { 
> > 
> >   define check_and_remove { 
> >     if !defined(Package[$title]) { 
> >       package { $title: 
> >         ensure => absent 
> >       } 
> >     } 
> >   } 
> > 
> >   $apps = split($::app_packages, ',') 
> >   check_and_remove { $apps: } 
> > 
> > } 
> > 
> > node 'foo' { 
> >   class { 'app::package::cleaner': stage => 'cleanup' } 
>
> > } 
>
> Unfortunately, this results in a dependency cycle.  It appears that 
> putting the Package[$title] resource reference in defined() actually 
> invokes an implicit dependency between my cleanup helper resource in the 
> cleanup stage and the original Package resource in the main stage. 
>
> > Augeas[redacted] => Service[iptables] => Class[Iptables] => Stage[main] 
> => Stage[cleanup] => Class[App::Package::Cleaner] => 
> App::Package::Cleaner::Check_and_remove[package-434] => 
> Package[package-434] => Exec[app-graceful-restart] => Class[App] => 
> Stage[main] 
>
>

Does it do that when Package[package-434] is already declared elsewhere, or 
only when it is not?

 

> Is this implicit dependency expected behaviour or am I doing something 
> Bad(tm)? 
>
>

Both.

Supposing that the target package is not declared elsewhere (so that the 
!defined() condition is true) the definition will declare the package 
itself to ensure it absent, and in that case you would expect a 
relationship between the defined-type instance and the resource declared by 
it.  If elsewhere you have specific references to that package, applicable 
resource parameter defaults, or collectors that will match that package, 
then you can get relationships with it that are not evident from the 
defined type body.

On the other hand, defined() is evil.  Do not use it.  Ever.  I usually 
attribute its malignancy to the parse-order dependency it inherently 
creates -- which is indeed a serious problem -- but in this case I think 
trying to use it to approach your problem it has also obfuscated your 
manifests enough to confuse you about the scope and nature of some of your 
other declarations.

Instead of using defined(), you can apply logic farther upstream to make 
the correct declaration in the first (one) place or to apply resource 
parameter overrides to the correct resources.  Alternatively, you can 
simply determine by other means what packages need to be ensured absent, 
such as by filtering a list of possible packages against a list of packages 
that are supposed to be installed.  Some of those options may still 
susceptible to the problem you observed, however, if relevant relationships 
spring from declarations elsewhere, as I described they may do.

For the record, however, no order-of-application relationship should be 
implied by the reference itself.  Therefore, when the referenced Package is 
declared elsewhere (so that the !defined() condition is false), there 
should be a relationship between 
App::Package::Cleaner::Check_and_remove[foo] and Package[foo] only if that 
relationship is declared somewhere else.


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?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to