inherits deprecated in puppet 4.x

1,573 views
Skip to first unread message

Jason Price

unread,
Jan 9, 2015, 2:52:39 PM1/9/15
to puppet...@googlegroups.com
This doesn't make me happy, but fine. Major versions let you have breaking changes.

My question is this: What do I replace it with?

My use case is as follows:

------------------------------------
node default {
   class{ 'ntp': }
   class{ 'dns': }
   class{ 'monitoring': }
   class{ 'puppet_agent': }
}

node 'myweb' inherits default {
   class{ 'web': }
}

node 'mydb' inherits default {
   class{ 'db': }
}
-----------------------------------

This has several very useful features:
1) Everything 'standard' is nicely encapsulated in the 'default' node. 
2) Everything in 'default' resolves and is complete before anything in 'web' or 'db' is done. This means I don't have to go crazy about 'requires' and 'notify' for these resources. They're already done.

So: What do I do instead which handles the two features?  I could easily build a new class with everything in the default node... But that fails the second piece. I'd have to build a nasty anchor pattern in every node to ensure that everything in default resolves first... which is ugly.

Thoughts?

-Jason

Dan White

unread,
Jan 9, 2015, 3:20:26 PM1/9/15
to puppet...@googlegroups.com
Clarification Request: NODE inheritance only, right ?
“Sometimes I think the surest sign that intelligent life exists elsewhere in the universe is that none of it has tried to contact us.”  (Bill Waterson: Calvin & Hobbes)
--
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/CAChvjRCug_eX3PY41WH56yrfTM08QO35UJjteMKWzpsPDgQ0HA%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.

Peter Bukowinski

unread,
Jan 9, 2015, 3:23:17 PM1/9/15
to puppet...@googlegroups.com
Here's a quick-and-dirty rejiggering that keeps the same functionality:

class default_class {
class{ 'ntp': }
class{ 'dns': }
class{ 'monitoring': }
class{ 'puppet_agent': }
}

node 'myweb' {
require default_class
class{ 'web': }
}

node 'mydb' {
require default_class
class{ 'db': }
}

Rilindo Foster

unread,
Jan 9, 2015, 4:34:41 PM1/9/15
to puppet...@googlegroups.com
It seems you are using this as a way to classify nodes. Your best option is to use  an ENC (Foreman or Hiera) to classify your nodes, ideally using the roles and profiles pattern to abstract your modules.

Jason Price

unread,
Jan 9, 2015, 8:41:05 PM1/9/15
to puppet...@googlegroups.com
This could work.  I'll play with that to see what I can do.

Thanks for the replies!
Jason

}

--
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.

jcbollinger

unread,
Jan 12, 2015, 8:55:57 AM1/12/15
to puppet...@googlegroups.com


On Friday, January 9, 2015 at 3:34:41 PM UTC-6, RIlindo Foster wrote:
It seems you are using this as a way to classify nodes. Your best option is to use  an ENC (Foreman or Hiera) to classify your nodes, ideally using the roles and profiles pattern to abstract your modules.



I strongly disagree. If you don't otherwise need (or want) an ENC, then this is not a good reason to start using one.  Changing the default node to a class and 'include'ing it, as Peter suggested, is much easier, and mostly equivalent to node inheritance.  If you use node-scoped variables in the (original) default node, however, then you have more work to do any way around.


John

Erik Dalén

unread,
Jan 21, 2015, 7:38:23 AM1/21/15
to puppet...@googlegroups.com
Note that you can also just put the standard classes (and variables) directly in the top scope. No real need to encapsulate them inside a node scope (unless you are overriding the value of facts in the manifest, but that seems like a pretty bad idea anyway).

A minor difference is also that resources that are inside a node scope will automatically get tagged with the certname of the node, but resources and classes in top scope won't. But that automatic tagging is mostly useless and a waste of space in PuppetDB IMO.




--
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.

Alessandro Franceschi

