Search code examples
puppet

Extend a class from different puppet module


I need to extend a class from a different Puppet module. Is it possible to do this? If yes, what would be the syntax?


Solution

  • In Puppet, it is possible for a class a::b to inherit class a via the inherits keyword. This allows class a::b to "extend" class a.

    Note that Puppet recommends that you should rarely if ever need to do this. In particular, most of what can be achieved by inheritance can also be achieved by just including the base class by using the include function. For more information, see the documentation here.

    If you do choose to use inheritance, class a is automatically declared first; class a becomes the parent scope of class a::b, so it receives copies of all variables and resource defaults; and the code in class a::b has permission to override resource attributes that are set in class a.

    Using this pattern, it is also possible for class a::b to use a variable from class a as a default for one of its class parameters. This led to the "params pattern" where a params.pp file is used to set class defaults.

    The following simple code example illustrates all of these features:

    class a {
      File {
        mode => '0755',
      }
      file { '/tmp/foo':
        ensure => absent,
      }
      $x = 'I, Foo'
    }
    
    class a::b (
      $y = $a::x  # default from class a.
    ) inherits a {
    
      # Override /tmp/foo's ensure
      # and content attributes.
    
      File['/tmp/foo'] {
        ensure  => file,
        content => $y,
      }
    
      # Both /tmp/foo and /tmp/bar
      # will receive the default file
      # mode of 0755.
    
      file { '/tmp/bar':
        ensure => file,
      }
    }
    

    And using Rspec to express the catalog's expected end-state:

    describe 'a::b' do
      it 'overrides ensure attribute' do
        is_expected.to contain_file('/tmp/foo').with({
          'ensure'  => 'file',
        })
      end
      it 'inherits content from $x' do
        is_expected.to contain_file('/tmp/foo').with({
          'content' => "I, Foo",
        })
      end
      it 'file defaults inherited' do
        is_expected.to contain_file('/tmp/foo').with({
          'mode' => '0755',
        })
        is_expected.to contain_file('/tmp/bar').with({
          'mode' => '0755',
        })
      end
    end
    

    Tests pass:

    a::b
      overrides ensure attribute
      inherits content from $x
      file defaults inherited
    
    Finished in 0.15328 seconds (files took 1.2 seconds to load)
    3 examples, 0 failures
    

    A note about "plusignment".

    As also described in the documentation, it is possible, when overriding a resource attribute that is an array, to add to that array instead of replacing using the +> "plusignment" operator. It is a rarely used feature, but should be mentioned in this context. See the link above for a code example.