puppet duplicate resources and virtual resources

Overview

I just started using Puppet and have been unable to suss something.

Problem

Because of normalization, when I add two classes to a node with packages that have the same dependencies it fails.

In simple terms have duplicate resources - in this case the package libssl.

Note: packages are being held to prevent latest packages being installed.

Question

What's the best practice way to get round this?

class ssh {
  package { 'openssh-server':
    ensure  => installed,
    require => Package['libssl'],
  }
  package { 'libssl': ensure => installed, }
}

class apache {
  package { 'apache':
    ensure   => installed,
    require  => Package['libssl'], 
  }        
  package { 'libssl': ensure => installed, }
}

node server {
  include apache
  include openssl-server

Solution 1:

You have two choices that are going to look almost the same.

1: make it it's own class.

class ssh {
  package { 'openssh-server':
    ensure => present,
    require => Class['ssl'],
  }
}
class ssl {
  package { 'libssl': ensure => present, }
}

2: virtual resource

class vpackages {
  @package { 'libssl': }
}
class ssh {
  include vpackages
  package { 'openssh-server':
    ensure => present,
    require => Package['libssl'],
  }
  realize Package['libssl']
}

I find it better to break dependencies out into their own modules rather than use virtual resources.

Solution 2:

If you're using the standard package management to manage the packages installed via Puppet than you should be able to leave off the libssl package dependency in Puppet as that will be handled automatically via the package management system on most systems.

On Debian/Ubuntu as well as RedHat/CentOS/SuSE systems the package management tools will look for dependencies and unless you've gone out of your way to stop the default behavior the additional dependent packages will be included when Puppet tells the system to install the package (in your case simply openssh-server or apache)