unread,
Jan 21, 2015, 12:36:25 PM1/21/15
to puppet...@googlegroups.com
Given that:
- I've used nodes inheritance with profit for years, in the past
- Now I mostly prefer a nodeless setup (with or without ENC)
let me spam the list with a fragment of my book Extending Puppet on the topic, as it contains some (controversial?) points of view I'm curious to hear opinions about (note: it was written before knowing about Puppet4 removal of nodes' inheritance, so now, I would not use it in any case) :

Node inheritance done right

Node inheritance has a bad reputation. All the Puppet books around, even the ones of a giant like James Turnbull, and the official Puppet Labs documentation describe it as a bad practice, and this puzzles me, as I had successfully used this approach for years.

The main problem, I think, has been a documentation issue, as it's not well explained to users that node inheritance makes sense when used to assign variables, but it is dangerous when used to manage class grouping.

Let's see an example of a wrong approach to node inheritance:

   node default {
     include general
   }
   node 'it' inherits default {

    $zone = 'it'
   }

   node 'web01.it.example.com' inherits 'it' {
     $role = 'web'
     include role::web

}

The issue in this extremely simplified example is that when Puppet parses general, it hasn't set the $role and $zone values, and the result for the resources declared in general, depending on them, would probably not be what was expected.

When node inheritance is used only to set and eventually override variables and not to include classes, none of these problems are present:

   node basenode {
     dns_server = '8.8.8.8'
   }
   node 'it' inherits basenode {

    $zone = 'it'
    $dns_server = '1.2.3.4'
   }

   node 'web01.it.example.com' inherits 'it' {
     $role = 'web'
     include site

  }

Now, I would not use this approach anymore, as it requires an include line for each node, and it sets variables at node scope. This implies that while they can be used in the node's classes, we cannot refer to them with a fully qualified name, and so, for example, we cannot use them on a Hiera hierarchy.

Still, in situations where an ENC and Hiera are not used and the node names are not descriptive, this is a working and effective way to identify nodes using the benefits of a hierarchical structure, based on inheritance. 

jcbollinger

unread,
Jan 22, 2015, 10:09:37 AM1/22/15
to puppet...@googlegroups.com


On Wednesday, January 21, 2015 at 11:36:25 AM UTC-6, Alessandro Franceschi wrote:
Given that:
- I've used nodes inheritance with profit for years, in the past
- Now I mostly prefer a nodeless setup (with or without ENC)
let me spam the list with a fragment of my book Extending Puppet on the topic, as it contains some (controversial?) points of view I'm curious to hear opinions about (note: it was written before knowing about Puppet4 removal of nodes' inheritance, so now, I would not use it in any case) :

Node inheritance done right

Node inheritance has a bad reputation. All the Puppet books around, even the ones of a giant like James Turnbull, and the official Puppet Labs documentation describe it as a bad practice, and this puzzles me, as I had successfully used this approach for years.


Me, too.  I'm sad to see it go, though I won't be too greatly inconvenienced.

 

The main problem, I think, has been a documentation issue, as it's not well explained to users that node inheritance makes sense when used to assign variables, but it is dangerous when used to manage class grouping.


I think the main issue is not so much documentation, but naming / keyword choice.  The actual behavior of Puppet node inheritance is reasonably well documented, and I have used it successfully for class grouping for years.  The concept of inheritance and the word "inherit[s]" don't very well fit the actual implementation of node inheritance in Puppet (<4), however.  Despite Puppet's documentation, some people make wrong assumptions about node scopes when inheritance is involved.  I think this tends to occur where their thinking is colored by experience with the OO concept of inheritance (and this is one aspect of a larger problem of Puppet adopting OO terminology for its own, slightly different, concepts).  Specifically, you get in trouble with node inheritance when you suppose that a child node can influence anything declared by its parent node, other than via explicit override.

 

Let's see an example of a wrong approach to node inheritance:

   node default {
     include general
   }
   node 'it' inherits default {

    $zone = 'it'
   }

   node 'web01.it.example.com' inherits 'it' {
     $role = 'web'
     include role::web

}

