FAQ
Hi.

I've seen in many modules at puppet-forge this kind of organization:

class myclass(
$somevar='value'
) inherits myclass::params {
file { $mydir:
ensure => directory,
}
}

class myclass::params {
$mydir = '/some/path'
}


Now, I wonder how can I override $mydir from node definition? Or am I
missing the whole point, am I supposed to put $mydir inside standard
brackets and then call the class with something like:

node mynode.mydomain.com {
class myclass($mydir='/some/other/path')
}


Thank you

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

Search Discussions

  • Jcbollinger at Sep 5, 2012 at 9:37 pm

    On Wednesday, September 5, 2012 1:19:16 PM UTC-5, Jakov Sosic wrote:
    Hi.

    I've seen in many modules at puppet-forge this kind of organization:

    class myclass(
    $somevar='value'
    ) inherits myclass::params {
    file { $mydir:
    ensure => directory,
    }
    }

    class myclass::params {
    $mydir = '/some/path'
    }


    Now, I wonder how can I override $mydir from node definition?


    Not as your example is written, read on.


    Or am I
    missing the whole point, am I supposed to put $mydir inside standard
    brackets and then call the class with something like:

    node mynode.mydomain.com {
    class myclass($mydir='/some/other/path')
    }
    I think very likely have overlooked a key aspect of the pattern you
    observed (or else the modules you are looking at aren't good teaching
    examples). The usual usage of the pattern I suspect you've seen is more
    like this:

    # This might as readily be named mymodule::myclass
    class mymodule ($myparam = $myparam_default) inherits mymodule::params {
    file { $myparam:
    # ...
    }
    }

    class mymodule::params {
    $myparam_default = '/some/path'
    }


    The key difference there is that a variable declared by the ::params class
    is used as a default value for a parameter of the class that inherits it.
    That's the *only* reason why class inheritance is reasonable in this
    particular case. As a matter of good style, classes inherited for this
    purpose should normally contain only variable declarations.

    If one class wants to use another class's variables, but not as class
    parameter defaults, then it should not inherit from that class. Instead,
    it should 'include' that class (provided it is not parametrized) and then
    refer to the variables by their fully-qualified names, such as
    $mymodule::params::anothervar. Inheriting the ::params class is simply a
    trick to ensure the variables are initialized and accessible for use before
    any part of the class body of the inheriting class is parsed (i.e. in time
    to be used as parameter defaults).

    Getting back to your questions, no, you cannot override the value of a
    class variable, but you *can* provide your own values for class parameters,
    which will then be used instead of whatever default values may have been
    declared. That's done like so:

    class { "mymodule":
    # parameters follow...
    myparam => 'custom value'
    }

    Yes, it looks very much like a resource declaration. No, I don't think
    that was a good design decision, but the prevailing opinion at PuppetLabs
    is different, or was when parametrized classes were added.

    Before you start swooning over how nice parametrized classes look, let me
    warn you that they carry some substantial drawbacks. Therefore, I urge you
    to avoid using them in your own code as much as you can do, at least until
    you understand Puppet well enough to appreciate why they might make sense
    in some circumstances (clue me in when you figure that out), and especially
    until you appreciate the problems they present. Hint: the biggest one is
    that parametrized classes cannot be declared more than once.

    There are other, better ways to get data to your classes, notably data
    access functions such as hiera(), and global or [other]class variables.
    Puppet 3 does shine up parametrized classes a lot, in large part by
    integrating hiera directly into parameter value resolution. Nevertheless,
    you don't need class parameters, and even in Puppet 3, parametrized classes
    retain a few pointy bits. Therefore, I'd focus on building classes that
    rely on hiera (which for Puppet 2.x is a third-party extension) where they
    need external data, as that will serve you well both now and going forward.


    John

    --
    You received this message because you are subscribed to the Google Groups "Puppet Users" group.
    To view this discussion on the web visit https://groups.google.com/d/msg/puppet-users/-/sHqw7Z31O_sJ.
    To post to this group, send email to puppet-users@googlegroups.com.
    To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com.
    For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en.
  • Jakov Sosic at Sep 7, 2012 at 11:25 am

    On 09/05/2012 11:37 PM, jcbollinger wrote:

    class { "mymodule":
    # parameters follow...
    myparam => 'custom value'
    }

    Yes, it looks very much like a resource declaration. No, I don't think
    that was a good design decision, but the prevailing opinion at
    PuppetLabs is different, or was when parametrized classes were added.
    It's a shame you cannot define multiple instances of parametrized
    classes with different parameters :(

    Anyway, how should I approach adding dynamic content into node's
    manifest, using a define maybe?

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

    On Friday, September 7, 2012 6:25:11 AM UTC-5, Jakov Sosic wrote:
    On 09/05/2012 11:37 PM, jcbollinger wrote:

    class { "mymodule":
    # parameters follow...
    myparam => 'custom value'
    }

    Yes, it looks very much like a resource declaration. No, I don't think
    that was a good design decision, but the prevailing opinion at
    PuppetLabs is different, or was when parametrized classes were added.
    It's a shame you cannot define multiple instances of parametrized
    classes with different parameters :(

    No, that's not it. I mean you can't do that, but the real problem is that
    you can't declare the same parametrized class multiple times even with the *
    same* parameters. That's one of the things you *can* do with ordinary
    classes (with the same effect as declaring that class exactly once), and
    there are several circumstances where it's a useful ability to have.

    Classes are singletons, so it doesn't make sense to try to assign different
    sets of parameters in different places. If you are trying to model some
    aspect of your systems that may be present more than once, then it's
    certainly a resource, and it should be modeled via one of Puppets built-in
    resources or via a resource of a custom or defined type. Most of the time
    you can use a defined type.

    Anyway, how should I approach adding dynamic content into node's
    manifest, using a define maybe?

    That's what I addressed at the end of my previous message. I strongly
    recommend that you look into hiera. Adding to what I already said,
    however, resources of defined types are just fine when a resource (as
    opposed to a class) is in fact what you want. It is worthwhile to
    understand the difference between class and resource at the conceptual
    level, because there are some circumstances that require a class. You may
    save yourself future grief if you start out with classes where they're
    appropriate, even if, for the moment, they're not actually needed.


    John


    --
    You received this message because you are subscribed to the Google Groups "Puppet Users" group.
    To view this discussion on the web visit https://groups.google.com/d/msg/puppet-users/-/ECnytUOh7MgJ.
    To post to this group, send email to puppet-users@googlegroups.com.
    To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com.
    For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en.
  • Jakov Sosic at Sep 7, 2012 at 3:26 pm

    On 09/07/2012 03:20 PM, jcbollinger wrote:

    That's what I addressed at the end of my previous message. I strongly
    recommend that you look into hiera. Adding to what I already said,
    however, resources of defined types are just fine when a resource (as
    opposed to a class) is in fact what you want. It is worthwhile to
    understand the difference between class and resource at the conceptual
    level, because there are some circumstances that require a class. You
    may save yourself future grief if you start out with classes where
    they're appropriate, even if, for the moment, they're not actually needed.
    I don't think you understood me there :) I use hiera for some purposes,
    but this is my class:

    class cobbler (
    $service_name = $cobbler::params::service_name,
    $package_name = $cobbler::params::package_name,
    $package_ensure = $cobbler::params::package_ensure,
    $distro_path = $cobbler::params::distro_path,
    ) inherits cobbler::params {
    package { $package_name :
    ensure => $package_ensure,
    }
    service { $service_name :
    ensure => running,
    enable => true,
    require => Package[$package_name],
    }
    file { $distro_path :
    ensure => directory,
    owner => root,
    group => root,
    mode => '0755',
    }
    file { '/etc/cobbler/settings':
    ensure => present,
    owner => root,
    group => root,
    mode => '0644',
    content => template('cobbler/settings.erb'),
    notify => Service["$service_name"],
    }
    define add_distro ($arch,$isolink){
    $distro = $title
    cobblerdistro { $distro :
    ensure => present,
    arch => $arch,
    isolink => $isolink,
    destdir => $cobbler::distro_path,
    require => Service[$cobbler::service_name],
    }
    }
    define del_distro (){
    $distro = $title
    cobblerdistro { $distro :
    ensure => absent,
    destdir => $cobbler::distro_path,
    require => Service[$cobbler::service_name],
    }
    }
    }


    So, from node manifest, I can do this:
    node 'mynode' {
    class { 'cobbler':
    distro_path => '/data/distro'
    }
    cobbler::add_distro { 'CentOS-6.3-x86_64':
    arch => 'x86_64',
    isolink =>
    'http://mi.mirror.garr.it/mirrors/CentOS/6.3/isos/x86_64/CentOS-6.3-x86_64-bin-DVD1.iso',
    }
    cobbler::add_distro { 'CentOS-6.2-x86_64':
    arch => 'x86_64',
    isolink =>
    'http://mi.mirror.garr.it/mirrors/CentOS/6.2/isos/x86_64/CentOS-6.2-x86_64-bin-DVD1.iso',
    }
    }


    Is this OK?

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

    On Friday, September 7, 2012 10:02:56 AM UTC-5, Jakov Sosic wrote:
    On 09/07/2012 03:20 PM, jcbollinger wrote:

    That's what I addressed at the end of my previous message. I strongly
    recommend that you look into hiera. Adding to what I already said,
    however, resources of defined types are just fine when a resource (as
    opposed to a class) is in fact what you want. It is worthwhile to
    understand the difference between class and resource at the conceptual
    level, because there are some circumstances that require a class. You
    may save yourself future grief if you start out with classes where
    they're appropriate, even if, for the moment, they're not actually
    needed.

    I don't think you understood me there :) I use hiera for some purposes,
    but this is my class:

    class cobbler (
    $service_name = $cobbler::params::service_name,
    $package_name = $cobbler::params::package_name,
    $package_ensure = $cobbler::params::package_ensure,
    $distro_path = $cobbler::params::distro_path,
    ) inherits cobbler::params {
    package { $package_name :
    ensure => $package_ensure,
    }
    service { $service_name :
    ensure => running,
    enable => true,
    require => Package[$package_name],
    }
    file { $distro_path :
    ensure => directory,
    owner => root,
    group => root,
    mode => '0755',
    }
    file { '/etc/cobbler/settings':
    ensure => present,
    owner => root,
    group => root,
    mode => '0644',
    content => template('cobbler/settings.erb'),
    notify => Service["$service_name"],
    }
    define add_distro ($arch,$isolink){
    $distro = $title
    cobblerdistro { $distro :
    ensure => present,
    arch => $arch,
    isolink => $isolink,
    destdir => $cobbler::distro_path,
    require => Service[$cobbler::service_name],
    }
    }
    define del_distro (){
    $distro = $title
    cobblerdistro { $distro :
    ensure => absent,
    destdir => $cobbler::distro_path,
    require => Service[$cobbler::service_name],
    }
    }
    }


    So, from node manifest, I can do this:
    node 'mynode' {
    class { 'cobbler':
    distro_path => '/data/distro'
    }
    cobbler::add_distro { 'CentOS-6.3-x86_64':
    arch => 'x86_64',
    isolink =>
    '
    http://mi.mirror.garr.it/mirrors/CentOS/6.3/isos/x86_64/CentOS-6.3-x86_64-bin-DVD1.iso',

    }
    cobbler::add_distro { 'CentOS-6.2-x86_64':
    arch => 'x86_64',
    isolink =>
    '
    http://mi.mirror.garr.it/mirrors/CentOS/6.2/isos/x86_64/CentOS-6.2-x86_64-bin-DVD1.iso',

    }
    }


    Is this OK?

    It depends on what you mean by "OK". Your class is not consistent with my
    recommendations, but that doesn't make it wrong.

    I am recommending that you use *only* hiera to communicate site- and
    node-specific data to your classes. That is, according to me, you should
    avoid use of parametrized classes wherever it is feasible to do so. That
    would mean using parametrized classes only from third-party modules,
    really, since you can always avoid parametrization in classes you write
    yourself. Thus, your "cobbler" class might start this way:

    class cobbler {
    include 'cobbler::params'

    $service_name = hiera('cobbler_service_name',
    $cobbler::params::service_name)
    $package_name = hiera('cobbler_package_name',
    $cobbler::params::package_name)
    $package_ensure = hiera('cobbler_package_ensure',
    $cobbler::params::package_ensure)
    $distro_path = hiera('cobbler_distro_path', $cobbler::params::distro_path)

    # ...


    Voila, (the beginning of) a non-parametrized version of your class.
    Nothing else has to change (but see below). Note that the non-parametrized
    version also doesn't need the inheritance trick; it uses an ordinary
    'include' instead.

    On a separate note, the PuppetLabs style recommendation and prevailing
    opinion agree that type definitions should go into their own files. Thus,
    instead of add_distro() and del_distro() being defined in the body of class
    cobbler, they should appear in sibling files add_distro.pp and
    del_distro.pp. And as a side note, that will actually be much cleaner with
    the non-parametrized version of class cobbler than it would be with the
    parametrized version, because

    1. It is safe for the definition bodies (in a separate file) to refer to
    class variables, but not to class parameters (the latter fails in some
    Puppet versions).
    2. The definition bodies can 'include' class cobbler to ensure that its
    variables are recognized (which they must not do if 'cobbler' is
    parametrized, even if they know the correct parameters, because
    parametrized classes can be declared at most once)
    3. If you do (2), then, at your option, your nodes don't have to declare
    class 'cobbler' at all as long as they declare at least one
    cobbler::add_distro or cobbler::del_distro resource

    So, for instance:

    modules/cobbler/manifests/add_distro.pp:

    define add_distro ($arch, $isolink) {
    include 'cobbler'

    cobblerdistro { $title :
    ensure => present,
    arch => $arch,
    isolink => $isolink,
    destdir => $cobbler::distro_path,
    require => Service[$cobbler::service_name],
    }
    }


    John

    --
    You received this message because you are subscribed to the Google Groups "Puppet Users" group.
    To view this discussion on the web visit https://groups.google.com/d/msg/puppet-users/-/z_FI9FiOJVMJ.
    To post to this group, send email to puppet-users@googlegroups.com.
    To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com.
    For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en.
  • Jcbollinger at Sep 10, 2012 at 2:28 pm

    On Monday, September 10, 2012 8:34:33 AM UTC-5, jcbollinger wrote:

    modules/cobbler/manifests/add_distro.pp:

    define add_distro ($arch, $isolink) {
    Oops, that should be

    define cobbler::add_distro ($arch, $isolink) {
    #...


    John

    --
    You received this message because you are subscribed to the Google Groups "Puppet Users" group.
    To view this discussion on the web visit https://groups.google.com/d/msg/puppet-users/-/XbOkFbWimXkJ.
    To post to this group, send email to puppet-users@googlegroups.com.
    To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com.
    For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en.
  • Jakov Sosic at Sep 11, 2012 at 5:00 pm

    On 09/10/2012 04:01 PM, jcbollinger wrote:


    On Monday, September 10, 2012 8:34:33 AM UTC-5, jcbollinger wrote:


    modules/cobbler/manifests/add_distro.pp:

    define add_distro ($arch, $isolink) {


    Oops, that should be

    define cobbler::add_distro ($arch, $isolink) {
    #...
    Thank you for your insights, very helpful!

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

    On 05/09/12 23:37, jcbollinger wrote:
    Before you start swooning over how nice parametrized classes look, let
    me warn you that they carry some substantial drawbacks. Therefore, I
    urge you to avoid using them in your own code as much as you can do,
    at least until you understand Puppet well enough to appreciate why
    they might make sense in some circumstances (clue me in when you
    figure that out), and especially until you appreciate the problems
    they present. Hint: the biggest one is that parametrized classes
    cannot be declared more than once.
    I've raised this very topic on the IRC channel, due to my frustration
    with the *bug* [1] that makes impossible to override parameters with
    custom classes while inheriting, and I still don't understand *why* is
    inheritance so bad nad if it's so, why is it still there? I think
    inheritance improves a lot manifests/classes readability and personally
    I hate using global variables and passing parameters (but it's just a
    matter of taste).

    But hey, if there's any technical reason in Puppet that makes
    inheritance bad, I'm all ears and happy to change my mind about it :)

    [1] https://projects.puppetlabs.com/issues/5517

    --
    Davide Ferrari
    Senior System Administrator
    Trovit Search http://www.trovit.com

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

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
grouppuppet-users @
categoriespuppet
postedSep 5, '12 at 6:19p
activeSep 11, '12 at 5:00p
posts9
users3
websitepuppetlabs.com

People

Translate

site design / logo © 2021 Grokbase