Forum Discussion

emmablisa's avatar
8 years ago

What is the major differences between Puppet inheritance vs Puppet composition.?

 What is the major differences between Puppet   inheritance vs Puppet composition.?

 

I just came cross puppet inheritance lately. A few  questions around it:

1. Is it a good practice to use puppet inheritance? I've been told by some of the experienced puppet colleagues Inheritance in puppet is not very good, I was not quite convinced.

2. Coming from OO world, I really want to understand under the cover, how puppet inheritance works, how overriding works as well.

 

 

  • eculler's avatar
    eculler
    Former Employee

    Hi emmablisa,

    Thanks for your questions. There are a few differences between inheritance and composition which lend themselves to slightly different use cases. Currently in our environment we use a combination of both class inheritance and composition to try and get the most out of each.

    Inheritance:

    There are 2 kinds of inheritance in (certain versions) of puppet. Node and class inheritance. As of puppet 4.0.0 node inheritance has been removed from the puppet language, so I'm going to skip that one.

    Class inheritance has the following effects

    • implicit declaration of base class first when the child class is declared 
    • base class becomes parent scope providing access to all of the base classes variables and resource defaults - this also allows for overriding the values and defaults.
    #This code is based on the logicmonitor puppet module
    include logicmonitor::collector # implictly includes the logicmonitor base class.
    
    # you can override the base class credentials
    class{'logicmonitor::master':
      account => 'accountname',
    }
    
    # the next examples show how the above classes are defined.
    
    class logicmonitor(
      $account    = undef,
      $access_id  = undef,
      $access_key = undef,
    ) {
    ...
    }
    
    class logicmonitor::collector(
      $install_dir      = '/usr/local/logicmonitor/',
      $agent_service    = 'logicmonitor-agent',
      $watchdog_service = 'logicmonitor-watchdog'
    ) inherits logicmonitor {
    ...
    }
    
    class logicmonitor::master (
      $account    = $logicmonitor::account,
      $access_id  = $logicmonitor::access_id,
      $access_key = $logicmonitor::access_key,
    )inherits logicmonitor {
    ...
    }

    In addition to the usage in modules like this, we use inheritance to reduce the redundancy of code in the role/profile framework documented here.

    Composition:

    This is a way to establish a ordering relationship while avoiding duplicate declaration of resources.

    If 2 classes within a profile have a dependency on the same class you can run into duplicate resource declaration errors.

    #Both classes are tomcat apps.
    
    class app1 {
      include tomcat::tomcat7_0_52
    }
    
    class app2 {
      include tomcat::tomcat7_0_52
    }
    
    #This will result in duplicate declaration
    class { ['app1', 'app2']: }
    
    #vs
    
    
    class app1 {
        Class['tomcat::tomcat7_0_52'] -> Class['app1']
    }
    
    class app2 {
      Class['tomcat::tomcat7_0_52'] -> Class['app2']
    }
    
    class { ['app1', 'app2']: }
    
    # This is ok, but requires that the node has the tomcat::tomcat7_0_52 class declared elsewhere.

    Hopefully this answers your questions.

    ~Ethan