Modules 201
                       Writing Flexible and Scalable
                                  Puppet


                        Eric Shamow | PuppetCamp NYC

Friday, April 27, 12
Who Am I?
                       • Senior Professional Services Engineer for
                         Puppet Labs
                       • Former Operations Manager
                       • Recovering Sysadmin
                       • Travel around helping people make Puppet
                         even more awesome
                       • Not Shamwow. If you came to the wrong
                         talk you can leave now
Friday, April 27, 12
How Did We Get
                            Here?
                       The module seemed just fine when I wrote
                                        it...




Friday, April 27, 12
How Did We Get
                            Here?
                       The module seemed just fine when I wrote
                                        it...
                         (I never thought RHEL 6 would come out)




Friday, April 27, 12
I never thought...




Friday, April 27, 12
I never thought...
                       • RHEL 6 would come out




Friday, April 27, 12
I never thought...
                       • RHEL 6 would come out
                       • My company would switch to Debian




Friday, April 27, 12
I never thought...
                       • RHEL 6 would come out
                       • My company would switch to Debian
                       • Other people would want to reuse the
                         module




Friday, April 27, 12
I never thought...
                       • RHEL 6 would come out
                       • My company would switch to Debian
                       • Other people would want to reuse the
                         module
                       • I’d want to use only a part of the module


Friday, April 27, 12
I never thought...
                       • RHEL 6 would come out
                       • My company would switch to Debian
                       • Other people would want to reuse the
                         module
                       • I’d want to use only a part of the module
                        • ...maybe as a part of something else

Friday, April 27, 12
Ur Doin It Wrong




Friday, April 27, 12
Puppet is Declarative
                          Shoehorning conditional logic into
                               declarative language?




Friday, April 27, 12
Puppet is Declarative
                          Shoehorning conditional logic into
                               declarative language?
                                Please do not do this:




Friday, April 27, 12
Puppet is Declarative
                           Shoehorning conditional logic into
                                declarative language?
                                 Please do not do this:
                       case $::operatingsystem {
                         ‘redhat’: {
                           if $::fqdn == “bobmarley” {
                              file { ‘foo’:
                                ...
                           } else {
                           ...
                          ...
                       }
Friday, April 27, 12
When Logic Fails




Friday, April 27, 12
Organizing Your Data




Friday, April 27, 12
Organizing Your Data

                       • Hiera




Friday, April 27, 12
Organizing Your Data

                       • Hiera
                       • External Node Classifiers




Friday, April 27, 12
Organizing Your Data

                       • Hiera
                       • External Node Classifiers
                       • Custom Functions




Friday, April 27, 12
Code Models Reality




Friday, April 27, 12
Code Models Reality

                       • Move complexity closer to where it is in
                         real life




Friday, April 27, 12
Code Models Reality

                       • Move complexity closer to where it is in
                         real life
                       • If your CMDB contains lots of
                         exceptions, that’s where you should read
                         from




Friday, April 27, 12
Code Models Reality

                       • Move complexity closer to where it is in
                         real life
                       • If your CMDB contains lots of
                         exceptions, that’s where you should read
                         from
                       • If there is contorted logic, keep it away
                         from nuts and bolts module mechanics



Friday, April 27, 12
Please Don’t Make Me Edit
                   Your Module




Friday, April 27, 12
Parameterized Classes

                         class motd (
                           $pci_enabled = true,
                           $owner       = ‘bob’,
                         ) {
                           ...
                         }




Friday, April 27, 12
params.pp Pattern

                       class motd::params {
                         $owner = ‘Bob’
                       }

                       class motd (
                         $owner = $motd::params::owner
                       ) {



Friday, April 27, 12
params.pp Pattern +
                                hiera

                       class motd::params {
                         $owner = hiera(‘owner’,‘Bob’)
                       }

                       class motd (
                         $owner = $motd::params::owner
                       ) {



Friday, April 27, 12
Outsource Logic to
                          Submodules
    class mysql::params {
      $server_package = $::operatingsystem ? {
        ‘redhat’ => ‘mysql-server’,
        ...
      }
    }

    class mysql::server {
      package { ‘mysql-server’:
        name => $mysql::params::server_package,
        ...
      }
    }
Friday, April 27, 12
Be as Modular as
                           Possible
    class mysql::server {
      package { ‘mysql-server’:
        name => $mysql::params::server_package,
        ...
      }
    }
    class mysql::client {
      ...
    }
    class mysql {
      include mysql::client
      include mysql::server
    }
Friday, April 27, 12
Limit Inheritance




Friday, April 27, 12
Limit Inheritance




Friday, April 27, 12
Limit Inheritance

                       • Favor composition over inheritance




Friday, April 27, 12
Limit Inheritance

                       • Favor composition over inheritance
                       • Inheritance + dynamic variable scoping =
                         PAIN




Friday, April 27, 12
Limit Inheritance

                       • Favor composition over inheritance
                       • Inheritance + dynamic variable scoping =
                         PAIN
                       • Useful at the edges



Friday, April 27, 12
Limit Inheritance

                       • Favor composition over inheritance
                       • Inheritance + dynamic variable scoping =
                         PAIN
                       • Useful at the edges
                       • Useful for overriding/extending in limited
                         circumstances



Friday, April 27, 12
Stop Being Surprised by Change




Friday, April 27, 12
Stop Being Surprised by Change




Friday, April 27, 12
Stop Being Surprised by Change

                       • You don’t have to define every Operating
                         System or version




Friday, April 27, 12
Stop Being Surprised by Change

                       • You don’t have to define every Operating
                         System or version
                       • Assume cutovers won’t be clean - you
                         will be 50% RHEL 5 and 50% RHEL 6 for
                         a while




Friday, April 27, 12
Stop Being Surprised by Change

                       • You don’t have to define every Operating
                         System or version
                       • Assume cutovers won’t be clean - you
                         will be 50% RHEL 5 and 50% RHEL 6 for
                         a while
                       • And even when you aren’t, you’ll be 98%
                         RHEL 6 and 2% RHEL 5 until the end of
                         time.


Friday, April 27, 12
Protect Yourself Against
                        Unintentional Defaults




Friday, April 27, 12
Protect Yourself Against
                        Unintentional Defaults

                       • Always provide a default case




Friday, April 27, 12
Protect Yourself Against
                        Unintentional Defaults

                       • Always provide a default case
                       • In most cases that default case should be
                         failure




Friday, April 27, 12
Protect Yourself Against
                        Unintentional Defaults

                       • Always provide a default case
                       • In most cases that default case should be
                         failure

                       • Use the stdlib :fail method to fail
                         gracefully.




Friday, April 27, 12
Protect Yourself Against
                        Unintentional Defaults


    class mysql::params {
      case $::operatingsystem {
        ‘redhat’: { $serverpkg = ‘mysql-server’ }
        default: {
          fail(‘MySQL Server package undefined.’)
        }
      }
    }



Friday, April 27, 12
Remember
                       You Don’t Have To Think of
                              Everything




Friday, April 27, 12
Remember
                          You Don’t Have To Think of
                                 Everything

                       Leave room for others to improve your modules
                                 without refactoring them...




Friday, April 27, 12
Remember
                          You Don’t Have To Think of
                                 Everything

                       Leave room for others to improve your modules
                                 without refactoring them...

                       ...and then you get to benefit and re-merge their
                                     changes when they do.




Friday, April 27, 12
And then we haz a community!




Friday, April 27, 12
Thank You

                           Eric Shamow
                       eric@puppetlabs.com
                        http://opsrealist.info
                            @eshamow




Friday, April 27, 12

Puppet Module Writing 201

  • 1.
    Modules 201 Writing Flexible and Scalable Puppet Eric Shamow | PuppetCamp NYC Friday, April 27, 12
  • 2.
    Who Am I? • Senior Professional Services Engineer for Puppet Labs • Former Operations Manager • Recovering Sysadmin • Travel around helping people make Puppet even more awesome • Not Shamwow. If you came to the wrong talk you can leave now Friday, April 27, 12
  • 3.
    How Did WeGet Here? The module seemed just fine when I wrote it... Friday, April 27, 12
  • 4.
    How Did WeGet Here? The module seemed just fine when I wrote it... (I never thought RHEL 6 would come out) Friday, April 27, 12
  • 5.
  • 6.
    I never thought... • RHEL 6 would come out Friday, April 27, 12
  • 7.
    I never thought... • RHEL 6 would come out • My company would switch to Debian Friday, April 27, 12
  • 8.
    I never thought... • RHEL 6 would come out • My company would switch to Debian • Other people would want to reuse the module Friday, April 27, 12
  • 9.
    I never thought... • RHEL 6 would come out • My company would switch to Debian • Other people would want to reuse the module • I’d want to use only a part of the module Friday, April 27, 12
  • 10.
    I never thought... • RHEL 6 would come out • My company would switch to Debian • Other people would want to reuse the module • I’d want to use only a part of the module • ...maybe as a part of something else Friday, April 27, 12
  • 11.
    Ur Doin ItWrong Friday, April 27, 12
  • 12.
    Puppet is Declarative Shoehorning conditional logic into declarative language? Friday, April 27, 12
  • 13.
    Puppet is Declarative Shoehorning conditional logic into declarative language? Please do not do this: Friday, April 27, 12
  • 14.
    Puppet is Declarative Shoehorning conditional logic into declarative language? Please do not do this: case $::operatingsystem { ‘redhat’: { if $::fqdn == “bobmarley” { file { ‘foo’: ... } else { ... ... } Friday, April 27, 12
  • 15.
  • 16.
  • 17.
    Organizing Your Data • Hiera Friday, April 27, 12
  • 18.
    Organizing Your Data • Hiera • External Node Classifiers Friday, April 27, 12
  • 19.
    Organizing Your Data • Hiera • External Node Classifiers • Custom Functions Friday, April 27, 12
  • 20.
  • 21.
    Code Models Reality • Move complexity closer to where it is in real life Friday, April 27, 12
  • 22.
    Code Models Reality • Move complexity closer to where it is in real life • If your CMDB contains lots of exceptions, that’s where you should read from Friday, April 27, 12
  • 23.
    Code Models Reality • Move complexity closer to where it is in real life • If your CMDB contains lots of exceptions, that’s where you should read from • If there is contorted logic, keep it away from nuts and bolts module mechanics Friday, April 27, 12
  • 24.
    Please Don’t MakeMe Edit Your Module Friday, April 27, 12
  • 25.
    Parameterized Classes class motd ( $pci_enabled = true, $owner = ‘bob’, ) { ... } Friday, April 27, 12
  • 26.
    params.pp Pattern class motd::params { $owner = ‘Bob’ } class motd ( $owner = $motd::params::owner ) { Friday, April 27, 12
  • 27.
    params.pp Pattern + hiera class motd::params { $owner = hiera(‘owner’,‘Bob’) } class motd ( $owner = $motd::params::owner ) { Friday, April 27, 12
  • 28.
    Outsource Logic to Submodules class mysql::params { $server_package = $::operatingsystem ? { ‘redhat’ => ‘mysql-server’, ... } } class mysql::server { package { ‘mysql-server’: name => $mysql::params::server_package, ... } } Friday, April 27, 12
  • 29.
    Be as Modularas Possible class mysql::server { package { ‘mysql-server’: name => $mysql::params::server_package, ... } } class mysql::client { ... } class mysql { include mysql::client include mysql::server } Friday, April 27, 12
  • 30.
  • 31.
  • 32.
    Limit Inheritance • Favor composition over inheritance Friday, April 27, 12
  • 33.
    Limit Inheritance • Favor composition over inheritance • Inheritance + dynamic variable scoping = PAIN Friday, April 27, 12
  • 34.
    Limit Inheritance • Favor composition over inheritance • Inheritance + dynamic variable scoping = PAIN • Useful at the edges Friday, April 27, 12
  • 35.
    Limit Inheritance • Favor composition over inheritance • Inheritance + dynamic variable scoping = PAIN • Useful at the edges • Useful for overriding/extending in limited circumstances Friday, April 27, 12
  • 36.
    Stop Being Surprisedby Change Friday, April 27, 12
  • 37.
    Stop Being Surprisedby Change Friday, April 27, 12
  • 38.
    Stop Being Surprisedby Change • You don’t have to define every Operating System or version Friday, April 27, 12
  • 39.
    Stop Being Surprisedby Change • You don’t have to define every Operating System or version • Assume cutovers won’t be clean - you will be 50% RHEL 5 and 50% RHEL 6 for a while Friday, April 27, 12
  • 40.
    Stop Being Surprisedby Change • You don’t have to define every Operating System or version • Assume cutovers won’t be clean - you will be 50% RHEL 5 and 50% RHEL 6 for a while • And even when you aren’t, you’ll be 98% RHEL 6 and 2% RHEL 5 until the end of time. Friday, April 27, 12
  • 41.
    Protect Yourself Against Unintentional Defaults Friday, April 27, 12
  • 42.
    Protect Yourself Against Unintentional Defaults • Always provide a default case Friday, April 27, 12
  • 43.
    Protect Yourself Against Unintentional Defaults • Always provide a default case • In most cases that default case should be failure Friday, April 27, 12
  • 44.
    Protect Yourself Against Unintentional Defaults • Always provide a default case • In most cases that default case should be failure • Use the stdlib :fail method to fail gracefully. Friday, April 27, 12
  • 45.
    Protect Yourself Against Unintentional Defaults class mysql::params { case $::operatingsystem { ‘redhat’: { $serverpkg = ‘mysql-server’ } default: { fail(‘MySQL Server package undefined.’) } } } Friday, April 27, 12
  • 46.
    Remember You Don’t Have To Think of Everything Friday, April 27, 12
  • 47.
    Remember You Don’t Have To Think of Everything Leave room for others to improve your modules without refactoring them... Friday, April 27, 12
  • 48.
    Remember You Don’t Have To Think of Everything Leave room for others to improve your modules without refactoring them... ...and then you get to benefit and re-merge their changes when they do. Friday, April 27, 12
  • 49.
    And then wehaz a community! Friday, April 27, 12
  • 50.
    Thank You Eric Shamow [email protected] http://opsrealist.info @eshamow Friday, April 27, 12