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.