The issue in this extremely simplified example is that when Puppet parses general, it hasn't set the $role and $zone values, and the result for the resources declared in general, depending on them, would probably not be what was expected.

When node inheritance is used only to set and eventually override variables and not to include classes, none of these problems are present:

   node basenode {
     dns_server = '8.8.8.8'
   }
   node 'it' inherits basenode {

    $zone = 'it'
    $dns_server = '1.2.3.4'
   }

   node 'web01.it.example.com' inherits 'it' {
     $role = 'web'
     include site

  }


The rule there being that only leaf nodes should declare any classes, yes?  That's actually quite nice and sensible, with only one limitation I see: it is hard to extend the inheritance tree once you decide which nodes are leaves.  In practice, that limitation is probably not a big deal.

Another safe general approach to node inheritance is to altogether avoid node-scoped variables (along with avoiding resource-like class declarations in node blocks, but you should do that in any case).  With that approach you can create an insanely complex, multi-level node inheritance tree, with no worries that you will come to grief from it, even when you later modify or extend it.

 

Now, I would not use this approach anymore, as it requires an include line for each node, and it sets variables at node scope. This implies that while they can be used in the node's classes, we cannot refer to them with a fully qualified name, and so, for example, we cannot use them on a Hiera hierarchy.

Still, in situations where an ENC and Hiera are not used and the node names are not descriptive, this is a working and effective way to identify nodes using the benefits of a hierarchical structure, based on inheritance. 




As you might guess from my approach to the issue, I've never been much of a fan of node-scoped variables in the first place.  I particularly don't care for them as a means to feed data to classes.  Although that provides for very safe use of node inheritance, it also means that I can adapt very easily to not having node inheritance.


John

jcbollinger

unread,
Jan 22, 2015, 10:13:55 AM1/22/15
to puppet...@googlegroups.com


On Thursday, January 22, 2015 at 9:09:37 AM UTC-6, jcbollinger wrote:
 
[...]  With that approach you can create an insanely complex, multi-level node inheritance tree [...].


Clarification: though you safely can do that, you shouldn't.


John

Alessandro Franceschi

unread,
Jan 22, 2015, 5:33:47 PM1/22/15
to puppet...@googlegroups.com


On Thursday, January 22, 2015 at 4:09:37 PM UTC+1, jcbollinger wrote:


On Wednesday, January 21, 2015 at 11:36:25 AM UTC-6, Alessandro Franceschi wrote:
Given that:
- I've used nodes inheritance with profit for years, in the past
- Now I mostly prefer a nodeless setup (with or without ENC)
let me spam the list with a fragment of my book Extending Puppet on the topic, as it contains some (controversial?) points of view I'm curious to hear opinions about (note: it was written before knowing about Puppet4 removal of nodes' inheritance, so now, I would not use it in any case) :

Node inheritance done right

Node inheritance has a bad reputation. All the Puppet books around, even the ones of a giant like James Turnbull, and the official Puppet Labs documentation describe it as a bad practice, and this puzzles me, as I had successfully used this approach for years.


Me, too.  I'm sad to see it go, though I won't be too greatly inconvenienced.

 

The main problem, I think, has been a documentation issue, as it's not well explained to users that node inheritance makes sense when used to assign variables, but it is dangerous when used to manage class grouping.


I think the main issue is not so much documentation, but naming / keyword choice.  The actual behavior of Puppet node inheritance is reasonably well documented, and I have used it successfully for class grouping for years.  The concept of inheritance and the word "inherit[s]" don't very well fit the actual implementation of node inheritance in Puppet (<4), however.  Despite Puppet's documentation, some people make wrong assumptions about node scopes when inheritance is involved.  I think this tends to occur where their thinking is colored by experience with the OO concept of inheritance (and this is one aspect of a larger problem of Puppet adopting OO terminology for its own, slightly different, concepts).  Specifically, you get in trouble with node inheritance when you suppose that a child node can influence anything declared by its parent node, other than via explicit override.

