class inheritance question

49 views
Skip to first unread message

jimbob palmer

unread,
Feb 7, 2012, 6:52:23 AM2/7/12
to puppet...@googlegroups.com
If I have a class

class something {}

and a subclass

class something::blah ($var=0) inherits something {
    class { 'something::aaa': somevar => 1, }
    class { 'something::bbb': somevar => 2, }
}

should the classes called from the subclass inherit the parent class? e.g. which is good practice?

class something::bbb($somevar) inherits something {}
or:
class something::bbb($somevar) {}

Also, what is the best way to set $somevar in something::bbb from a node definition?

Thanks.

R.I.Pienaar

unread,
Feb 7, 2012, 6:59:05 AM2/7/12
to puppet...@googlegroups.com

Felix Frank

unread,
Feb 7, 2012, 7:21:27 AM2/7/12
to puppet...@googlegroups.com
Hi,

sorry for jumping to conclusions, but your questions suggest that you're
committed to some rather horribly design ideas.

Can you add some meat to your inquiry? What are your trying to achieve?

Under most circumstances, you don't want inheritance at all.
Use it *only* to override the parameters of one or more resources in the
base class.

HTH,
Felix

jimbob palmer

unread,
Feb 7, 2012, 7:56:29 AM2/7/12
to Puppet Users
On Feb 7, 1:21 pm, Felix Frank <felix.fr...@alumni.tu-berlin.de>
wrote:
> Hi,
>
> sorry for jumping to conclusions, but your questions suggest that you're
> committed to some rather horribly design ideas.

Then please educate me! What's horrible about it?

>
> Can you add some meat to your inquiry? What are your trying to achieve?

I have a class which represents a group of yum repositories
(something::blah) and that class calls each repository
(something::aaa)

> Under most circumstances, you don't want inheritance at all.
> Use it *only* to override the parameters of one or more resources in the
> base class.

What I have done wrong would be much appreciated. Thanks.

Felix Frank

unread,
Feb 7, 2012, 8:33:35 AM2/7/12
to puppet...@googlegroups.com
Hi,

On 02/07/2012 01:56 PM, jimbob palmer wrote:
>> sorry for jumping to conclusions, but your questions suggest that you're
>> > committed to some rather horribly design ideas.
> Then please educate me! What's horrible about it?

There are few use cases for parameterized classes, and also few for
inheritance. Combining them could be considered an advanced concept.
There is nothing here that suggests you need either technique.

No offense, I just want to keep people (you) from shooting yourselves in
the feet.

>> >
>> > Can you add some meat to your inquiry? What are your trying to achieve?
> I have a class which represents a group of yum repositories
> (something::blah) and that class calls each repository
> (something::aaa)
>

You probably want to create a custom type like

