Question regarding Puppet4 class params and Hiera5

43 views
Skip to first unread message

Sean

unread,
Sep 26, 2017, 11:00:49 AM9/26/17
to Puppet Users
Greetings,

I have read searched and read several threads in the list regarding using hiera, automatic lookup, and class params.  Some of them, I'm thinking relate to Puppet3 and prior, and I admit I'm struggling a bit with weeding through the information that's appropriate to my scenario of versions.  Please bear with me.  I am attempting to build a module that will use Hiera data layers and get away from the params.pp pattern.  The hope is that customers can use their environment hiera data if they choose, global data from an ENC, accept the default module layer data or use resource definition and supply data directly.  Unfortunately the module is complex and has many sublcasses, the init.pp looks something like:

class complex (
  Array $class_incl_list,
  Array $class_excl_list,
  Boolean $enable_feature1,
  ...more params that subclasses might use...
) {

  validate_array($class_incl_list)
  validate_array($class_excl_list)

  $local_incl_list = array_subtract($class_incl_list, $class_excl_list)

  include $local_incl_list

}

The class arrays are strings of fully qualified subclass names, e.g. [ 'complex::redhat::subclass1', 'complex::redhat::subclass2', ] etc. 

Is there a benefit to actually using class params or declaring all references to class variables directly as fully qualified in the subclasses?

Here's a simplified example subclass, and yes the example is silly, if we enable/disable a feature in puppet code, why not just exclude the subclass altogether.  Typically, that is what happens, but I was failing to find any other simplistic examples to provide.

class complex::redhat::subclass1 (
  Boolean $enable_feature1,
) {

  if $enable_feature1 {
    notify("${::osfamily} Feature 1 is enabled")
  } else {
    notify("${::osfamily} Feature 1 is disabled")
  }

}


Would I be better off removing the class param and using $::complex::enable_feature1 in the conditional?  The subclasses aren't really meant to be called by the end-user directly, so I would never expect to see someone doing a resource declaration of a subclass, but I would expect to see a user doing a resource declaration of the main class and supplying the enable_feature1 boolean with it.

Thanks for your thoughts and input.

David Schmitt

unread,
Sep 26, 2017, 12:13:42 PM9/26/17
to puppet...@googlegroups.com
On Tue, Sep 26, 2017 at 4:01 PM Sean <smal...@gmail.com> wrote:
Greetings,

I have read searched and read several threads in the list regarding using hiera, automatic lookup, and class params.  Some of them, I'm thinking relate to Puppet3 and prior, and I admit I'm struggling a bit with weeding through the information that's appropriate to my scenario of versions.  Please bear with me.  I am attempting to build a module that will use Hiera data layers and get away from the params.pp pattern.  The hope is that customers can use their environment hiera data if they choose, global data from an ENC, accept the default module layer data or use resource definition and supply data directly.  Unfortunately the module is complex and has many sublcasses, the init.pp looks something like:

class complex (
  Array $class_incl_list,
  Array $class_excl_list,
  Boolean $enable_feature1,
  ...more params that subclasses might use...
) {

  validate_array($class_incl_list)
  validate_array($class_excl_list)

Since you have already specified `Array` on the params, you can skip the `validate_array()` call here.
 

  $local_incl_list = array_subtract($class_incl_list, $class_excl_list)

  include $local_incl_list

}

The class arrays are strings of fully qualified subclass names, e.g. [ 'complex::redhat::subclass1', 'complex::redhat::subclass2', ] etc. 

Is there a benefit to actually using class params or declaring all references to class variables directly as fully qualified in the subclasses?

`include` is necessary to make the class - and its resources - available in the catalog. It has no influence over variable namespacing/scope.

If that doesn't answer your question, likely I haven't really understood what you were asking.
 
Here's a simplified example subclass, and yes the example is silly, if we enable/disable a feature in puppet code, why not just exclude the subclass altogether. 

If you need to have stuff done to *remove* a feature, this pattern is absolutely fine!

 
Typically, that is what happens, but I was failing to find any other simplistic examples to provide.

class complex::redhat::subclass1 (
  Boolean $enable_feature1,
) {

  if $enable_feature1 {
    notify("${::osfamily} Feature 1 is enabled")
  } else {
    notify("${::osfamily} Feature 1 is disabled")
  }

}


Would I be better off removing the class param and using $::complex::enable_feature1 in the conditional?

Yes.
 
  The subclasses aren't really meant to be called by the end-user directly, so I would never expect to see someone doing a resource declaration of a subclass, but I would expect to see a user doing a resource declaration of the main class and supplying the enable_feature1 boolean with it.

Thanks for your thoughts and input.


Cheers, David

--
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/f374a512-e5a1-4933-bc0e-405bbc8b44f9%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Sean

