On 06/02/2010 07:42 PM, Luke Kanies wrote:
How would something like this work as a language feature?  Something
like:

class apache2::redhat implements apache2 for(operatingsystem =>
redhat) { ... }
>
We need something that can be queried from outside, and we need
something that can essentially be automatically loaded when the base
class is evaluated.

That could work for me. Agreed on the query-ability, though I'd still like to leave in a override mechanism. Example: so you could override apache2::redhat to use a custom apache package, rather than the generic redhat one -- yet otherwise keep the other standard "apache redhat module" behaviors intact -- how sites are defined in /etc/httpd/conf.d/, etc, etc.

It seems like we almost want to build an automatically included class
heirarchy, with a class search path that the base class can define:

class apache2
loads_subclasses(operatingsystem::operatingsystem_release,
operatingsystem) { ... }

So, when someone included apache2, Puppet would automatically look for
"apache::$operatingsystem::$operatingsystem_release" then "apache::
$operatingsystem", and include them if found.

Doing it in this way would mean folks could override apache2 with a child class, then override the load_subclasses line. That'd let them include their own partial or full implementations (which couldn't be named apache2::$operatingsystem since that'd be duplicate definitions), so I guess that'd work out fine. Bit complex and intimidating looking though...

That doesn't start to approach your provider feature stuff, but I
think that's a bit outside my brain space right now. :)

It might be able to be much simpler; boiling it down, all we're really doing is writing a lot of fancy syntax to accomplish what looks a lot like a shell alias, right? Consider:

class apache {
  include apache::$os
  implements {
    "apache::featuers": provider => apache::$os::features;
    "apache::sites": provider => apache::$os::sites;
  }
}

which would essentially translate any class/define calls to apache::features into apache::$os::features. The only trick there is it'd be hard to override the "include apache::$os" -- at least until parameterized classes and you could pass in a "provider=>" to the apache class (defaulting to provider=>$operatingsystem). {post-thought: I suppose extlookup() actually would be a really good solution there until or even after param'd classes.}

This contradicts any type/providers pattern by removing the "provider knows where it belongs" pushing that up into the generic apache class. I'm not particular on where that applicability decision resides, but pushing it up keeps the DSL simpler and in many ways, clearer. Module developers specify "sane" defaults, but individual sysadmins running puppet can override them.

It'd be easy to use too -- add site-specific tweaks to a module -- so if I run RedHat but need to store things in /services for historic reasons, I can tweak the provided classes to do that with (relatively) minimal effort. I don't have to fork the apache module, nor do I have to start from scratch. Or be sick and wrong and mix and match providers, thus:

class siteapache inherits apache {
  # Use CAR instead (Custom Apache on Redhat)
  include siteapache::myca
  Implements["apache::features"] { provider=>apache::redhat::sites }
  Implements["apache::sites"] { provider=>apache::debian::sites }
  file { "/etc/httpd/conf.d/debian_style_sites.conf":
    content => "Include /etc/apache2/sites-enabled/" }
}
class siteapache::myca inherits apache::redhat {
  Package["httpd"] { name => "mycrazycustomapache" }
}


I can't tell from a brief grep around the puppet ruby code if implements{} would be easy to write or not. My offhand guess is fairly easy -- it'd basically just reach inside puppet's class listings and at the worst, subclass $name to provider=>value. (I did try 'class foo inherits foo::$operatingsystem' in the DSL itself, but the parser wasn't impressed with a variable interpolation post 'inherits'.)

One big drawback I'm seeing is this is likely order-dependent. Until apache/implements{} is evaluated, calls to apache::sites are likely to be undefined. So you may never be able to 'include apache' -- you'll have to 'require apache' instead.

--
You received this message because you are subscribed to the Google Groups "Puppet 
Developers" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/puppet-dev?hl=en.

Reply via email to