SlideShare a Scribd company logo
From Puppet 3 to 4:
Code Changes
A quick survey of the most common
code issues in the field, when
migrating Puppet code
from version three
to four
Gabriel M Schuyler
Professional Services, Puppet, Inc.
@gabe_sky
Introductions
Pro Services at Puppet
Assist in migrations
Dislike over-planning
Me You
Probably in operations ... yes?
Any level of experience
Need a quick heads-up
Hi there, I'm Gabe Schuyler. I work in Professional Services at Puppet, Inc.

I travel all around the world -- training, getting folks started, consulting. Lately I've been doing Puppet 3 to 4 migrations.

I'm in a hurry ... so I don't like analysis paralysis. Look ahead at what you're about to do, but don't go crazy with the what-if.

Show of hands -- who identifies themselves as "operations?" Does anyone still have "devops" on their business card?

For this talk, you don't need to be super-experienced. We're not going to look at anything all that complex.

You need to do things now. You're not doing anything fancy -- you just want some tips before you get started.
Puppet Server
All-In-One Agent packaging
Facter 3
Wait. Why am I upgrading?
There's not a lot of point upgrading something if it doesn't provide any advantage. Here are a few advantages.

The new "puppet server" for the Master vastly improves performance. Our tests say it handles 2.5x the Agents that Ruby-based
can.

"All in one" Agent packaging means no more vying with the system's version of components. For instance, it has Ruby 2.1.

Facter 3 is much faster, and returns structured facts, rather than just strings. These are hashes, and also are more strongly
typed.
Don't panic.
New features are opt-in.
Puppet 3 Agents abide Puppet 4 Masters.
Okay. Where do I start?
Our official docs have enormous lists of changes. You are not affected by most of these. I'm about to tell you what matters.

Things like iteration, or specifying the type of your class parameters are opt-in. Your Puppet 3 code can keep leaving them out.

Since code is compiled on the Master, you can keep using old Agents. They may get a catalog with extra data, but they'll ignore
it.

Okay. Let's get into some of the really simple things you're going to need to look out for in your code.
Numbers are Numbers
file { '/etc/motd':
ensure => file,
owner => 'root',
group => 'root',
mode => '0644',
}
Warning: Non-string values for the file mode property are
deprecated. It must be a string, either a symbolic mode
like 'o+w,a+r' or an octal representation like '0644' or
'755'.
Error: Parameter mode failed on File[/etc/motd]: The file
mode specification must be a string, not 'Fixnum' at line
1
3
4
Puppet 3 tends to pass values around as strings, so the provider would just incidentally get '0644' passed to it. 

Puppet 4 preserves more about the types of objects. One of those types, is numbers.

The most common case where this difference causes issues is with file resource modes.

Puppet 4 sees an unquoted number as an actual (octal) number.

The provider requires a string. Puppet 3 with future parser will issue a deprecation warning. Puppet 4 will fail because of the
type.

Only undef and false are actually false in Puppet 4.
Some code relies on empty strings to evaluate to false.
Try puppetlabs/stdlib str2bool( ) function.
Booleans
if ( '' ) {
notify { 'An empty string is true in Puppet 4': }
}
if ( str2bool('') == false ) {
notify { 'str2bool() always says an empty string is false': }
}
It used to be Puppet 3 would treat an empty string as false. Now only undefined or an actual boolean false are.

A common example where this causes trouble, is a custom fact that returns an empty string to indicate, generally, "not
applicable"

In their code they would simply evaluate the truth of the variable to decide if they needed to apply its value to something.
Lowercase your Variable Names
Puppet 3 allows variable names to start with capital letters.
Puppet 4 requires they start with lowercase alphabetical letter.
$Pkg_name = 'awesome-server'
package { $Pkg_name:
ensure => installed,
}
Error: Illegal variable name, The given name 'Pkg_name'
does not conform to the naming rule /^((::)?[a-z]
w*)*((::)?[a-z_]w*)$/ at /tmp/variables.pp:1:1
I don't see this one all that much, but it's out there, and will cause your catalog to fail compilation.
A Little More Esoteric
Regexps on Numbers
Class names with hyphens
Unquoted cases
Relative class declaration
ERB variables lacking @
class configure-me {
if ( $::memorysize_mb =~ /^1ddd/ ) {
notify { 'Looks like a small instance size.': }
}
case $::operatingsystem {
centos,redhat: { notify { 'I am RedHat-ish.': } }
debian: { include debian } # configure-me::debian
default: { notify { 'I do not have a hat.': } }
}
}
<%= @my_variable %>
Not so common, but worth mentioning, are a few more Puppet 4 differences. Here's a heads-up on five of them.