define my_yum_repo($url) {
yum_repo { $name: ...
}

Then you can use it like this:

class something {
my_yum_repo {
"internal_repo1": url => "http://...";
"internal_repo2": ... ;
}
}

Sorry if doesn't hit the spot, your problem description is still rather
abstract.

HTH,
Felix

jcbollinger

unread,
Feb 7, 2012, 9:33:40 AM2/7/12
to Puppet Users


On Feb 7, 7:33 am, Felix Frank <felix.fr...@alumni.tu-berlin.de>
wrote:
> Hi,
>
> On 02/07/2012 01:56 PM, jimbob palmer wrote:
>
> >> sorry for jumping to conclusions, but your questions suggest that you're
> >> > committed to some rather horribly design ideas.
> > Then please educate me! What's horrible about it?
>
> There are few use cases for parameterized classes, and also few for
> inheritance. Combining them could be considered an advanced concept.
> There is nothing here that suggests you need either technique.


+1


> >> > Can you add some meat to your inquiry? What are your trying to achieve?
> > I have a class which represents a group of yum repositories
> > (something::blah) and that class calls each repository
> > (something::aaa)
>
> You probably want to create a custom type like
>
> define my_yum_repo($url) {
>   yum_repo { $name: ...
>
> }
>
> Then you can use it like this:
>
> class something {
>   my_yum_repo {
>     "internal_repo1": url => "http://...";
>     "internal_repo2": ... ;
>   }
>
> }


I have a class much like that in my own configuration, in fact.


Addressing the question more generally, do not use class inheritance
where what you really want is composition. That is, given

class foo::common {
# common stuff
}

use this:


# The right way
class foo::specific {
include 'foo::common'
# specific stuff
}


instead of this:

# DONT DO THIS
class foo::specific inherits 'foo::common' {
}


And definitely do not use inheritance to try to indicate ownership or
some similar concept -- that's alien to Puppet. Puppet has namespaces
and scopes, but no native concept of class or resource ownership, and
all declarations are globally visible once they are parsed.


John

jimbob palmer

unread,
Feb 7, 2012, 9:54:25 AM2/7/12
to puppet...@googlegroups.com
2012/2/7 jcbollinger <John.Bo...@stjude.org>:

So can I be sure that the include will run first, before the "specific
stuff" here?

>
>
> instead of this:
>
> # DONT DO THIS
> class foo::specific inherits 'foo::common' {
> }

Okay. So if I am not meant to use class inheritance for this, when
should I use it?

Is scoping different between include and inherits?

Jan Ivar Beddari

unread,
Feb 7, 2012, 2:50:45 PM2/7/12
to puppet...@googlegroups.com
On 02/07/2012 03:54 PM, jimbob palmer wrote:
>>
>> # The right way
>> class foo::specific {
>> include 'foo::common'
>> # specific stuff
>> }
>
> So can I be sure that the include will run first, before the "specific
> stuff" here?

Kind of, but you need to change your thinking. The include does not
_run_ before the specific stuff, it _declares_ foo::common. The result
is not a sequential run of something, but a graph - a catalog of
resources and relationships :)

> Okay. So if I am not meant to use class inheritance for this, when
> should I use it?

Hm, I'm tempted to say "never" but this is an example use

http://docs.puppetlabs.com/guides/parameterized_classes.html#appendix-smart-parameter-defaults


--
http://www.uib.no/personer/Jan.Ivar.Beddari

jimbob palmer

unread,
Feb 7, 2012, 4:13:18 PM2/7/12
to puppet...@googlegroups.com
2012/2/7 Jan Ivar Beddari <jan.ivar...@uib.no>:

> On 02/07/2012 03:54 PM, jimbob palmer wrote:
>>>
>>>
>>> # The right way
>>> class foo::specific {
>>>    include 'foo::common'
>>>    # specific stuff
>>> }
>>
>>
>> So can I be sure that the include will run first, before the "specific
>> stuff" here?
>
>
> Kind of, but you need to change your thinking. The include does not _run_
> before the specific stuff, it _declares_ foo::common. The result is not a
> sequential run of something, but a graph - a catalog of resources and
> relationships :)

Yikes so how can I be sure that the included stuff gets included
before I need it? Say it pulls in some variables and package
requirements.

And a related question: if I have a case statement at the top of my
class that sets a variable, how can I be sure the variable will be set
before I need it lower down in the same class?

>
>
>> Okay. So if I am not meant to use class inheritance for this, when
>> should I use it?
>
>
> Hm, I'm tempted to say "never" but this is an example use
>
> http://docs.puppetlabs.com/guides/parameterized_classes.html#appendix-smart-parameter-defaults
>
>
> --
> http://www.uib.no/personer/Jan.Ivar.Beddari
>
>

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

Nan Liu

unread,
Feb 7, 2012, 4:29:15 PM2/7/12
to puppet...@googlegroups.com
On Tue, Feb 7, 2012 at 1:13 PM, jimbob palmer <jimbob...@gmail.com> wrote:
> 2012/2/7 Jan Ivar Beddari <jan.ivar...@uib.no>:
>> On 02/07/2012 03:54 PM, jimbob palmer wrote:
>>>>
>>>>
>>>> # The right way
>>>> class foo::specific {
>>>>    include 'foo::common'
>>>>    # specific stuff
>>>> }
>>>
>>>
>>> So can I be sure that the include will run first, before the "specific
>>> stuff" here?

Yes, you just have to be explicit and specify relationship.

> Yikes so how can I be sure that the included stuff gets included
> before I need it? Say it pulls in some variables and package
> requirements.

