Puppet - Restart a service in a different class

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.


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
}

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!