On Wednesday, June 18, 2014 4:22:16 AM UTC-5, Trevor Vaughan wrote: > > Hi Felix, > > Yes, I'm very aware that the current recommendations are to very cleanly > model your system to be able to non-ambiguously define your catalog. > > However, there have always been arguments that the Puppet language should > be declarative throughout which makes for more maintainable and intuitive > manifests overall. > > If you go look for posts surrounding this subject, I'd say that the > consensus is because reflection just doesn't work, not because it shouldn't > be there. > >
To the extent that I get to say what the consensus is -- and I have been outspoken enough on the topic to suppose I have helped shape that consensus -- I'd say it's that most anything dependent on evaluation order does not work reliably, and reflection shouldn't be there because it cannot be relieved of evaluation-order dependencies. (Sorry, Henrik, if I'm getting my different orders mixed up.) To put it another way, I'd say reflection *can't* work. If, however, some constrained context could be established in which to perform reflection, then perhaps some form of reflection could be introduced. For example, it might be possible to inspect which classes are in the catalog from a construct wherein, or at a time when, no further classes can be added. Adding bona fide resources would be allowed (else what would be the point?), but they would need to actively be prevented from adding classes. > Frankly, it can solve a LOT of problems for you and make the system > designer's life a lot easier. > > It does not solve *any* problems if it doesn't work reliably, and general reflection cannot work reliably. > Scenario 1: A requires B if C but not otherwise. > > If I don't have reflection in this case, then I have to have documentation > that says, hey, if you put A and C together on a system, remember to add B! > This is prone to error and is something that the code should just "take > care of" for me. I'm aware that you could use a role/profile model to take > care of this but you're just making people write extra code for no really > good reason except that the language doesn't actually address this issue. > (I'll rant about the irritation of figuring out what code is doing in a > role/profile system later). > > Scenario 2: A requires B if module B is present but do something else > otherwise. > > This one is more about system introspection I suppose but we have all of > these lovely Module Forge description files and we can't use them in the > language! I would love to be able to do the following: > > if $::module_mysql <= '1.2' { include 'mysql' } else { service { 'mysql': > ensure => running, enable => true } } > > You can then also use $::module_mysql to set up automatic Hiera > hierarchies that run from version down to a default (hieradata/mysql/1.0, > hieradata/mysql/0.9, hieradata/mysql/default) and life is magic and > wonderful when modules on the forge change. > > Scenario 1 is obviously what we're referring to in this thread and I > think, with the way most cloud component architectures seem to be designed, > the burden is being placed on the system user as opposed to the system > designer in too many cases. And, frankly, some times you just need to get > something working and you hit a point where you realize that you'd have to > redesign the system to avoid using reflection and you just don't have time > for that or it is going to add a LOT of unnecessary code. > > Puppet already has a tool for separating the details of a resource from the decision about whether to include it in the catalog: virtual resources. Those decisions can be tied to whether a given class is declared by having that class realize or (especially) collect the resources. In many cases that can be done via a wrapper class or definition if the target class itself must not be modified. Here's an idea: Collectors are already processed very late, so maybe they are late enough -- or could be *made* late enough -- to provide the kind of context needed for safe reflection. One might then write something along these lines: Firewall::Rule<| title == 'whatever' and defined == 'firewall' |> @firewall::rule { "whatever": # ... } Of course, the collector wouldn't need actually to be close to the resource declaration, and it might be more general than just one resource, but it could be right there with the resource declaration to provide something much like an if defined() effect. For that to be safe though, it would be necessary to prevent the collected resources from adding classes to the catalog, probably by failing the catalog if any of them try to do so. That restriction might be reserved for when the 'defined' key is used in the collector's select expression, provided that such collectors were processed after all others. John -- You received this message because you are subscribed to the Google Groups "Puppet Developers" group. To unsubscribe from this group and stop receiving emails from it, send an email to puppet-dev+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/puppet-dev/5affcbe8-4a14-4e7f-95da-1e598f10fd5f%40googlegroups.com. For more options, visit https://groups.google.com/d/optout.