The variables are evaluated during compilation so include the class
before you reference any variables. If you need resource in
foo::package applied before foo::specific:

require 'foo::package'

or 2.7 parametrized class:

class { 'foo::package':
version => 'latest',
}

Class['foo::package'] -> Class['foo::specific']

> And a related question: if I have a case statement at the top of my
> class that sets a variable, how can I be sure the variable will be set
> before I need it lower down in the same class?

If you mean there's a variable in foo::common you want to reference in
foo::specific just use fully qualified variable and include
foo::common.

include foo::common

if $::foo::common:variable {
...
}

HTH,

Nan

Craig White

unread,
Feb 7, 2012, 4:30:49 PM2/7/12
to puppet...@googlegroups.com

On Feb 7, 2012, at 2:13 PM, jimbob palmer wrote:

> 2012/2/7 Jan Ivar Beddari <jan.ivar...@uib.no>:
>> On 02/07/2012 03:54 PM, jimbob palmer wrote:
>>>>
>>>>
>>>> # The right way
>>>> class foo::specific {
>>>> include 'foo::common'
>>>> # specific stuff
>>>> }
>>>
>>>
>>> So can I be sure that the include will run first, before the "specific
>>> stuff" here?
>>
>>
>> Kind of, but you need to change your thinking. The include does not _run_
>> before the specific stuff, it _declares_ foo::common. The result is not a
>> sequential run of something, but a graph - a catalog of resources and
>> relationships :)
>
> Yikes so how can I be sure that the included stuff gets included
> before I need it? Say it pulls in some variables and package
> requirements.

----
require [ Class["some_class"], Package["some_package"] ]
----


> And a related question: if I have a case statement at the top of my
> class that sets a variable, how can I be sure the variable will be set
> before I need it lower down in the same class?

----
leap of faith

Craig

jimbob palmer

unread,
Feb 8, 2012, 1:43:25 AM2/8/12
to puppet...@googlegroups.com
2012/2/7 Nan Liu <n...@puppetlabs.com>:

> On Tue, Feb 7, 2012 at 1:13 PM, jimbob palmer <jimbob...@gmail.com> wrote:
>> 2012/2/7 Jan Ivar Beddari <jan.ivar...@uib.no>:
>>> On 02/07/2012 03:54 PM, jimbob palmer wrote:
>>>>>
>>>>>
>>>>> # The right way
>>>>> class foo::specific {
>>>>>    include 'foo::common'
>>>>>    # specific stuff
>>>>> }
>>>>
>>>>
>>>> So can I be sure that the include will run first, before the "specific
>>>> stuff" here?
>
> Yes, you just have to be explicit and specify relationship.
>
>> Yikes so how can I be sure that the included stuff gets included
>> before I need it? Say it pulls in some variables and package
>> requirements.
>
> The variables are evaluated during compilation so include the class
> before you reference any variables. If you need resource in
> foo::package applied before foo::specific:
>
> require 'foo::package'
>
> or 2.7 parametrized class:
>
> class { 'foo::package':
>  version => 'latest',
> }
>
> Class['foo::package'] -> Class['foo::specific']
>

Thanks. but I meant more within the same class: before I was using
class inheritance to ensure that I don't have to worry about ordering.

Now I will use includes as you suggest. Say I have a class that has an
include, is there a guarantee that the include will always be included
before the rest of the class is examined?

>> And a related question: if I have a case statement at the top of my
>> class that sets a variable, how can I be sure the variable will be set
>> before I need it lower down in the same class?
>
> If you mean there's a variable in foo::common you want to reference in
> foo::specific just use fully qualified variable and include
> foo::common.

I mean withint the same class. Say I have a case statement at the top
of my class that sets a variable, will that run before I need the
variable (later in the same class)?

Sorry for the confusion.

Felix Frank

unread,
Feb 8, 2012, 4:00:16 AM2/8/12
to puppet...@googlegroups.com
Hi,

On 02/08/2012 07:43 AM, jimbob palmer wrote:
> Now I will use includes as you suggest. Say I have a class that has an
> include, is there a guarantee that the include will always be included
> before the rest of the class is examined?

Referencing variables scoped to included classes will *always* work.

include foo
notify { "$foo::bar": }

where $bar is declared in the class foo.

Don't even thing about using $bar (without explicit scope $foo::bar)
anywhere outside the very foo class.
There are dynamic scoping features, but using them is stronly
discouraged (by me at least ;-)

> I mean withint the same class. Say I have a case statement at the top
> of my class that sets a variable, will that run before I need the
> variable (later in the same class)?

Yes, this most definitely works.

I don't even think it's important in which order you use and declare
variables, because variables can be assigned only once. So there is no
concept of "earlier" or "later" where variables are concerned.

HTH,
Felix

jimbob palmer

unread,
Feb 8, 2012, 8:57:46 AM2/8/12
to puppet...@googlegroups.com
2012/2/8 Felix Frank <felix...@alumni.tu-berlin.de>:

So say I have a single class which in order I need to ensure a file
doesn't exist, then after that install a package, then after that call
a define function.

The file package part is doable with a chain (although I could be more
confident about where they are defined), but how do I put the define
function in the chain?

>
> HTH,
> Felix

Felix Frank

unread,
Feb 8, 2012, 9:23:35 AM2/8/12
to puppet...@googlegroups.com
Hi,

On 02/08/2012 02:57 PM, jimbob palmer wrote:
> So say I have a single class which in order I need to ensure a file
> doesn't exist, then after that install a package, then after that call
> a define function.

careful: define() has nothing to do with custom functions.

You create a definded *type*. You do not call a define, you create
instances, resource-like entities that comprise multiple resources each.

> The file package part is doable with a chain (although I could be more

Absolutelzy.

> confident about where they are defined), but how do I put the define
> function in the chain?

Suppose your defined type is define mycooltype() { }.

package { "whatever": before => Mycooltype["cool-type-entity"] }

If your question was geared to the effect of "i want my custom type to
be defined after the package was ensured", well, that doesn't make
sense. Chains and require/before are used to control the order of agent
operation. That's all you need to worry about. At what time the *master*
processes your define() is not important at all.

Caveat:
mycooltype { "cool-type-entity": require => Package["whatever"] }
will *not* work out of the box. See defined types in
http://docs.puppetlabs.com/guides/language_guide.html#resource-collections
for details.

HTH,
Felix

jcbollinger

unread,
Feb 8, 2012, 9:24:14 AM2/8/12
to Puppet Users


On Feb 8, 12:43 am, jimbob palmer <jimbobpal...@gmail.com> wrote:
> Thanks. but I meant more within the same class: before I was using
> class inheritance to ensure that I don't have to worry about ordering.


Class foo::specific 'include'ing class foo::common on the first line
of its body gives exactly the same ordering guarantees that would be
afforded by foo::specific inheriting from foo::common, so inheritance
gains you nothing special there. Moreover, those guarantees are
*entirely* with respect to catalog compilation (on the master), not
the order in which resources are applied to your nodes by the agent.

To influence the order in which resources are applied, you need to set
up relationships between resources and / or classes. That is what the
'require' variant of the 'include' function, resources' require /
before / listen / notify metaparameters, and the resource chaining
operators are for.


> Now I will use includes as you suggest. Say I have a class that has an
> include, is there a guarantee that the include will always be included
> before the rest of the class is examined?


When you use the 'include' function, you can rest assured that the
declarations you have included will be visible to all code that
follows the inclusion within the same scope (that is, within the same
class, defined type, or node definition) in top-to-bottom order. All
class, resource, and type declarations are globally visible once they
are parsed, so once you have 'include'd a class, that class and all
the resources it declares are also visible to classes referenced by
subsequent 'include' calls.


> >> And a related question: if I have a case statement at the top of my
> >> class that sets a variable, how can I be sure the variable will be set
> >> before I need it lower down in the same class?
>
> > If you mean there's a variable in foo::common you want to reference in
> > foo::specific just use fully qualified variable and include
> > foo::common.
>
> I mean withint the same class. Say I have a case statement at the top
> of my class that sets a variable, will that run before I need the
> variable (later in the same class)?


Puppet processes each manifest file in order from top to bottom.
Declarations appearing earlier in the file are guaranteed to be
visible to code later in the file.


John
Reply all
Reply to author
Forward
0 new messages