Way to pass "arguments" into a subclass?

1,014 views
Skip to first unread message

Omen Wild

unread,
Apr 28, 2016, 4:03:44 PM4/28/16
to puppet...@googlegroups.com
I am looking for a way to pass "arguments" through multiple includes into
a subclass. Situation is like this:

----- Begin code -----
node 'a-file-server.ucdavis.edu' {
include physicsnode
}

class physicsnode {
include baseclass

include ucdpuppet::kerberos
}

class ucdpuppet::kerberos {
...
include ucdpuppet::kerberos::config
...
}

class ucdpuppet::kerberos::params inherits ucdpuppet::params {
case $::osfamily {
'Debian', 'RedHat' : {
$krb5_conf_path = '/etc/krb5.conf'
$krb5_keytab_path = '/etc/krb5.keytab'
}
}
...
}

class ucdpuppet::kerberos::config inherits ucdpuppet::kerberos::params {
file {$ucdpuppet::kerberos::params::krb5_conf_path :
source => 'puppet:///modules/ucdpuppet/kerberos/krb5.conf'
}
}
----- End code -----

The problem is that a-file-server.ucdavis.edu is a special snowflake
and requires a different krb5.conf file. I could build that knowledge
into ucdpuppet::kerberos::params based on the fqdn, but burying the
info like that really bugs me. I would like some way to define that in
the node definition and be able to pull that out in ucdpuppet::kerberos::config.

Thanks,
Omen

--
Omen Wild
Systems Administrator
Metro Cluster

Rob Nelson

unread,
Apr 28, 2016, 4:15:30 PM4/28/16
to puppet...@googlegroups.com
This sounds like a great use case for an additional parameter on ucdpuppet::kerberos::config, to allow a user to pass in a source location, with a sane default, or to use an ERB template in conjunction with at least one parameter to define the contents. The parameters could be defined in hiera, so there's no special if case in your code, just various data fed in based on your hierarchy.
--
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...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/puppet-users/20160428200333.GA7428%40descolada.ucdavis.edu.
For more options, visit https://groups.google.com/d/optout.


--

jcbollinger

unread,
Apr 29, 2016, 9:27:38 AM4/29/16
to Puppet Users
This sort of thing is Hiera's bread & butter.  That would be a home run if you were already using parameterized classes and automated data binding, but Hiera does not depend on that -- you can use it directly via the hiera() function.  It might look something like this:

class ucdpuppet::kerberos::config {
  include
'ucdpuppet::kerberos::params'

 
# look up a value for $conf_path in Hiera; fall back to
 
# $ucdpuppet::kerberos::params::krb5_conf_path if Hiera
  # doesn't otherwise provide a value
  $conf_path
= hiera('ucdpuppet::kerberos::config::conf_path',
                     $ucdpuppet
::kerberos::params::krb5_conf_path)

  file
{$conf_path :
    source
=> 'puppet:///modules/ucdpuppet/kerberos/krb5.conf'
 
}
}

That does require that you set up an Hiera data store, but if it were limited to serving only what you describe, then that would comprise just two small YAML files.

Note that the code you present appears to be using class inheritance needlessly, and therefore inappropriately.  There are only two good reasons for using class inheritance in Puppet:
  1. To perform resource overrides on resources declared by the parent class (or by a more distant ancestor)
  2. To ensure that class variables of the parent class are available for use as class parameter defaults in the child class.
You do not need class inheritance for any other reason, and reason (1) is these days not much exercised, as class parameterization and automated data binding have eclipsed it as the preferred approach and the one recommended by Puppet, Inc..  My example presents the alternative: simply to include classes whose variables or resources you rely upon, but that you do not need for class parameter defaults.

Note also that there is nothing special to Hiera about the internal structure of data keys, but Puppet's automated data binding subsystem does generate keys systematically.  You're not using automated data binding, but the key I chose in my example is the one that ADB would use for $ucdpuppet::kerberos::config::conf_path if it were a class parameter instead of an ordinary class variable.  You might find that convenient if you ever decided to start using ADB in your code base.


John

Omen Wild

unread,
Apr 29, 2016, 12:51:12 PM4/29/16
to puppet...@googlegroups.com
Quoting jcbollinger <John.Bo...@stJude.org> on Fri, Apr 29 06:27:
>
> This sort of thing is Hiera's bread & butter.

Awesome, and the second recommendation for Hiera. We're already using Hiera
for other stuff (mostly defining users and groups) so this should be a
pretty small addition.

Thanks for the detailed write-up, makes the implementation look pretty
straight forward.

> That would be a home run if you were already using parameterized
> classes and automated data binding,

I have a fairly extensive programming and sysadmin background, but am
still relatively new to Puppet. I inherited a pretty big setup that
started in the 0.x Puppet era and has evolved over time. Let me see if I
can parameterized ucdpuppet::kerberos::config:

class ucdpuppet::kerberos::config ($source = $ucdpuppet::kerberos::params::krb5_source)
inherits ucdpuppet::kerberos::params {

file { $ucdpuppet::kerberos::params::krb5_conf_path: source => "puppet:///modules/ucdpuppet/kerberos/$source" }
}