unread,
Sep 26, 2017, 1:30:35 PM9/26/17
to Puppet Users
Hi David, thanks for your reply.

I can see where I may have confused the intent of my questions with too much information.  If someone using the class were to declare something like:

class { 'complex':
  enable_feature1 => false,
  class_incl_list  => [ 'complex::redhat::subclass1', ],
}

Will subclass1 obtain the value of enable_feature1 from the above declaration?  Suppose the module default in data/common.yaml for enable_feature1 is true.

David Schmitt

unread,
Sep 27, 2017, 8:33:32 AM9/27/17
to puppet...@googlegroups.com
On Tue, Sep 26, 2017 at 6:30 PM Sean <smal...@gmail.com> wrote:
Hi David, thanks for your reply.

I can see where I may have confused the intent of my questions with too much information.  If someone using the class were to declare something like:

class { 'complex':
  enable_feature1 => false,
  class_incl_list  => [ 'complex::redhat::subclass1', ],
}

Will subclass1 obtain the value of enable_feature1 from the above declaration?  Suppose the module default in data/common.yaml for enable_feature1 is true.

There is always only one $complex::enable_feature1 value, and setting it in the class{} definition will override what's loaded from hiera.

You can get into troubles, when you do inheritance between the subclass, and the main class, and then override values at different levels. Which is why I recommend against it. Especially in the case you're outlining, adding more complexity doesn't buy you anything.

For example, this here is totally fine:

class complex::redhat::subclass1 {
    if $complex::enable_feature1 { ... }
}

and will get the expected value for enable_feature1.

To avoid any surprises I also recommend that you always run using --strict, so nobody can use the subclass standalone and then be surprised by it not working as intended.


Cheers, David

 

jcbollinger

unread,
Sep 28, 2017, 9:24:49 AM9/28/17
to Puppet Users
Dear Sean,

David has already given you great answers to the questions you posed.  I have nothing to add to those, but I feel inclined to nitpick your question a bit:

On Tuesday, September 26, 2017 at 10:00:49 AM UTC-5, Sean wrote:
[...]

The class arrays are strings of fully qualified subclass names, e.g. [ 'complex::redhat::subclass1', 'complex::redhat::subclass2', ] etc. 

Is there a benefit to actually using class params or declaring all references to class variables directly as fully qualified in the subclasses?

Here's a simplified example subclass, and yes the example is silly, if we enable/disable a feature in puppet code, why not just exclude the subclass altogether.  Typically, that is what happens, but I was failing to find any other simplistic examples to provide.

class complex::redhat::subclass1 (
  Boolean $enable_feature1,
) {

  if $enable_feature1 {
    notify("${::osfamily} Feature 1 is enabled")
  } else {
    notify("${::osfamily} Feature 1 is disabled")
  }

}




Puppet has subclasses, whose definitions can be recognized by their use of the 'inherits' keyword.  What you are describing are not them.  Even bona fide Puppet subclasses behave differently than most people tend to expect based on the uses of the term "subclass" in object-oriented programming languages, but the classes you are actually describing have nothing at all recognizable as a superclass / subclass relationship, in any accepted sense of the term.  In particular, each of the classes you described defines its own namespace, separate from and independent of all the others'.

The thrust of some of your questions suggests uncertainty about the relationship between those classes, which is an excellent reason to avoid use of the term 'subclass' for it. Even if you understood (and when you do understand) the relationship, describing it via the term 'subclass' is prone to confuse.  In fact, one class having another's name as its namespace has very little practical significance, other than putting them in the same module.  Even that is primarily organizational, not functional. I suggest just calling them "classes".


John

Sean

unread,
Sep 28, 2017, 10:32:55 AM9/28/17
to Puppet Users
John,
  I have no disagreement with your statements.  I've never done object oriented programming professionally, and only dabbled with java to learn some basics, so I guess I don't have as much bias in that regard...I really thought I was just going with the terminology flow.  The complexity of this module comes with trying to extend it's use to various platforms.  The goal is to have the end user just "include complex" and get what's broadly appropriate for that platform, while having the flexibility to exclude specific components as needed.  The module is implementing a system-wide configuration policy and touches many aspects things that would normally be done in individual modules.  This is a policy thing similar to what the SCAP Security Guide project might address.  So if other modules are in play, an end use could exclude or disable a feature in order to avoid a conflict of multiple resource declarations.

David,
  Currently, aside from using --strict, is what I am doing.  I think what made your explanations click most for me was referring to there being only one value for a parameter.  It seems a better approach to use the fully scoped names, and including class parameters only in init.pp, than attempting to include class params in the module's member classes (formerly addressed as sublcasses).

Thank you both!
Reply all
Reply to author
Forward
0 new messages