Very good points.
I suppose we all agree, Luke included, that OO naming for non OO concepts has generated a lot of confusion.
Also, I'd say, that documentation, which is now great, was much less clear in the past (remember the wiki?) and different patterns were tested and explored.
Many have suffered with nodes inheritance and dynamic variables scoping in the past, and I suppose this is the reason of their progressive removal.
 

 

Let's see an example of a wrong approach to node inheritance:

   node default {
     include general
   }
   node 'it' inherits default {

    $zone = 'it'
   }

   node 'web01.it.example.com' inherits 'it' {
     $role = 'web'
     include role::web

}

The issue in this extremely simplified example is that when Puppet parses general, it hasn't set the $role and $zone values, and the result for the resources declared in general, depending on them, would probably not be what was expected.

When node inheritance is used only to set and eventually override variables and not to include classes, none of these problems are present:

   node basenode {
     dns_server = '8.8.8.8'
   }
   node 'it' inherits basenode {

    $zone = 'it'
    $dns_server = '1.2.3.4'
   }

   node 'web01.it.example.com' inherits 'it' {
     $role = 'web'
     include site

  }


The rule there being that only leaf nodes should declare any classes, yes?  That's actually quite nice and sensible, with only one limitation I see: it is hard to extend the inheritance tree once you decide which nodes are leaves.  In practice, that limitation is probably not a big deal.

Well, the leaves are always the single hosts, so if you need to introduce new layers in the inherited nodes, you still can (it's like adding a hierarchy in Hiera) 

Another safe general approach to node inheritance is to altogether avoid node-scoped variables (along with avoiding resource-like class declarations in node blocks, but you should do that in any case).  With that approach you can create an insanely complex, multi-level node inheritance tree, with no worries that you will come to grief from it, even when you later modify or extend it.

 

Now, I would not use this approach anymore, as it requires an include line for each node, and it sets variables at node scope. This implies that while they can be used in the node's classes, we cannot refer to them with a fully qualified name, and so, for example, we cannot use them on a Hiera hierarchy.

Still, in situations where an ENC and Hiera are not used and the node names are not descriptive, this is a working and effective way to identify nodes using the benefits of a hierarchical structure, based on inheritance. 




As you might guess from my approach to the issue, I've never been much of a fan of node-scoped variables in the first place.  I particularly don't care for them as a means to feed data to classes.  Although that provides for very safe use of node inheritance, it also means that I can adapt very easily to not having node inheritance.

Indeed. Honestly I won't miss nodes inheritance too, not anymore.
In fact I don't see any advantage to other, more concise and effective, ways to assign variables and classes to nodes.

Given this, and back to the topic of this thread, then, Jason, I would do something like:

node 'myweb'  {
   include site
   class{ 'web': }
}

node 'mydb'  {
   include site
   class{ 'db': }
}

and in the site class (and/or its subclasses manage the general baseline common to all your systems):
class { 'site':

   class{ 'ntp': }
   class{ 'dns': }
   class{ 'monitoring': }
   class{ 'puppet_agent': }
}

Alternatively, and even better, if you have a way to set a $role  variable (either as custom or external fact, or via an ENC, or extracting its value using Puppet DSL from the certname of the clients directly in site.pp (so setting $role at top scope), you can have a "nodeless setup" and a site.pp as simple as

include site
# Call is site, call with with your compay/project name or whatever 

and the in $MODULEPATH/site/manifests/init.pp have your site class with common resources and optional addition of role specific ones):

class { 'site':

   class{ 'ntp': }
   class{ 'dns': }
   class{ 'monitoring': }
   class{ 'puppet_agent': }

  if $::role and $::role != '' {  # On Puppet <4 is enough if $::role 
    include "::site::roles::${::role}"
  }

}


Then for each role, have a class like:
class site::roles::db {
 # Resources or classes for this role
}
 
Hope it helped,
my2c

PS: Thanks for your time and your answers John, always appreciated
Reply all
Reply to author
Forward
0 new messages