Then in nodes/%{::trusted.certname}.yaml for any host that needs to
override the default in ucdpuppet::kerberos::params, I put:

ucdpuppet::kerberos::params::krb5_source: "krb5.conf.special"

> Note that the code you present appears to be using class inheritance
> needlessly, and therefore inappropriately. There are only two good reasons
> for using class inheritance in Puppet:
>
> 1. To perform resource overrides on resources declared by the parent
> class (or by a more distant ancestor)
> 2. To ensure that class variables of the parent class are available for
> use as class parameter defaults in the child class.

Like I said, inherited code base that started in the 0.x era, but given
the way I re-wrote ucdpuppet::kerberos::config above it looks like I fall
under 2).

Hmmm, looking it over it seems like I could do:

class ucdpuppet::kerberos::config {
include ucdpuppet::kerberos::params

file { $ucdpuppet::kerberos::params::krb5_conf_path: source => "puppet:///modules/ucdpuppet/kerberos/${ucdpuppet::kerberos::params::krb5_source}"}
}

Will ADB kick in for that one, or does it only apply for class parameters?

Thanks!

jcbollinger

unread,
May 2, 2016, 12:28:47 PM5/2/16
to Puppet Users


On Friday, April 29, 2016 at 11:51:12 AM UTC-5, Omen Wild wrote:
 
I have a fairly extensive programming and sysadmin background, but am
still relatively new to Puppet. I inherited a pretty big setup that
started in the 0.x Puppet era and has evolved over time. Let me see if I
can parameterized ucdpuppet::kerberos::config:

class ucdpuppet::kerberos::config ($source = $ucdpuppet::kerberos::params::krb5_source)
      inherits ucdpuppet::kerberos::params {

  file { $ucdpuppet::kerberos::params::krb5_conf_path: source => "puppet:///modules/ucdpuppet/kerberos/$source" }
}



Yes, that's the standard form for a parameterized class definition with a parameter default coming from a params class, a.k.a. the params class pattern.

 
Then in nodes/%{::trusted.certname}.yaml for any host that needs to
override the default in ucdpuppet::kerberos::params, I put:

ucdpuppet::kerberos::params::krb5_source: "krb5.conf.special"



No the key should identify the name and class of the parameter with which the value is associated, but you have given a name that matches the source of that parameter's default value.  Data binding will not change the value of the ::params class's variable; rather, it will cause Puppet to use the value drawn from Hiera instead of the value of the params-class variable.  To achieve that with your updated class definition, you want this:

ucdpuppet::kerberos::config::source: "krb5.conf.special"

 
> Note that the code you present appears to be using class inheritance
> needlessly, and therefore inappropriately.  There are only two good reasons
> for using class inheritance in Puppet:
>
>    1. To perform resource overrides on resources declared by the parent
>    class (or by a more distant ancestor)
>    2. To ensure that class variables of the parent class are available for
>    use as class parameter defaults in the child class.

Like I said, inherited code base that started in the 0.x era, but given
the way I re-wrote ucdpuppet::kerberos::config above it looks like I fall
under 2).


Yes, indeed.  As I said above, your rewrite is in the conventional form for params class pattern.  That's in fact orthogonal to automated data binding.

 

Hmmm, looking it over it seems like I could do:

class ucdpuppet::kerberos::config {
   include ucdpuppet::kerberos::params
                
   file { $ucdpuppet::kerberos::params::krb5_conf_path: source => "puppet:///modules/ucdpuppet/kerberos/${ucdpuppet::kerberos::params::krb5_source}"}
}



Yes, if you do not parameterize, then that's how I would recommend doing it.

 
Will ADB kick in for that one, or does it only apply for class parameters?



ADB applies only to class parameters, not to other class variables.  Do be mindful, however, of my comments above about which parameter of which class is the appropriate target for ADB in this case.


John

Omen Wild

unread,
May 3, 2016, 5:09:30 PM5/3/16
to puppet...@googlegroups.com
Quoting jcbollinger <John.Bo...@stJude.org> on Mon, May 02 09:28:
>
> > Then in nodes/%{::trusted.certname}.yaml for any host that needs to
> > override the default in ucdpuppet::kerberos::params, I put:
> >
> > ucdpuppet::kerberos::params::krb5_source: "krb5.conf.special"
> >
> >
>
> No the key should identify the name and class of the parameter with which
> the value is associated, but you have given a name that matches the source
> of that parameter's default value. Data binding will not change the value
> of the ::params class's variable; rather, it will cause Puppet to use the
> value drawn from Hiera *instead of* the value of the params-class
> variable. To achieve that with your updated class definition, you want
> this:
>
> ucdpuppet::kerberos::config::source: "krb5.conf.special"

Thanks again for the detailed write-up and explanation. You have saved me
many hours of hair pulling. The one quoted above would have been very
confusing, but makes perfect sense the way you explained it.
Reply all
Reply to author
Forward
0 new messages