Ask Your Question
0

Managing common resources with roles and profiles

asked 2014-12-04 09:31:01 -0500

mraynham gravatar image

Hi,

I'm quite new to Puppet, and have spent quite a lot of time reading the docs and researching how best to organise our manifests. As a developer, the roles and profiles pattern makes a lot of sense, but I'm still struggling with some fundamental problems. In particular, I am unsure of a good way to manage common resources, such as packages that are required by multiple roles or profiles, especially when we use some third-party Forge modules that explicitly declare package resources.

By way of an example, let's assume I have a web server role and a job queue role. The application profile is common to both:

class acme::role::web_server {
    include acme::profile::application
    include acme::profile::web_server
}

class acme::role::job_queue {
    include acme::profile::application
    include acme::profile::gearman
}

Each profile defines the components that it requires to operate as a standalone unit. The examples show each component as a separate module that can be included, but that doesn't have to be the case - the resources could be declared directly in the profile:

class acme::profile::application {
    include acme::component::network
    include acme::component::ntp
    include acme::component::application
}

class acme::profile::web_server {
    include acme::component::network
    include acme::component::ntp
    include acme::component::httpd
}

class acme::profile::gearman {
    include acme::component::network
    include acme::component::ntp
    include acme::component::application
    include acme::component::gearman
}

The network and ntp components are common to all profiles, and could therefore be placed in a parent class from which all others inherit. It's a trade-off between duplication and each profile being explicit.

Now let's say that the application component and the gearman component both share common package requirements, such as gcc and memcached. I can't explicitly declare those dependencies in both my application and gearman components because that will cause duplicate resource errors. I could define those dependencies as virtual resources, and then realize them in my components:

class acme::packages {
    @package {['gcc', 'memcached']: ensure => 'installed'}
}

class acme::component::application {
    include acme::packages
    realize Package['gcc', 'memcached']
    ...
}

But let's also say that a third-party Forge module used by the gearman component already explicitly installs the gcc package. That will cause a conflict with my virtual gcc package definition. The simple solution is to remove my virtual gcc package definition, but then the fact that my components require gcc is lost. I could comment it out, with a note that explains the problem, but that's starting to get really messy:

class acme::packages {
    @package {[
        # 'gcc', Installed by third-party module
        'memcached'
    ]: ensure => 'installed'}
}

class acme::component::application {
    realize Package[
        # 'gcc', Installed by third-party module
        'memcached'
    ]
    ...
}

I could decide not to use the Forge module, but then I'd have to rewrite the useful bits. I could edit the module, but that makes upgrading difficult. After some digging around, I found the constraints module, which allows me to explicitly specify my component's dependencies, without actually declaring them as resources:

class acme::component::application ...
(more)
edit retag flag offensive close merge delete

Comments

Did you ever find a resolution to this issue? I've come to the same problem. I have two profiles that require a common component (e.g. ssh). Most component modules seem to use templates so we would have to have duplicate declarations.

ljkimmel9903 gravatar imageljkimmel9903 ( 2017-05-04 09:44:04 -0500 )edit

While we could provide all required parameters to the component directly, we then lose the explicit requirement for the component within the profile.

ljkimmel9903 gravatar imageljkimmel9903 ( 2017-05-04 09:44:52 -0500 )edit

1 Answer

Sort by ยป oldest newest most voted
0

answered 2014-12-09 11:41:35 -0500

lorcutt gravatar image

The puppetlabs-stdlib package provides ensure_resource. You could use it like:

class acme::role::web_server {
  ensure_resource(
      'package',
      ['memcached','gcc'],
      { ensure => 'installed' },
  )
  include acme::profile::application
  include acme::profile::web_server
}

class acme::role::job_queue {
  ensure_resource(
      'package',
      ['memcached'],
      { ensure => 'installed' },
  )
  include acme::profile::application
  include acme::profile::gearman
}
edit flag offensive delete link more

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

1 follower

Stats

Asked: 2014-12-04 09:31:01 -0500

Seen: 280 times

Last updated: Dec 09 '14