Johan Sunnerstig
2011-Nov-02 08:31 UTC
[Puppet Users] Inheritance and parameterized classes
Hi. I''ve been reading up on inheritance, parameterized classes and whatnot, and basically wish to see whether I''m thinking right or if I''m just confused(more than usual). I''ll use a trivial NFS module as an example since it should cover the basic questions and has some interesting dependencies. I have Debian and RedHat(including Scientific Linux, but I''ll treat those the same as RH) boxes, our standard setup disables NFS on these, the occasional box might have it enabled. On Debian an NFS server depends on three services, nfs-common, nfs-kernel-server and portmap. The client depends on nfs-common and portmap. On Redhat the server depends on nfs and rpcbind, the client on rpcbind. (I''ll note that this is to the best of my knowledge so far since RH didn''t bother documenting NFS particularly well for RHEL 6.x). The goal is the usual(I would guess), a basic node config that has a baseline of hardening, ideally I would use this for every other node unless I''m doing something really different(say setting up a server with intentionally bad hardening for testing purposes or something). Nodes would then override this as needed. I can think of a couple of ways to do this, but having read some of the conversations on parameterized classes it seems like this is the way forward and preferred by Puppetlabs. Basically I want to follow best practices and make sure I make my setup as futureproof as I reasonably can. I''m on 2.6.x right now but the less I have to rewrite when the time for 2.8 or even 3.0 comes, the happier I''ll be obviously. :) So what I''m thinking is something like so for nodes: nodes.pp ---- node basenode { include nfs ( server=no, client=no ) ... } node somebox inherits basenode { ... } node nfsserver inherits basenode { include nfs ( server=yes ) ... } The NFS module would look something like: init.pp ---- class nfs::params { OS detection and such. } class nfs::install { install packages as needed, skip entirely pretty much if both server and client are no. } class nfs::config { configure as needed } class nfs::service { start/stop services based on server/client=yes/no. } class nfs ( $server, $client ) { include nfs::params, nfs::install, nfs::config, nfs::service } Does this make sense or am I about to blown my foot off? Regards Johan -- 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
2011-Nov-03 13:59 UTC
[Puppet Users] Re: Inheritance and parameterized classes
On Nov 2, 3:31 am, Johan Sunnerstig <Johan.Sunners...@auriga.se> wrote:> Hi. > > I''ve been reading up on inheritance, parameterized classes and whatnot, and basically wish to see whether I''m thinking right or if I''m just confused(more than usual). > I''ll use a trivial NFS module as an example since it should cover the basic questions and has some interesting dependencies. > > I have Debian and RedHat(including Scientific Linux, but I''ll treat those the same as RH) boxes, our standard setup disables NFS on these, the occasional box might have it enabled. > On Debian an NFS server depends on three services, nfs-common, nfs-kernel-server and portmap. The client depends on nfs-common and portmap. > On Redhat the server depends on nfs and rpcbind, the client on rpcbind. (I''ll note that this is to the best of my knowledge so far since RH didn''t bother documenting NFS particularly well for RHEL 6.x). > > The goal is the usual(I would guess), a basic node config that has a baseline of hardening, ideally I would use this for every other node unless I''m doing something really different(say setting up a server with intentionally bad hardening for testing purposes or something). > Nodes would then override this as needed. > > I can think of a couple of ways to do this, but having read some of the conversations on parameterized classes it seems like this is the way forward and preferred by Puppetlabs. Basically I want to follow best practices and make sure I make my setup as futureproof as I reasonably can. > I''m on 2.6.x right now but the less I have to rewrite when the time for 2.8 or even 3.0 comes, the happier I''ll be obviously. :) > > So what I''m thinking is something like so for nodes: > > nodes.pp > ---- > node basenode { > include nfs ( server=no, client=no ) > ... > > } > > node somebox inherits basenode { > ... > > } > > node nfsserver inherits basenode { > include nfs ( server=yes ) > ... > > } > > The NFS module would look something like: > > init.pp > ---- > class nfs::params { > OS detection and such. > > } > > class nfs::install { > install packages as needed, skip entirely pretty much if both server and client are no. > > } > > class nfs::config { > configure as needed > > } > > class nfs::service { > start/stop services based on server/client=yes/no. > > } > > class nfs ( $server, $client ) { > include nfs::params, nfs::install, nfs::config, nfs::service > > } > > Does this make sense or am I about to blown my foot off?You are about to blow your foot off, or at least your little toe. You cannot include a parameterized class twice, not even with the same parameters, and certainly not with different parameters. That will scuttle catalog compilation for node nfsserver. If you abandon class parameterization then you can do this with class inheritance, but the two do not work well together. The class inheritance approach might look something like this: class nfs { include nfs::params, nfs::install, nfs::config, nfs::service } class nfs::service::enabled inherits nfs::service { # Override Service[''nfs''] to ensure it enabled and running } node basenode { include nfs ... } node nfsserver inherits basenode { include nfs::service::enabled } Alternatively, you can make basenode not include class nfs, leaving the choice of class parameters to the more specific node types, but then every one of them must include class nfs itself. Or you could use external data, such as obtained via extlookup() or hiera, to define whether nodes should be enabled as NFS servers. That would not only allow you to dispense with class nfs''s parameters, but probably you could also drop node nfsserver. In general (says me), you should avoid defining class parameters whose purpose is to tweak the *meaning* of the class, such as your $client and $server parameters. That sort of purpose is better served by providing distinct classes. As a rule of thumb, do not define class parameters whose values are not intended to end up as [part of] resource property values. (That''s supposing you have already decided to ignore my maxim #1 of Puppet class parameterization: don''t do it.) Using external data to tweak the meaning of a class is at least better than using parameters for the same purpose. It causes the same kind of ambiguation of the class''s meaning, but at least it doesn''t introduce the practical limitations that come with class parameterization. John -- 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.
Johan Sunnerstig
2011-Nov-07 09:51 UTC
RE: [Puppet Users] Re: Inheritance and parameterized classes
> > You are about to blow your foot off, or at least your little toe. You > cannot include a parameterized class twice, not even with the same > parameters, and certainly not with different parameters. That will > scuttle catalog compilation for node nfsserver. > > If you abandon class parameterization then you can do this with class > inheritance, but the two do not work well together. The class > inheritance approach might look something like this: > > class nfs { > include nfs::params, nfs::install, nfs::config, nfs::service > } > > class nfs::service::enabled inherits nfs::service { > # Override Service[''nfs''] to ensure it enabled and running > } > > node basenode { > include nfs > ... > } > > node nfsserver inherits basenode { > include nfs::service::enabled > } >That looks good to me, easy to understand, which makes me feel stupid for not thinking about it myself.> > Alternatively, you can make basenode not include class nfs, leaving > the choice of class parameters to the more specific node types, but > then every one of them must include class nfs itself. > > Or you could use external data, such as obtained via extlookup() or > hiera, to define whether nodes should be enabled as NFS servers. That > would not only allow you to dispense with class nfs''s parameters, but > probably you could also drop node nfsserver.Extlookup has been on my todo-list for a while, I just figured I''d try to get a better feel for the basics before I go there.> > In general (says me), you should avoid defining class parameters whose > purpose is to tweak the *meaning* of the class, such as your $client > and $server parameters. That sort of purpose is better served by > providing distinct classes. As a rule of thumb, do not define class > parameters whose values are not intended to end up as [part of] > resource property values. (That''s supposing you have already decided > to ignore my maxim #1 of Puppet class parameterization: don''t do it.)I haven''t really decided anything yet, I''m certainly not set on using parameterized classes, I''m mostly trying to find the Right Way to do things.> > Using external data to tweak the meaning of a class is at least better > than using parameters for the same purpose. It causes the same kind > of ambiguation of the class''s meaning, but at least it doesn''t > introduce the practical limitations that come with class > parameterization. > > > JohnThanks for the input, I''ll see if I can make the first way you suggested working, seems easy enough. :) Oh and sorry for the mail formatting...Outlook... Regards Johan -- 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.