On Wednesday, June 12, 2013 9:15:22 AM UTC-5, Tom Lanyon wrote: > > On 05/06/2013, at 11:51 PM, jcbollinger [...] wrote: > > I don't much like that general approach in the first place on account of > the $requested_package parameter. That you encounter difficulty when you > try something a bit dodgy should not be surprising. > > Can you explain this further so I can understand the issue? > >
Initially, it was mostly a gut feeling. After having had time to step back from the issue and return to it fresh, I think it's a combination of things, mostly revolving around what you're actually modeling, and how you're modeling it. Basically, the 'myapp' definition represents one package chosen from a list of mutually exclusive packages. If that's all it is, then its name is misleading -- it should be more generic -- and it should probably take the exclusive list as a second parameter. On the other hand, if it is indeed supposed to be something specific, then it doesn't take much advantage of that. In particular -- and here's where my previous comment came from -- if it supposed to represent something specific to your application, then why doesn't it know anything about the application's package names? Also, if the point is supposed to be that only one version of the application can be installed at a time, and the definition is specific to that application, then it really ought to be a class instead. > > In fact, despite my dissatisfaction with your approach, you can indeed > do this without defined(), and without even disrupting your current > structure very much. Here's one way I think would work: > > > > # This class ensures all known app packages are > > # by default purged > > class app::packages { > > $apps = split($::app_packages, ',') > > package { $apps: > > ensure => 'purged' > > } > > } > > > > # Overrides the requested package to be declared > > # present instead of purged. > > define app::myapp($requested_package) { > > include 'app::packages' > > Package<| title == $requested_package |> { > > ensure => 'present' > > } > > } > > > > # no separate package_cleanup required > > > OK, I wondered whether we could do something like this however - forgive > my naivety - I still can't see how this could be a complete solution > without something like defined(). > > As an example... your above snippet works fine to ensure already installed > packages remain installed, but what if we wanted to install a brand new > version of app::myapp? Because a 'package' resource with title > $requested_package does not yet exist, the Package<||> collector matches no > resources and the new package is not installed. The only solution that I > can come up with is to check whether such a resource is already defined > and, if not, define one. > > You appear to have a serious misunderstanding. Resource collectors have no direct relationship with or dependency on which resources are already installed on the target system. They work exclusively with resource * declarations* in your manifests, and they do so at catalog compilation time. Moreover, they are independent of parse order (though the example anyway ensures a parse order that would work if collectors were parse-order dependent). Explanation of the example: - class app::packages declares all of the possible application packages, specifying the intended state for each one as 'purged'. If that is the only thing applied to the target node then it will cause the removal of each and every one of those packages that is installed. ('purged' is stronger than 'absent'. The former is more sure to remove the specified package, but the latter takes care to avoid causing any other packages to be removed, and therefore fails if any other package depends on the target package.) It is necessary that the list of possible packages include every one that you may want to have installed, so it needs to be updated whenever you introduce a new one that you want to manage. That was already a requirement for you, however, whether you recognized it or not. - Resources of defined type app::myapp ensure that class app::packages is declared on the target node (by declaring it itself) - Resources of defined type app::myapp override the declaration of the target package (made by class app::packages) so that its target state is 'present' instead of 'purged'. This will cause it to be installed if it is not already present, and will avoid removing it if it is present. - To use the example, simply declare one or more instances of app::myapp for the target node, either in a node block or in some class assigned to the node. You may also declare class app::packages directly for any node, whether or not they declare any app::myapp instances. That is useful if you have nodes on which you want to ensure that no version of the application is installed. 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.