6

I am relatively new to Puppet, but so far realize it to be a very powerful tool.

For an easy example, lets say I have a module "ntp" In module ntp I have three classes:

  • class ntp - Installs the package from the distro package provider, sets the information for starting the service, etc
  • class ntp::client - Creates the configuration file to use my local ntp servers, stops ntp, forces an ntpupdate, and starts the ntp service
  • class ntp::server - Creates the configuration file to make my local ntp servers, stops ntp, forces an ntpupdate (on initial configuration), and starts the ntp service

I am unsure of the proper way to make the service definitions in the ntp class available to the ntp::client and ntp::server classes.

I am using facts to basically case the different operating systems and the package and service names. I left that out of my examples to save clutter.

Instead of having something like the following in each class:

service{ 'ntp':
  name      => $ntpservice,
  ensure    => running,
  subscribe => File['ntpconf'],
}
package{ 'ntp':
  (etc - I think the point has been communicated)

I would think it would be cleaner and easier to define the service in the ntp class and call that service in the class ntp from class ntp::client and ntp::server. Basically, because of multiple platforms (RHEL based and Debian based) the packages and services may be slightly different definitions.

What I would prefer to have in ntp::client and ntp::server is something like this:

file{ 'ntpconf':
  source  => 'puppet:///modules/ntp/ntp.conf',
  owner   => 'root',
  group   => 'root',
  mode    => '0644',
  notify  => Service[**CALL TO class ntp SERVICE**],
  require => Package[**CALL TO class ntp PACKAGE**],
}

I seem to remember reading in the documentation some time back that this can be done, but I CANNOT seem to find it again. Of all the things I bookmarked, I failed to bookmark this!

Any suggestions are greatly appreciated. Thanks in advance.

EDIT In addition, I am using facts and casing to set the parameters for the package name and service names by operating system. I didn't include that information in the example code because it is working fine and seems like unnecessary clutter.

3
  • 1
    I think I don't understand your question. If you include the "ntp" class in the "ntp::client" and "ntp::server" classes, are you not able to use those resources' names directly, e.g. 'Package["ntp"]'? Can you post some --debug output of it not working?
    – Handyman5
    Jul 31, 2012 at 16:58
  • I could include the class ntp in the other classes. Lets go ahead and pretend that I have cross module dependencies (I know - bad idea). Lets say a class in Module5 has to restart the ntp service that is defined in class NTP - Is there anyway to make the service definition globally available?
    – JTWOOD
    Aug 1, 2012 at 10:57
  • I don't know of one.
    – Handyman5
    Aug 1, 2012 at 19:24

2 Answers 2

1

I've done it this way. It might be a bit cleaner to use an ENC or Hiera to do a lookup based on the server name or role and decide whether to include ntp::server or whatnot, but this is fairly simple and requires no additional software or setup.

Keep in mind that Puppet's inheritance model isn't normal. You will have trouble unless your use of it is very very simple. I would not inherit more than once in any module.

class ntp {
  include ntp::install, ntp::config, ntp::sevice
  Class['ntp::install'] -> Class['ntp::config'] ~> Class['ntp::service']
}

class ntp::config {
  file { 'ntp.conf':
    ensure  => present,
    content => template('ntp/ntp.erb'),
  }
}

class ntp::config::server inherits ntp::config {
  File['ntp.conf'] { content => template('ntp/ntp.conf.server.erb'), }
}

node basenode {
  include ntp
}
node /^ntp\d+/ inherits basenode {
  include ntp::config::server
}
2
  • I will definitely look at this example closer. I need to read a bit more about the inheritance and make sure I understand it and it suits my needs. I am definitely looking at Hiera, but rather than trying to learn everything at once, I am satisfied with getting Puppet in place and working for now. It has been a boon just for virtual machines that I set up for testing configuration changes and software packages. The time it saves is incredible - I can create a replica of a production server in a new virtual machine in moments to test major upgrades or changes. Thanks for your input!
    – JTWOOD
    Aug 1, 2012 at 11:02
  • 1
    In regards to inheritance this example should work fine because it's very simple and only happens once in a module. I did want you caution you against inheritance across modules, multiple levels of inheritance, and other designs that are almost guaranteed to cause problems.
    – kashani
    Aug 1, 2012 at 16:59
1

I stumbled upon what Puppet themselves deems to be the proper solution.

I had read that inheritance should be avoided, but it is with one exception, classes within modules - according to documentation found at Puppet Style-Guide -- Class Inheritance

Since these are the people writing the software, I deem this to be the BEST solution.

Basically, if I had the above package and service definitions in class ntp, when I define the class ntp::server I would do the following:

class ntp::server inherits ntp {

That would provide what I needed and solves the problem.

Thanks all!

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .