Can you upgrade to 
Puppet 4.x? 
PuppetCamp Düsseldorf 
Martin Alfke 
<martin.alfke@buero20.org>
About me 
• Martin Alfke 
• Berlin/Germany 
• Freelancer / Trainer 
• PuppetLabs Training Partner 
• Puppet User Group Berlin
Poll 
! 
! 
• Using Puppet 2.x?
Poll 
! 
! 
• Using Puppet 2.x? 
• Using Puppet 3.x?
Agenda 
• Why upgrading at all? 
• Is your code still working? 
• How to upgrading Puppet? 
• What brings Puppet 4?
Why do I need to bother? 
• Fast releases 
• Best Practices 
• Changing functionality 
• Removing deprecated stuff 
• Puppet 4 is coming
Why should I upgrade 
Puppet at all? 
• Do you want security updates? 
• Do you want to make use of new functionality? 
(e.g. automatic data bindings, environmentpath, 
future parser) 
• Do you want to get support (community or 
enterprise)?
Is my Puppet DSL code still 
working on new versions? 
• Your code was developed some years 
ago and is still running unmodified 
• Your code was written on old best 
practices and does not follow new 
style guide 
• You do not check your Puppet runs 
for deprecation warnings (or do 
you?)
What to look for?
BAD 
Best practice 
• Do you inherit from inherited 
classes? 
• Do you still use import? 
• Do you modify remote modules? 
• Do you access non-local variables 
without scope names?
BAD 
Best practice 
Stop doing multiple levels of inheritance 
! 
class foo { 
} 
! 
class foo::bar inherits foo { 
} 
! 
class foo::baz inherits foo::bar { 
} 
! 
class foo::foobar inherits foo::baz { 
}
BAD 
Best practice 
Stop doing inheritance at all 
! 
class foo { 
} 
! 
class foo::bar inherits foo { 
} 
! 
class foo::baz inherits foo { 
} 
! 
class foo::foobar inherits foo { 
}
Best practice 
Restrict Inheritance 
! 
In most cases you can use parameterised classes instead. 
Only one kind of inheritance is proven good practice: inherit from 
module params.pp 
! 
class ssh ( 
$server = $ssh::params::server, 
$client = $ssh::params::client, 
$x11fwd = false, 
) inherits ssh::params { 
} 
! 
class { ssh::params:: 
server => false, 
x11fwd => true, 
} 
BETTER
BAD 
Best practice 
Stop importing 
! 
# foo/manifests/init.pp 
class foo { 
import ‘bar.pp’ 
} 
! 
# foo/manifests/bar.pp 
class foo::baz { 
} 
! 
# foo/manifests/baz.pp 
class foo::baz { 
} 
! 
Which class foo::baz will be used?
Best practice 
Use include 
! 
In most cases you can make use of the puppet autoloader and 
you can use include. 
! 
# foo/manifests/init.pp 
class foo { 
include foo::baz 
} 
BETTER 
! 
# foo/manifests/baz.pp 
class foo::baz { 
} 
!
BAD 
Best practice 
Stop modifying remote modules 
! 
Take “remote modules” as a software 
provided by others. 
Are you also patching apache?
Best practice 
Co-Work on remote 
modules 
! 
Do a PR if you want 
improvements. 
! 
Keep your remote modules 
upgradeable. 
BETTER
BAD 
Best practice 
Stop using non-local variables 
without scope 
! 
class foo ( 
$bar = ‘baz’ 
) { 
} 
! 
class foo::baz { 
notify { $bar: } 
}
Best practice 
Start using non-local variables with 
scope 
! 
class foo ( 
$bar 
) { 
} 
! 
class foo::baz { 
notify { $foo::bar: } 
} 
BETTER
Best practice 
Stop using un-scoped variables 
in templates 
!! 
key = <%= var %> 
! 
! 
! 
BAD
Best practice 
Start using scoped variables in 
templates 
!! 
key = <%= @var %> 
!!!! 
BETTER
BAD 
Best practice 
Stop using factor variables without top-scope 
! 
class foo { 
notify { “We are on OS: $operatingsystem”: } 
} 
! 
class foo::baz { 
if $is_virtual { 
notify { “We are running on $virtual virtualisation”: } 
} else { 
notify { “We are running on hardware: $productname”: } 
}
Best practice 
Start using factor variables with top-scope 
! 
class foo { 
notify { “We are on OS: ${::operatingsystem}”: } 
} 
! 
class foo::baz { 
if $::is_virtual { 
notify { “We are running on ${::virtual} virtualisation”: } 
} else { 
notify { “We are running on hardware: ${::productname}”: } 
} 
BETTER
BAD 
Best practice 
Stop not doing data validation 
! 
class foo ( 
$server = hiera(‘server’, ‘localhost’) 
){ 
notify { “We will use Server: ${server}”: } 
} 
!
Best practice 
BETTER 
Start doing data validation 
! 
class foo ( 
$server = hiera(‘server’, ‘localhost’) 
){ 
# validate_string is a function from stdlib 
validate_string($server) 
notify { “We will use Server: ${server}”: } 
} 
!
Remote modules 
• Do foreign modules support 
your version? 
• Newer Puppet versions have 
new function attributes (arity) 
• New foreign module versions 
might need newer modules 
not supported by your 
Puppet version
Remote modules 
• Check Puppetfile / 
metadata.json for 
requirements 
• Test prior upgrading in 
production
How can I test my actual 
Puppet DSL code?
How can I test my actual 
Puppet DSL code? 
• Syntax/Semantic check 
• puppet parser validate / puppet-syntax / puppet-lint 
• Unit test 
• rspec-puppet 
• Integration test 
• beaker, vagrant, serverspec,…
Simple rspec upgrade check
Simple rspec upgrade check 
• Add rspec tests to all your modules and run them 
locally 
• Use rvm or rbenv to choose between ruby 
versions 
• Provide puppet version to verify in Gemfile 
• Run spec tests locally and verify results
Automatic rspec upgrade 
check
Automatic rspec upgrade 
check 
• Install a CI-Server (Jenkins, 
GO, Teamcity,…) and add build 
steps 
• Add git commit hooks to 
identify changes in 
repositories 
• Run rspec tests automatically
Simple Puppet upgrade test
Simple Puppet upgrade test 
• Install Puppet tarball in a separate directory on 
your master 
• Start puppet master manually using RUBYLIB or 
ruby -I on another port (—masterport 8141) 
• Test run from a single node with —noop against 
the new port
Simple Puppet upgrade test 
Example: additional Puppet Master process: 
! 
tar zxf puppet-3.7.1.tar.gz -C /opt/puppet-3.7.1 
! 
ruby1.8 -I /opt/puppet-3.7.1/lib /opt/puppet-3.7.1/bin/puppet master  
—nodaemonize —masterport=8150 —pidfile=/tmp/puppetmaster.pid 
!! 
Example: Agent run against additional Puppet Master process: 
! 
puppet agent —test —masterport 8150
Demo
Puppet 4 
• Major update 
• Removes deprecated 
functionality 
• New language features
Puppet 4 
• Deprecated in Puppet 4: 
• node inheritance - use roles/profiles instead 
• upper case variable names 
• variable with underscore in first position 
• references to classes using upper case name/title 
• hypens and periods in names 
• Ruby DSL
Puppet 4 
• New in Puppet 4: 
• Strict variable naming and lookup (will become 
mandatory in Puppet 5) 
• Variable type validation 
• Boolean conversion (“” -> true instead of false) 
• Environmentpath 
• Functions in Puppet 
• New function API
You can upgrade to 
Puppet 4.x! 
! 
Thank you. 
! 
Martin Alfke 
<martin.alfke@buero20.org>

Can you upgrade to Puppet 4.x? (Beginner) Can you upgrade to Puppet 4.x? (Beginner) - Martin Alfke