Passing things around internally as strings used to mean you could do a regexp on a number. No longer. This if statement would
fail.

(Though it's interesting to note that some facts that look like numbers, may be strings. For instance, version numbers like 6.5.1.)

Make sure you haven't used hyphens in class names. They are no longer allowed. This example class is no longer valid.

Also, the old behavior of an include first searching for a subclass under the current class no longer works. This is a good thing.

Not pictured here, you'll now get a warning (and likely the template generation will misbehave) if you don't have @variable.
Node inheritance no longer works.
Vestiges of Puppet 2 -- Nodes
node 'linux_base' {
include ssh
include selinux
include sudoers
}
node 'linux_exposed' inherits 'linux_base' {
include iptables
}

node 'web001.puppet.com' inherits 'linux_exposed' {
include apache
include apache::mod::php
}
It used to be a common design pattern to create node definitions that served only as templates that others would add on to.

For instance, this example is somewhat common. All Linux nodes inherit a fictitious node called linux_base.

This sometimes resulted in chains of inheritance that composed a node from an aggregation of node definitions.

This is no longer allowed. For an alternative, look at the Roles & Profiles design pattern.
Importing other manifests no longer works.
Vestiges of Puppet 2 -- Import
# site.pp
import nodes/*.pp
# environments/$environment/environment.conf
manifest = nodes
It used to be common that when site.pp got too large, you'd break it into smaller files and have site.pp import those.

Import no longer works.

However, for some time now, the "manifest" setting has been willing to take a whole directory as its setting.

And it defaults to reading the whole "manifests" directory, which on a base install just contains the site.pp file.

You likely won't need to change much, as it will recurse into subdirectories, which is where folks have be storing these already.

You can override where Puppet looks for manifests by changing an environment's "manifest" setting.
Structured facts
Typed facts
Old-style facts
System Gems
Facter 3
os => {
architecture => "x86_64",
family => "RedHat",
hardware => "x86_64",
name => "CentOS",
release => {
full => "7.2.1511",
major => "7",
minor => "2"
}
}
notify { "${::os['family']}": }
notify { "${::osfamily}": }
Facter 3, which is the one that the Puppet 4 installer will give you, is a little fancier than you might be used to.

Structured facts, for instance, are actual hashes of keys and values. To index a sub-item, use normal array indexing notation.

Facter 2 tended to represent facts as strings. Facter 3 is more aware of types. Test some agents with "stringify_facts" set to
false.

Structured facts are handy, but tons of code uses the old Facter 2 built-in facts. For the most part, 3 will return these if asked.

Note that if you have custom facts use Ruby gem/library, you'll need to make sure the new vendored Ruby has them as well.

By the way, Facter 3 is much faster than 2.
puppet parser validate
puppet-lint and plug-ins
zack/catalog_diff
puppetlabs/catalog_preview
Automatic Code Checks
It's valuable to know if Puppet 4 is going to compile your catalog at all, and also that it will compile a similar one to Puppet 3.

The most basic of test -- will it parse -- is easy to check on the command line with `puppet parser validate` .. probably in a for
loop.

One step up is to make sure the basic checklist (quoted modes, booleans) is done. There are puppet-lint plug-ins that will do
this.

Next up is to actually compile catalogs, for actual nodes in your environment. You've got two front-running choices here.

Zack's catalog_diff tool will actually talk to two masters, have them compile catalogs from nodes' last facts, and compare them.

The PuppetLabs catalog_preview tool uses a 3.8 Master, compiling catalogs in two environments where one has parser = future.

Please note. Neither of these tools actually applies a catalog to a node. So, for instance, a broken provider will not be revealed.
And that's all I've got.

Despite enormous lists of "breaking changes" my field experience says only a few of them usually crop up in the real world.

In just a few afternoons, you can get a pretty thorough impression of what it's going to take to migrate your code.

And I think you'll be surprised by how easy it's going to be.

I appreciate your attention, and now I welcome your questions.

More Related Content

ODP
biopython, doctest and makefiles
PPT
Phyton Learning extracts
PDF
Brogramming - Python, Bash for Data Processing, and Git
PPTX
Python Homework Help
PPTX
Using Rhino Mocks for Effective Unit Testing
PDF
The Sincerest Form of Flattery
PPTX
The Sincerest Form of Flattery
PPT
Introduction To Python
biopython, doctest and makefiles
Phyton Learning extracts
Brogramming - Python, Bash for Data Processing, and Git
Python Homework Help
Using Rhino Mocks for Effective Unit Testing
The Sincerest Form of Flattery
The Sincerest Form of Flattery
Introduction To Python

What's hot (14)

PPTX
Computer Science Homework Help
ODP
Python 3000
PDF
cs3157-summer06-lab1
PPT
Introduction to Python - Part Three
PDF
Implementing a decorator for thread synchronisation.
PDF
Python cheat-sheet
PDF
Perl intro
KEY
Your Own Metric System
ODP
Introduction to Python - Training for Kids
PDF
Perl_Part4
PDF
Playfulness at Work
PPT
typemap in Perl/XS
PDF
Thnad's Revenge
PDF
Write Your Own JVM Compiler
Computer Science Homework Help
Python 3000
cs3157-summer06-lab1
Introduction to Python - Part Three
Implementing a decorator for thread synchronisation.
Python cheat-sheet
Perl intro
Your Own Metric System
Introduction to Python - Training for Kids
Perl_Part4
Playfulness at Work
typemap in Perl/XS
Thnad's Revenge
Write Your Own JVM Compiler
Ad

Similar to Migrating Puppet 3 to 4 -- Code Changes (20)

PDF
20_Python_Libraries_You_Aren't_Using_But_Should.pdf
PDF
10 things you're doing wrong in Talend
PDF
10 things you're doing wrong in Talend
PDF
Puppet Camp Paris 2014: Test Driven Development
PDF
20140408 tdd puppetcamp-paris
PDF
Learning puppet chapter 2
PPTX
Ot performance webinar
PPTX
Php extensions
PDF
Introduction to Writing Readable and Maintainable Perl (YAPC::EU 2011 Version)
PDF
Introduction to writing readable and maintainable Perl
PPTX
How to build your own OpenStack distro using Puppet OpenStack
PDF
Good Coding Practices with JavaScript
PDF
Code with style
PDF
Intermediate python
PDF
HPC and HPGPU Cluster Tutorial
PDF
CS225_Prelecture_Notes 2nd
PDF
Python Interview Questions And Answers
PDF
INTRODUCTION TO MACHINE LEARNING FOR MATERIALS SCIENCE
PDF
Code with Style - PyOhio
PPTX
Functions in Python Syntax and working .
20_Python_Libraries_You_Aren't_Using_But_Should.pdf
10 things you're doing wrong in Talend
10 things you're doing wrong in Talend
Puppet Camp Paris 2014: Test Driven Development
20140408 tdd puppetcamp-paris
Learning puppet chapter 2
Ot performance webinar
Php extensions
Introduction to Writing Readable and Maintainable Perl (YAPC::EU 2011 Version)
Introduction to writing readable and maintainable Perl
How to build your own OpenStack distro using Puppet OpenStack
Good Coding Practices with JavaScript
Code with style
Intermediate python
HPC and HPGPU Cluster Tutorial
CS225_Prelecture_Notes 2nd
Python Interview Questions And Answers
INTRODUCTION TO MACHINE LEARNING FOR MATERIALS SCIENCE
Code with Style - PyOhio
Functions in Python Syntax and working .
Ad

More from Gabriel Schuyler (14)

PDF
2024 Kernelcon Attack and Defense of AI.pdf
PDF
2023 BSides ATX Trending Attack and Defense.pdf
PDF
Trends in Cloud Security Attack & Defense
PDF
Pancakes Con 4 Trends in Cloud Security & Fun Facts about Real Clouds
PDF
Automating Security Tests in Development with Docker
PDF
2022 GrrCON Shifting Right with Policy as Code.pdf
PDF
Texas Cyber Summit 2022: Challenges Securing Cloud-Native.pdf
PDF
Dog Days of Devops 2022: Policy as Code
PDF
fwd:cloudsec 2022: Shifting right with policy-as-code
PDF
Hope 2022: Just Enough RFID Cloning to be Dangerous
PDF
Kernel Con 2022: Securing Cloud Native Workloads
PPTX
ShmooCon 2022: RFID Key Cloning for Angry Bikers
PDF
Cybersecurity in 2022
PDF
IC3 -- Configuration Management 101
2024 Kernelcon Attack and Defense of AI.pdf
2023 BSides ATX Trending Attack and Defense.pdf
Trends in Cloud Security Attack & Defense
Pancakes Con 4 Trends in Cloud Security & Fun Facts about Real Clouds
Automating Security Tests in Development with Docker
2022 GrrCON Shifting Right with Policy as Code.pdf
Texas Cyber Summit 2022: Challenges Securing Cloud-Native.pdf
Dog Days of Devops 2022: Policy as Code
fwd:cloudsec 2022: Shifting right with policy-as-code
Hope 2022: Just Enough RFID Cloning to be Dangerous
Kernel Con 2022: Securing Cloud Native Workloads
ShmooCon 2022: RFID Key Cloning for Angry Bikers
Cybersecurity in 2022
IC3 -- Configuration Management 101

Recently uploaded (20)

PDF
System and Network Administraation Chapter 3
PDF
Raksha Bandhan Grocery Pricing Trends in India 2025.pdf
PDF
How to Migrate SBCGlobal Email to Yahoo Easily
PDF
Softaken Excel to vCard Converter Software.pdf
PPTX
Reimagine Home Health with the Power of Agentic AI​
PDF
Upgrade and Innovation Strategies for SAP ERP Customers
PPTX
L1 - Introduction to python Backend.pptx
PDF
Internet Downloader Manager (IDM) Crack 6.42 Build 41
PDF
top salesforce developer skills in 2025.pdf
PDF
Design an Analysis of Algorithms II-SECS-1021-03
PDF
Internet Downloader Manager (IDM) Crack 6.42 Build 42 Updates Latest 2025
PPTX
Operating system designcfffgfgggggggvggggggggg
PDF
Adobe Illustrator 28.6 Crack My Vision of Vector Design
PPTX
Odoo POS Development Services by CandidRoot Solutions
PDF
Audit Checklist Design Aligning with ISO, IATF, and Industry Standards — Omne...
PDF
Which alternative to Crystal Reports is best for small or large businesses.pdf
PDF
wealthsignaloriginal-com-DS-text-... (1).pdf
PPTX
Agentic AI : A Practical Guide. Undersating, Implementing and Scaling Autono...
PDF
2025 Textile ERP Trends: SAP, Odoo & Oracle
PPTX
Oracle E-Business Suite: A Comprehensive Guide for Modern Enterprises
System and Network Administraation Chapter 3
Raksha Bandhan Grocery Pricing Trends in India 2025.pdf
How to Migrate SBCGlobal Email to Yahoo Easily
Softaken Excel to vCard Converter Software.pdf
Reimagine Home Health with the Power of Agentic AI​
Upgrade and Innovation Strategies for SAP ERP Customers
L1 - Introduction to python Backend.pptx
Internet Downloader Manager (IDM) Crack 6.42 Build 41
top salesforce developer skills in 2025.pdf
Design an Analysis of Algorithms II-SECS-1021-03
Internet Downloader Manager (IDM) Crack 6.42 Build 42 Updates Latest 2025
Operating system designcfffgfgggggggvggggggggg
Adobe Illustrator 28.6 Crack My Vision of Vector Design
Odoo POS Development Services by CandidRoot Solutions
Audit Checklist Design Aligning with ISO, IATF, and Industry Standards — Omne...
Which alternative to Crystal Reports is best for small or large businesses.pdf
wealthsignaloriginal-com-DS-text-... (1).pdf
Agentic AI : A Practical Guide. Undersating, Implementing and Scaling Autono...
2025 Textile ERP Trends: SAP, Odoo & Oracle
Oracle E-Business Suite: A Comprehensive Guide for Modern Enterprises

Migrating Puppet 3 to 4 -- Code Changes

  • 1. From Puppet 3 to 4: Code Changes A quick survey of the most common code issues in the field, when migrating Puppet code from version three to four Gabriel M Schuyler Professional Services, Puppet, Inc. @gabe_sky Introductions Pro Services at Puppet Assist in migrations Dislike over-planning Me You Probably in operations ... yes? Any level of experience Need a quick heads-up Hi there, I'm Gabe Schuyler. I work in Professional Services at Puppet, Inc. I travel all around the world -- training, getting folks started, consulting. Lately I've been doing Puppet 3 to 4 migrations. I'm in a hurry ... so I don't like analysis paralysis. Look ahead at what you're about to do, but don't go crazy with the what-if. Show of hands -- who identifies themselves as "operations?" Does anyone still have "devops" on their business card? For this talk, you don't need to be super-experienced. We're not going to look at anything all that complex. You need to do things now. You're not doing anything fancy -- you just want some tips before you get started. Puppet Server All-In-One Agent packaging Facter 3 Wait. Why am I upgrading? There's not a lot of point upgrading something if it doesn't provide any advantage. Here are a few advantages. The new "puppet server" for the Master vastly improves performance. Our tests say it handles 2.5x the Agents that Ruby-based can. "All in one" Agent packaging means no more vying with the system's version of components. For instance, it has Ruby 2.1. Facter 3 is much faster, and returns structured facts, rather than just strings. These are hashes, and also are more strongly typed.
  • 2. Don't panic. New features are opt-in. Puppet 3 Agents abide Puppet 4 Masters. Okay. Where do I start? Our official docs have enormous lists of changes. You are not affected by most of these. I'm about to tell you what matters. Things like iteration, or specifying the type of your class parameters are opt-in. Your Puppet 3 code can keep leaving them out. Since code is compiled on the Master, you can keep using old Agents. They may get a catalog with extra data, but they'll ignore it. Okay. Let's get into some of the really simple things you're going to need to look out for in your code. Numbers are Numbers file { '/etc/motd': ensure => file, owner => 'root', group => 'root', mode => '0644', } Warning: Non-string values for the file mode property are deprecated. It must be a string, either a symbolic mode like 'o+w,a+r' or an octal representation like '0644' or '755'. Error: Parameter mode failed on File[/etc/motd]: The file mode specification must be a string, not 'Fixnum' at line 1 3 4 Puppet 3 tends to pass values around as strings, so the provider would just incidentally get '0644' passed to it. Puppet 4 preserves more about the types of objects. One of those types, is numbers. The most common case where this difference causes issues is with file resource modes. Puppet 4 sees an unquoted number as an actual (octal) number. The provider requires a string. Puppet 3 with future parser will issue a deprecation warning. Puppet 4 will fail because of the type. Only undef and false are actually false in Puppet 4. Some code relies on empty strings to evaluate to false. Try puppetlabs/stdlib str2bool( ) function. Booleans if ( '' ) { notify { 'An empty string is true in Puppet 4': } } if ( str2bool('') == false ) { notify { 'str2bool() always says an empty string is false': } } It used to be Puppet 3 would treat an empty string as false. Now only undefined or an actual boolean false are. A common example where this causes trouble, is a custom fact that returns an empty string to indicate, generally, "not applicable" In their code they would simply evaluate the truth of the variable to decide if they needed to apply its value to something.
  • 3. Lowercase your Variable Names Puppet 3 allows variable names to start with capital letters. Puppet 4 requires they start with lowercase alphabetical letter. $Pkg_name = 'awesome-server' package { $Pkg_name: ensure => installed, } Error: Illegal variable name, The given name 'Pkg_name' does not conform to the naming rule /^((::)?[a-z] w*)*((::)?[a-z_]w*)$/ at /tmp/variables.pp:1:1 I don't see this one all that much, but it's out there, and will cause your catalog to fail compilation. A Little More Esoteric Regexps on Numbers Class names with hyphens Unquoted cases Relative class declaration ERB variables lacking @ class configure-me { if ( $::memorysize_mb =~ /^1ddd/ ) { notify { 'Looks like a small instance size.': } } case $::operatingsystem { centos,redhat: { notify { 'I am RedHat-ish.': } } debian: { include debian } # configure-me::debian default: { notify { 'I do not have a hat.': } } } } <%= @my_variable %> Not so common, but worth mentioning, are a few more Puppet 4 differences. Here's a heads-up on five of them. Passing things around internally as strings used to mean you could do a regexp on a number. No longer. This if statement would fail. (Though it's interesting to note that some facts that look like numbers, may be strings. For instance, version numbers like 6.5.1.) Make sure you haven't used hyphens in class names. They are no longer allowed. This example class is no longer valid. Also, the old behavior of an include first searching for a subclass under the current class no longer works. This is a good thing. Not pictured here, you'll now get a warning (and likely the template generation will misbehave) if you don't have @variable. Node inheritance no longer works. Vestiges of Puppet 2 -- Nodes node 'linux_base' { include ssh include selinux include sudoers } node 'linux_exposed' inherits 'linux_base' { include iptables }
 node 'web001.puppet.com' inherits 'linux_exposed' { include apache include apache::mod::php } It used to be a common design pattern to create node definitions that served only as templates that others would add on to. For instance, this example is somewhat common. All Linux nodes inherit a fictitious node called linux_base. This sometimes resulted in chains of inheritance that composed a node from an aggregation of node definitions. This is no longer allowed. For an alternative, look at the Roles & Profiles design pattern.
  • 4. Importing other manifests no longer works. Vestiges of Puppet 2 -- Import # site.pp import nodes/*.pp # environments/$environment/environment.conf manifest = nodes It used to be common that when site.pp got too large, you'd break it into smaller files and have site.pp import those. Import no longer works. However, for some time now, the "manifest" setting has been willing to take a whole directory as its setting. And it defaults to reading the whole "manifests" directory, which on a base install just contains the site.pp file. You likely won't need to change much, as it will recurse into subdirectories, which is where folks have be storing these already. You can override where Puppet looks for manifests by changing an environment's "manifest" setting. Structured facts Typed facts Old-style facts System Gems Facter 3 os => { architecture => "x86_64", family => "RedHat", hardware => "x86_64", name => "CentOS", release => { full => "7.2.1511", major => "7", minor => "2" } } notify { "${::os['family']}": } notify { "${::osfamily}": } Facter 3, which is the one that the Puppet 4 installer will give you, is a little fancier than you might be used to. Structured facts, for instance, are actual hashes of keys and values. To index a sub-item, use normal array indexing notation. Facter 2 tended to represent facts as strings. Facter 3 is more aware of types. Test some agents with "stringify_facts" set to false. Structured facts are handy, but tons of code uses the old Facter 2 built-in facts. For the most part, 3 will return these if asked. Note that if you have custom facts use Ruby gem/library, you'll need to make sure the new vendored Ruby has them as well. By the way, Facter 3 is much faster than 2. puppet parser validate puppet-lint and plug-ins zack/catalog_diff puppetlabs/catalog_preview Automatic Code Checks It's valuable to know if Puppet 4 is going to compile your catalog at all, and also that it will compile a similar one to Puppet 3. The most basic of test -- will it parse -- is easy to check on the command line with `puppet parser validate` .. probably in a for loop. One step up is to make sure the basic checklist (quoted modes, booleans) is done. There are puppet-lint plug-ins that will do this. Next up is to actually compile catalogs, for actual nodes in your environment. You've got two front-running choices here. Zack's catalog_diff tool will actually talk to two masters, have them compile catalogs from nodes' last facts, and compare them. The PuppetLabs catalog_preview tool uses a 3.8 Master, compiling catalogs in two environments where one has parser = future. Please note. Neither of these tools actually applies a catalog to a node. So, for instance, a broken provider will not be revealed.
  • 5. And that's all I've got. Despite enormous lists of "breaking changes" my field experience says only a few of them usually crop up in the real world. In just a few afternoons, you can get a pretty thorough impression of what it's going to take to migrate your code. And I think you'll be surprised by how easy it's going to be. I appreciate your attention, and now I welcome your questions.