  • 1.
    Can you upgradeto Puppet 4.x? PuppetCamp Düsseldorf Martin Alfke <martin.alfke@buero20.org>
  • 2.
    About me •Martin Alfke • Berlin/Germany • Freelancer / Trainer • PuppetLabs Training Partner • Puppet User Group Berlin
  • 3.
    Poll ! ! • Using Puppet 2.x?
  • 4.
    Poll ! ! • Using Puppet 2.x? • Using Puppet 3.x?
  • 5.
    Agenda • Whyupgrading at all? • Is your code still working? • How to upgrading Puppet? • What brings Puppet 4?
  • 6.
    Why do Ineed to bother? • Fast releases • Best Practices • Changing functionality • Removing deprecated stuff • Puppet 4 is coming
  • 7.
    Why should Iupgrade Puppet at all? • Do you want security updates? • Do you want to make use of new functionality? (e.g. automatic data bindings, environmentpath, future parser) • Do you want to get support (community or enterprise)?
  • 8.
    Is my PuppetDSL code still working on new versions? • Your code was developed some years ago and is still running unmodified • Your code was written on old best practices and does not follow new style guide • You do not check your Puppet runs for deprecation warnings (or do you?)
  • 9.
  • 10.
    BAD Best practice • Do you inherit from inherited classes? • Do you still use import? • Do you modify remote modules? • Do you access non-local variables without scope names?
  • 11.
    BAD Best practice Stop doing multiple levels of inheritance ! class foo { } ! class foo::bar inherits foo { } ! class foo::baz inherits foo::bar { } ! class foo::foobar inherits foo::baz { }
  • 12.
    BAD Best practice Stop doing inheritance at all ! class foo { } ! class foo::bar inherits foo { } ! class foo::baz inherits foo { } ! class foo::foobar inherits foo { }
  • 13.
    Best practice RestrictInheritance ! In most cases you can use parameterised classes instead. Only one kind of inheritance is proven good practice: inherit from module params.pp ! class ssh ( $server = $ssh::params::server, $client = $ssh::params::client, $x11fwd = false, ) inherits ssh::params { } ! class { ssh::params:: server => false, x11fwd => true, } BETTER
  • 14.
    BAD Best practice Stop importing ! # foo/manifests/init.pp class foo { import ‘bar.pp’ } ! # foo/manifests/bar.pp class foo::baz { } ! # foo/manifests/baz.pp class foo::baz { } ! Which class foo::baz will be used?
  • 15.
    Best practice Useinclude ! In most cases you can make use of the puppet autoloader and you can use include. ! # foo/manifests/init.pp class foo { include foo::baz } BETTER ! # foo/manifests/baz.pp class foo::baz { } !
  • 16.
    BAD Best practice Stop modifying remote modules ! Take “remote modules” as a software provided by others. Are you also patching apache?
  • 17.
    Best practice Co-Workon remote modules ! Do a PR if you want improvements. ! Keep your remote modules upgradeable. BETTER
  • 18.
    BAD Best practice Stop using non-local variables without scope ! class foo ( $bar = ‘baz’ ) { } ! class foo::baz { notify { $bar: } }
  • 19.
    Best practice Startusing non-local variables with scope ! class foo ( $bar ) { } ! class foo::baz { notify { $foo::bar: } } BETTER
  • 20.
    Best practice Stopusing un-scoped variables in templates !! key = <%= var %> ! ! ! BAD
  • 21.
    Best practice Startusing scoped variables in templates !! key = <%= @var %> !!!! BETTER
  • 22.
    BAD Best practice Stop using factor variables without top-scope ! class foo { notify { “We are on OS: $operatingsystem”: } } ! class foo::baz { if $is_virtual { notify { “We are running on $virtual virtualisation”: } } else { notify { “We are running on hardware: $productname”: } }
  • 23.
    Best practice Startusing factor variables with top-scope ! class foo { notify { “We are on OS: ${::operatingsystem}”: } } ! class foo::baz { if $::is_virtual { notify { “We are running on ${::virtual} virtualisation”: } } else { notify { “We are running on hardware: ${::productname}”: } } BETTER
  • 24.
    BAD Best practice Stop not doing data validation ! class foo ( $server = hiera(‘server’, ‘localhost’) ){ notify { “We will use Server: ${server}”: } } !
  • 25.
    Best practice BETTER Start doing data validation ! class foo ( $server = hiera(‘server’, ‘localhost’) ){ # validate_string is a function from stdlib validate_string($server) notify { “We will use Server: ${server}”: } } !
  • 26.
    Remote modules •Do foreign modules support your version? • Newer Puppet versions have new function attributes (arity) • New foreign module versions might need newer modules not supported by your Puppet version
  • 27.
    Remote modules •Check Puppetfile / metadata.json for requirements • Test prior upgrading in production
  • 28.
    How can Itest my actual Puppet DSL code?
  • 29.
    How can Itest my actual Puppet DSL code? • Syntax/Semantic check • puppet parser validate / puppet-syntax / puppet-lint • Unit test • rspec-puppet • Integration test • beaker, vagrant, serverspec,…
  • 30.
  • 31.
    Simple rspec upgradecheck • Add rspec tests to all your modules and run them locally • Use rvm or rbenv to choose between ruby versions • Provide puppet version to verify in Gemfile • Run spec tests locally and verify results
  • 32.
  • 33.
    Automatic rspec upgrade check • Install a CI-Server (Jenkins, GO, Teamcity,…) and add build steps • Add git commit hooks to identify changes in repositories • Run rspec tests automatically
  • 34.
  • 35.
    Simple Puppet upgradetest • Install Puppet tarball in a separate directory on your master • Start puppet master manually using RUBYLIB or ruby -I on another port (—masterport 8141) • Test run from a single node with —noop against the new port
  • 36.
    Simple Puppet upgradetest Example: additional Puppet Master process: ! tar zxf puppet-3.7.1.tar.gz -C /opt/puppet-3.7.1 ! ruby1.8 -I /opt/puppet-3.7.1/lib /opt/puppet-3.7.1/bin/puppet master —nodaemonize —masterport=8150 —pidfile=/tmp/puppetmaster.pid !! Example: Agent run against additional Puppet Master process: ! puppet agent —test —masterport 8150
  • 37.
  • 38.
    Puppet 4 •Major update • Removes deprecated functionality • New language features
  • 39.
    Puppet 4 •Deprecated in Puppet 4: • node inheritance - use roles/profiles instead • upper case variable names • variable with underscore in first position • references to classes using upper case name/title • hypens and periods in names • Ruby DSL
  • 40.
    Puppet 4 •New in Puppet 4: • Strict variable naming and lookup (will become mandatory in Puppet 5) • Variable type validation • Boolean conversion (“” -> true instead of false) • Environmentpath • Functions in Puppet • New function API
  • 41.
    You can upgradeto Puppet 4.x! ! Thank you. ! Martin Alfke <martin.alfke@buero20.org>