SlideShare a Scribd company logo
RE-USEYOUR MODULES!
Techniques and Approaches to Modules Reusability
Puppet Camp 2010 San Francisco
Alessandro Franceschi
al@lab42.it
I have a dream
a small one
CrossVendor
Reusable
Plug & Play
Puppet
modules
CrossVendor
Reusable
Plug & Play
At the beginning...
class foo {
package { foo:
ensure => installed
}
service { foo:
ensure => running,
enable => true,
hasstatus => true,
require => Package[foo],
subscribe => File[foo.conf],
}
file { foo.conf:
ensure => present,
path => “/etc/foo.conf”,
mode => 644,
owner => root,
group => root,
source => “puppet:///foo/foo.conf”,
}
}
At the beginning
Facing Diversity
class foo {
package { foo:
ensure => installed,
name => $operatingsystem ? {
debian => “food”,
default => “foo”,
},
}
service { foo:
ensure => running,
name => $operatingsystem ? {
debian => “food”,
default => “foo”,
},
enable => true,
hasstatus => true,
require => Package[foo],
subscribe => File[foo.conf],
}
file { foo.conf:
ensure => present,
path => $operatingsystem ? {
debian => “/etc/foo/foo.conf”,
default => “/etc/foo.conf”,
},
mode => 644,
Facing Diversity
class foo {
package { foo:
ensure => installed
name => $operatingsystem ? {
debian => “food”,
default => “foo”,
}
}
service { foo:
ensure => running,
name => $operatingsystem ? {
debian => “food”,
default => “foo”,
},
enable => true,
hasstatus => $operatingsystem ? {
debian => false,
default => true,
},
pattern => “food”,
require => Package[foo],
subscribe => File[foo.conf],
}
file { foo.conf:
ensure => present,
path => $operatingsystem ? {
debian => “/etc/foo/foo.conf”,
default => “/etc/foo.conf”,
},
mode => 644,
Facing Diversity
package { foo:
ensure => installed
name => $operatingsystem ? {
debian => “food”,
ubuntu => “food”,
default => “foo”,
}
}
service { foo:
ensure => running,
name => $operatingsystem ? {
debian => “food”,
ubuntu => “food”,
default => “foo”,
},
enable => true,
hasstatus => $operatingsystem ? {
debian => false,
ubuntu => false,
default => true,
},
pattern => “food”,
require => Package[foo],
subscribe => File[foo.conf],
}
file { foo.conf:
ensure => present,
path => $operatingsystem ? {
debian => “/etc/foo/foo.conf”,
default => “/etc/foo.conf”,
Facing Diversity
Centralized settings: foo::params
Qualified variables
OS dedicated classes
Facing Diversity
Centralized settings
class foo::params {
$packagename = $operatingsystem ? {
debian => “food”,
ubuntu => “food”
default => "foo",
}
$servicename = $operatingsystem ? {
debian => “food”,
ubuntu => “food”,
default => “foo”,
},
$processname = $operatingsystem ? {
default => "food",
}
$hasstatus = $operatingsystem ? {
debian => false,
ubuntu => false,
default => true,
}
$configfile = $operatingsystem ? {
freebsd => "/usr/local/etc/foo.conf",
ubuntu => “/etc/foo/foo.conf",
Facing Diversity
Qualified variables
class foo {
require foo::params
package { "foo":
name => "${foo::params::packagename}",
ensure => present,
}
service { "foo":
name => "${foo::params::servicename}",
ensure => running,
enable => true,
hasstatus => "${foo::params::hasstatus}",
pattern => "${foo::params::processname}",
require => Package["foo"],
subscribe => File["foo.conf"],
}
file { "foo.conf":
path => "${foo::params::configfile}",
mode => "${foo::params::configfile_mode}",
owner => "${foo::params::configfile_owner}",
group => "${foo::params::configfile_group}",
ensure => present,
require => Package["foo"],
Facing Diversity
OS dedicated classes
class foo {
[ ... ]
# Include OS specific subclasses, if necessary
# Note that they needn’t to inherit foo
case $operatingsystem {
debian: { include foo::debian }
ubuntu: { include foo::debian }
default: { }
}
}
Facing Diversity
Dealing with Users
# foo class needs users’ variables
# IE: $foo_server
class foo {
[ ... ]
file { foo.conf:
ensure => present,
path => $operatingsystem ? {
debian => “/etc/foo/foo.conf”,
default => “/etc/foo.conf”,
},
mode => 644,
content => template(“foo/foo.conf.erb”),
}
}
# foo/templates/foo.conf.erb is something like:
# File Managed by Puppet
server = <%= foo_server %>
# Plug & Play ?
Dealing with Users
Filtering user variables
Setting default values
Dealing with Users
Setting default values
class foo::params {
# Full hostname of foo server
$server = $foo_server ? {
'' => "foo.example42.com",
default => "${foo_server}",
}
# Foo DB management
$db_host = $foo_db_host ? {
'' => "localhost",
default => "${foo_db_host}",
}
$db_user = $foo_db_user ? {
'' => "root",
default => "${foo_db_user}",
}
$db_password = $foo_db_password ? {
'' => "",
default => "${foo_db_host}",
}
Dealing with Users
Setting default values
class foo {
include foo::params
[ ... ]
# ${foo_server} is user variable unfiltered
# ${foo::params::server} is user variable filtered
# You may want/need to reassign ${foo_server} value:
${foo_server} = ${foo::params::server}
}
In templates this fails:
server = <%= foo::params::server %>
This works (of course):
server = <%= foo_server %>
This works (even if variable is not set):
server = <%= scope.lookupvar('foo::params::server') %>
Dealing with Users
Adapt and Customize
debian => “food”,
ubuntu => “food”,
default => “foo”,
},
enable => true,
hasstatus => $operatingsystem ? {
debian => false,
ubuntu => false,
default => true,
},
require => Package[foo],
subscribe => File[foo.conf],
}
file { foo.conf:
ensure => present,
path => “/etc/foo.conf”,
mode => 644,
owner => root,
group => root,
source => [ “puppet:///foo/foo.conf-$hostname”,
“puppet:///foo/foo.conf-$my_role”,
“puppet:///foo/foo.conf” ],
}
}
Adapt and customize
}
file { foo.conf:
ensure => present,
path => “/etc/foo.conf”,
mode => 644,
owner => root,
group => root,
source => [ “puppet:///foo/foo.conf-$hostname”,
“puppet:///foo/foo.conf-$my_role”,
“puppet:///foo/foo.conf” ],
}
case $my_role {
mail: {
file { foo.conf-mail:
ensure => present,
path => “/etc/foo.conf.d/mail”,
mode => 644,
owner => root,
group => root,
source => [ “puppet:///foo/foo.conf-mail”,
}
}
default: { }
}
Adapt and customize
Isolation of diversity
Project classes || Project module
Adapt and Customize
Isolation of diversity
# Class foo::example42
#
# You can use your custom project class to modify
# the standard behavior of foo module
#

# You don't need to use class inheritance if you
# don't override or redefine resources in foo class
#
# You can add custom resources and are free to
# decide how to provide the contents of your files:
# - Via static sourced files ( source => ) according
# to the naming convention you need
# - Via custom templates ( content => )
# - Via some kind of infile line modification tools
# such as Augeas
#
class foo::example42 inherits foo {
File["foo.conf"] {
source => [ "puppet:///foo/foo.conf-$hostname",
"puppet:///foo/foo.conf-$role",
"puppet:///foo/foo.conf" ],
}
}
Adapt and Customize
Project Classes ||
Project Modules
class foo {
[ ... ]
# Include project specific class if $my_project is set
# The extra project class is by default looked in foo module
# If $my_project_onmodule == yes it's looked in your project
# module
if $my_project {
case $my_project_onmodule {
yes,true: { include "${my_project}::foo" }
default: { include "foo::${my_project}" }
}
}
}
Adapt and Customize
Control and monitor
service { foo:
ensure => running,
name => $operatingsystem ? {
debian => “food”,
ubuntu => “food”,
default => “foo”,
},
enable => true,
hasstatus => $operatingsystem ? {
debian => false,
ubuntu => false,
default => true,
},
pattern => “food”,
require => Package[foo],
subscribe => File[foo.conf],
}
# Monitoring stuff: munin and nagios
munin::plugin { "foo_processes":
ensure => present,
}
nagios::service { "foo_${foo_port_real}":
check_command => "tcp_port!${foo_port_real}"
}
Control and Monitor
Monitoring abstraction
Monitor meta-module
Control and Monitor
Monitoring abstraction
class foo {
[ ... ]
# Include monitor classe if $monitor == yes
# Define the monitoring tools to use 

# with the variables $monitor_tools (can be an array)
if $monitor == "yes" { include foo::monitor }
}
Control and Monitor
Monitoring abstraction
class foo::monitor {
include foo::params
monitor::port { "foo_${foo::params::protocol}_

${foo::params::port}":
protocol => "${foo::params::protocol}",
target => "${foo::params::monitor_target_real}",
port => "${foo::params::port}",
enable => "${foo::params::monitor_port_enable}",
tool => "${monitor_tool}",
}
monitor::process { "foo_process":
process => "${foo::params::processname}",
service => "${foo::params::servicename}",
pidfile => "${foo::params::pidfile}",
enable => "${foo::params::monitor_process_enable}",
tool => "${monitor_tool}",
}
[ ... ]
if $my_project {
case $my_project_onmodule {
yes,true: { include "${my_project}::foo::monitor" }
default: { include "foo::monitor::${my_project}" }
Control and Monitor
Monitor Meta-module
define monitor::process ( $process, $service,
$pidfile, $tool, $enable ) {
if ($enable != "false") and ($enable != "no") {
if ($tool =~ /munin/) { # TODO }
if ($tool =~ /collectd/) { # TODO }
if ($tool =~ /monit/) {
monitor::process::monit { "$name":
pidfile => "$pidfile",
process => "$process",
service => "$service",
}
}
if ($tool =~ /nagios/) {
monitor::process::nagios { "$name":
process => $process,
}
}
} # End if $enable
}
Control and Monitor
Monitor Meta-module
define monitor::process::monit (
$pidfile='',
$process='',
$service=''
) {
# Use for Example42 monit module
monit::checkpid { "${process}":
pidfile => "${pidfile}",
startprogram => "/etc/init.d/${service} start",
stopprogram => "/etc/init.d/${service} stop",
}
# Use for Camptocamp’s monit module (sample)
# monit::config { "${process}":
# ensure => present,
# content => template(“monit/checkprocess.erb”), # To create
# }
# Use for Monit recipe on Puppet’s wiki (sample)
# monit::package { "${process}": }
}
Control and Monitor
Coherent naming conventions
Predictable behaviors
A name for Everything
Naming conventions
include foo - Installs and runs foo service


# If foo can be client or server
include foo::server - Installs foo server
include foo::client - Installs foo client
# If foo is on every/many host either client or server:
if ($foo_server_local == true) or ($foo_server == "$fqdn") {
include puppet::server
} else {
include puppet::client
}
# If foo has to be disable or removed:
include foo::absent - Remove foo

include foo::disable - Disable foo service
include foo::disableboot - Disable foo service but

do not check if is running
A name for Everything
Quick cloning & customization
Coherent Modules Infrastructure
Modules Machine
Quick cloning
# Few seds for a script that clones foo module
example42_module_clone.sh
# Creates new module from foo template. Then you:
# - Edit params.pp
# - Add specific classes, defines, types, facts
# - Eventually define modules variables and templates
#
# - Everything else is ready out of the box
Modules Machine
Quick customization
# Script that adapts a module for a new project
example42_project_rename.sh
# Prepares custom classes for new project
# foo/manifests/my_project.pp
# foo/manifests/monitor/my_project.pp
# foo/manifests/backup/my_project.pp
#
# - Use the logic that works for your project
# - Choose how to provide your configuration files
Modules Machine
Coherent Infrastructure
# Clone is GOOD
# Modules are similar
# They share a coherent naming convention

# They have confined places where to apply
# custom logic

# Fixed files for fixes functions
# Common approach for the Puppet team members
# Reduced risks and better manageability
# Quick update to template improvements
# Could be more easily manageable/autogenerated

# by GUI tools
Modules Machine
ReUse Your (Puppet) Modules!
Centralized settings:
foo::params
Qualified variables
Isolation of diversity
Project classes ||
Project module
Monitoring abstraction
Monitor meta-module
Filtering user variables
Setting default values
Coherent naming
conventions
Predictable behaviors
Quick cloning of foo
module
Quick customization
CrossVendor Reusable Plug & Play
Modules
Machine
A name for
Everything
Dealing
with Users
Control
and Monitor
Adapt and
Customize
Facing
Diversity
small dreams turn easier into reality
www.example42.com
github.com/example42/puppet-foo/
ReUse Your (Puppet) Modules!

More Related Content

PDF
Anatomy of a reusable module
PDF
Puppet @ Seat
PDF
Puppet modules for Fun and Profit
PDF
Power of Puppet 4
PDF
Puppi. Puppet strings to the shell
PDF
Oliver hookins puppetcamp2011
PPTX
Troubleshooting Puppet
PDF
Puppet Camp Paris 2015: Power of Puppet 4 (Beginner)
Anatomy of a reusable module
Puppet @ Seat
Puppet modules for Fun and Profit
Power of Puppet 4
Puppi. Puppet strings to the shell
Oliver hookins puppetcamp2011
Troubleshooting Puppet
Puppet Camp Paris 2015: Power of Puppet 4 (Beginner)

What's hot (20)

PDF
Doing It Wrong with Puppet -
PDF
Dependency Injection with PHP 5.3
PDF
The Puppet Debugging Kit: Building Blocks for Exploration and Problem Solving...
PDF
Symfony2 - WebExpo 2010
PDF
関西PHP勉強会 php5.4つまみぐい
PDF
Spl in the wild
KEY
DPC 2012 : PHP in the Dark Workshop
PDF
Replacing "exec" with a type and provider: Return manifests to a declarative ...
PDF
SPL to the Rescue - Tek 09
PDF
Memory Manglement in Raku
PDF
BSDM with BASH: Command Interpolation
PDF
BASH Variables Part 1: Basic Interpolation
PDF
Perforce Object and Record Model
PPTX
Php on the desktop and php gtk2
PDF
SPL: The Missing Link in Development
PPTX
Php on the Web and Desktop
ODP
Tutorial Puppet
PDF
Findbin libs
PDF
PECL Picks - Extensions to make your life better
PPT
Working with databases in Perl
Doing It Wrong with Puppet -
Dependency Injection with PHP 5.3
The Puppet Debugging Kit: Building Blocks for Exploration and Problem Solving...
Symfony2 - WebExpo 2010
関西PHP勉強会 php5.4つまみぐい
Spl in the wild
DPC 2012 : PHP in the Dark Workshop
Replacing "exec" with a type and provider: Return manifests to a declarative ...
SPL to the Rescue - Tek 09
Memory Manglement in Raku
BSDM with BASH: Command Interpolation
BASH Variables Part 1: Basic Interpolation
Perforce Object and Record Model
Php on the desktop and php gtk2
SPL: The Missing Link in Development
Php on the Web and Desktop
Tutorial Puppet
Findbin libs
PECL Picks - Extensions to make your life better
Working with databases in Perl
Ad

Similar to ReUse Your (Puppet) Modules! (20)

PDF
Alessandro sf 2010
PDF
PuppetCamp Ghent - What Not to Do with Puppet
PDF
Puppet: What _not_ to do
PDF
PuppetCamp Ghent - What Not to Do with Puppet
PDF
Puppetcamp module design talk
PDF
Puppet Camp LA 2015: Basic Puppet Module Design (Beginner)
PPTX
Creating beautiful puppet modules with puppet-lint
PDF
Puppet fundamentals
KEY
Puppet for Java developers - JavaZone NO 2012
PDF
Puppet Modules for Fun and Profit
PDF
Advanced symfony Techniques
PDF
20090514 Introducing Puppet To Sasag
PDF
Feeds drupal cafe
KEY
Kansai.pm 10周年記念 Plack/PSGI 入門
PPTX
Filesystem abstractions and msg queue sergeev - symfony camp 2018
KEY
How to simplify OSGi development using OBR - Peter Kriens
PDF
Puppet Camp Amsterdam 2015: Manifests of Future Past
PDF
Developing IT infrastructures with Puppet
PDF
Puppet: Eclipsecon ALM 2013
Alessandro sf 2010
PuppetCamp Ghent - What Not to Do with Puppet
Puppet: What _not_ to do
PuppetCamp Ghent - What Not to Do with Puppet
Puppetcamp module design talk
Puppet Camp LA 2015: Basic Puppet Module Design (Beginner)
Creating beautiful puppet modules with puppet-lint
Puppet fundamentals
Puppet for Java developers - JavaZone NO 2012
Puppet Modules for Fun and Profit
Advanced symfony Techniques
20090514 Introducing Puppet To Sasag
Feeds drupal cafe
Kansai.pm 10周年記念 Plack/PSGI 入門
Filesystem abstractions and msg queue sergeev - symfony camp 2018
How to simplify OSGi development using OBR - Peter Kriens
Puppet Camp Amsterdam 2015: Manifests of Future Past
Developing IT infrastructures with Puppet
Puppet: Eclipsecon ALM 2013
Ad

More from Alessandro Franceschi (16)

PDF
Strategies for Puppet code upgrade and refactoring
PDF
DevOps - Evoluzione della specie - DevOps Heroes.pdf
PDF
Tiny Puppet Can Install Everything. Prove me wrong!
PDF
Ten years of [Puppet] installations. What now?
PDF
Puppet Systems Infrastructure Construction Kit
PDF
Puppet Continuous Integration with PE and GitLab
PDF
Puppet control-repo 
to the next level
PDF
Tp install anything
PDF
Puppet: From 0 to 100 in 30 minutes
PDF
Puppet evolutions
PDF
Essential applications management with Tiny Puppet
PDF
Raise the bar! Reloaded
PDF
Raise the bar!
PDF
Puppet modules: A Holistic Approach - Geneva
PDF
Puppet modules: An Holistic Approach
PDF
Spaghetti devops
Strategies for Puppet code upgrade and refactoring
DevOps - Evoluzione della specie - DevOps Heroes.pdf
Tiny Puppet Can Install Everything. Prove me wrong!
Ten years of [Puppet] installations. What now?
Puppet Systems Infrastructure Construction Kit
Puppet Continuous Integration with PE and GitLab
Puppet control-repo 
to the next level
Tp install anything
Puppet: From 0 to 100 in 30 minutes
Puppet evolutions
Essential applications management with Tiny Puppet
Raise the bar! Reloaded
Raise the bar!
Puppet modules: A Holistic Approach - Geneva
Puppet modules: An Holistic Approach
Spaghetti devops

Recently uploaded (20)

PDF
Chapter 3 Spatial Domain Image Processing.pdf
PDF
cuic standard and advanced reporting.pdf
PDF
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
PDF
Bridging biosciences and deep learning for revolutionary discoveries: a compr...
PDF
How UI/UX Design Impacts User Retention in Mobile Apps.pdf
PPTX
Cloud computing and distributed systems.
PDF
Unlocking AI with Model Context Protocol (MCP)
PDF
NewMind AI Monthly Chronicles - July 2025
PDF
Reach Out and Touch Someone: Haptics and Empathic Computing
PDF
Spectral efficient network and resource selection model in 5G networks
PDF
KodekX | Application Modernization Development
PDF
GamePlan Trading System Review: Professional Trader's Honest Take
PDF
Mobile App Security Testing_ A Comprehensive Guide.pdf
PDF
Advanced Soft Computing BINUS July 2025.pdf
PDF
GDG Cloud Iasi [PUBLIC] Florian Blaga - Unveiling the Evolution of Cybersecur...
PDF
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
PDF
Dropbox Q2 2025 Financial Results & Investor Presentation
PDF
CIFDAQ's Market Insight: SEC Turns Pro Crypto
PDF
Shreyas Phanse Resume: Experienced Backend Engineer | Java • Spring Boot • Ka...
PPT
“AI and Expert System Decision Support & Business Intelligence Systems”
Chapter 3 Spatial Domain Image Processing.pdf
cuic standard and advanced reporting.pdf
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
Bridging biosciences and deep learning for revolutionary discoveries: a compr...
How UI/UX Design Impacts User Retention in Mobile Apps.pdf
Cloud computing and distributed systems.
Unlocking AI with Model Context Protocol (MCP)
NewMind AI Monthly Chronicles - July 2025
Reach Out and Touch Someone: Haptics and Empathic Computing
Spectral efficient network and resource selection model in 5G networks
KodekX | Application Modernization Development
GamePlan Trading System Review: Professional Trader's Honest Take
Mobile App Security Testing_ A Comprehensive Guide.pdf
Advanced Soft Computing BINUS July 2025.pdf
GDG Cloud Iasi [PUBLIC] Florian Blaga - Unveiling the Evolution of Cybersecur...
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
Dropbox Q2 2025 Financial Results & Investor Presentation
CIFDAQ's Market Insight: SEC Turns Pro Crypto
Shreyas Phanse Resume: Experienced Backend Engineer | Java • Spring Boot • Ka...
“AI and Expert System Decision Support & Business Intelligence Systems”

ReUse Your (Puppet) Modules!

  • 1. RE-USEYOUR MODULES! Techniques and Approaches to Modules Reusability Puppet Camp 2010 San Francisco Alessandro Franceschi al@lab42.it
  • 2. I have a dream a small one
  • 9. class foo { package { foo: ensure => installed } service { foo: ensure => running, enable => true, hasstatus => true, require => Package[foo], subscribe => File[foo.conf], } file { foo.conf: ensure => present, path => “/etc/foo.conf”, mode => 644, owner => root, group => root, source => “puppet:///foo/foo.conf”, } } At the beginning
  • 11. class foo { package { foo: ensure => installed, name => $operatingsystem ? { debian => “food”, default => “foo”, }, } service { foo: ensure => running, name => $operatingsystem ? { debian => “food”, default => “foo”, }, enable => true, hasstatus => true, require => Package[foo], subscribe => File[foo.conf], } file { foo.conf: ensure => present, path => $operatingsystem ? { debian => “/etc/foo/foo.conf”, default => “/etc/foo.conf”, }, mode => 644, Facing Diversity
  • 12. class foo { package { foo: ensure => installed name => $operatingsystem ? { debian => “food”, default => “foo”, } } service { foo: ensure => running, name => $operatingsystem ? { debian => “food”, default => “foo”, }, enable => true, hasstatus => $operatingsystem ? { debian => false, default => true, }, pattern => “food”, require => Package[foo], subscribe => File[foo.conf], } file { foo.conf: ensure => present, path => $operatingsystem ? { debian => “/etc/foo/foo.conf”, default => “/etc/foo.conf”, }, mode => 644, Facing Diversity
  • 13. package { foo: ensure => installed name => $operatingsystem ? { debian => “food”, ubuntu => “food”, default => “foo”, } } service { foo: ensure => running, name => $operatingsystem ? { debian => “food”, ubuntu => “food”, default => “foo”, }, enable => true, hasstatus => $operatingsystem ? { debian => false, ubuntu => false, default => true, }, pattern => “food”, require => Package[foo], subscribe => File[foo.conf], } file { foo.conf: ensure => present, path => $operatingsystem ? { debian => “/etc/foo/foo.conf”, default => “/etc/foo.conf”, Facing Diversity
  • 14. Centralized settings: foo::params Qualified variables OS dedicated classes Facing Diversity
  • 15. Centralized settings class foo::params { $packagename = $operatingsystem ? { debian => “food”, ubuntu => “food” default => "foo", } $servicename = $operatingsystem ? { debian => “food”, ubuntu => “food”, default => “foo”, }, $processname = $operatingsystem ? { default => "food", } $hasstatus = $operatingsystem ? { debian => false, ubuntu => false, default => true, } $configfile = $operatingsystem ? { freebsd => "/usr/local/etc/foo.conf", ubuntu => “/etc/foo/foo.conf", Facing Diversity
  • 16. Qualified variables class foo { require foo::params package { "foo": name => "${foo::params::packagename}", ensure => present, } service { "foo": name => "${foo::params::servicename}", ensure => running, enable => true, hasstatus => "${foo::params::hasstatus}", pattern => "${foo::params::processname}", require => Package["foo"], subscribe => File["foo.conf"], } file { "foo.conf": path => "${foo::params::configfile}", mode => "${foo::params::configfile_mode}", owner => "${foo::params::configfile_owner}", group => "${foo::params::configfile_group}", ensure => present, require => Package["foo"], Facing Diversity
  • 17. OS dedicated classes class foo { [ ... ] # Include OS specific subclasses, if necessary # Note that they needn’t to inherit foo case $operatingsystem { debian: { include foo::debian } ubuntu: { include foo::debian } default: { } } } Facing Diversity
  • 19. # foo class needs users’ variables # IE: $foo_server class foo { [ ... ] file { foo.conf: ensure => present, path => $operatingsystem ? { debian => “/etc/foo/foo.conf”, default => “/etc/foo.conf”, }, mode => 644, content => template(“foo/foo.conf.erb”), } } # foo/templates/foo.conf.erb is something like: # File Managed by Puppet server = <%= foo_server %> # Plug & Play ? Dealing with Users
  • 20. Filtering user variables Setting default values Dealing with Users
  • 21. Setting default values class foo::params { # Full hostname of foo server $server = $foo_server ? { '' => "foo.example42.com", default => "${foo_server}", } # Foo DB management $db_host = $foo_db_host ? { '' => "localhost", default => "${foo_db_host}", } $db_user = $foo_db_user ? { '' => "root", default => "${foo_db_user}", } $db_password = $foo_db_password ? { '' => "", default => "${foo_db_host}", } Dealing with Users
  • 22. Setting default values class foo { include foo::params [ ... ] # ${foo_server} is user variable unfiltered # ${foo::params::server} is user variable filtered # You may want/need to reassign ${foo_server} value: ${foo_server} = ${foo::params::server} } In templates this fails: server = <%= foo::params::server %> This works (of course): server = <%= foo_server %> This works (even if variable is not set): server = <%= scope.lookupvar('foo::params::server') %> Dealing with Users
  • 24. debian => “food”, ubuntu => “food”, default => “foo”, }, enable => true, hasstatus => $operatingsystem ? { debian => false, ubuntu => false, default => true, }, require => Package[foo], subscribe => File[foo.conf], } file { foo.conf: ensure => present, path => “/etc/foo.conf”, mode => 644, owner => root, group => root, source => [ “puppet:///foo/foo.conf-$hostname”, “puppet:///foo/foo.conf-$my_role”, “puppet:///foo/foo.conf” ], } } Adapt and customize
  • 25. } file { foo.conf: ensure => present, path => “/etc/foo.conf”, mode => 644, owner => root, group => root, source => [ “puppet:///foo/foo.conf-$hostname”, “puppet:///foo/foo.conf-$my_role”, “puppet:///foo/foo.conf” ], } case $my_role { mail: { file { foo.conf-mail: ensure => present, path => “/etc/foo.conf.d/mail”, mode => 644, owner => root, group => root, source => [ “puppet:///foo/foo.conf-mail”, } } default: { } } Adapt and customize
  • 26. Isolation of diversity Project classes || Project module Adapt and Customize
  • 27. Isolation of diversity # Class foo::example42 # # You can use your custom project class to modify # the standard behavior of foo module #
 # You don't need to use class inheritance if you # don't override or redefine resources in foo class # # You can add custom resources and are free to # decide how to provide the contents of your files: # - Via static sourced files ( source => ) according # to the naming convention you need # - Via custom templates ( content => ) # - Via some kind of infile line modification tools # such as Augeas # class foo::example42 inherits foo { File["foo.conf"] { source => [ "puppet:///foo/foo.conf-$hostname", "puppet:///foo/foo.conf-$role", "puppet:///foo/foo.conf" ], } } Adapt and Customize
  • 28. Project Classes || Project Modules class foo { [ ... ] # Include project specific class if $my_project is set # The extra project class is by default looked in foo module # If $my_project_onmodule == yes it's looked in your project # module if $my_project { case $my_project_onmodule { yes,true: { include "${my_project}::foo" } default: { include "foo::${my_project}" } } } } Adapt and Customize
  • 30. service { foo: ensure => running, name => $operatingsystem ? { debian => “food”, ubuntu => “food”, default => “foo”, }, enable => true, hasstatus => $operatingsystem ? { debian => false, ubuntu => false, default => true, }, pattern => “food”, require => Package[foo], subscribe => File[foo.conf], } # Monitoring stuff: munin and nagios munin::plugin { "foo_processes": ensure => present, } nagios::service { "foo_${foo_port_real}": check_command => "tcp_port!${foo_port_real}" } Control and Monitor
  • 32. Monitoring abstraction class foo { [ ... ] # Include monitor classe if $monitor == yes # Define the monitoring tools to use 
 # with the variables $monitor_tools (can be an array) if $monitor == "yes" { include foo::monitor } } Control and Monitor
  • 33. Monitoring abstraction class foo::monitor { include foo::params monitor::port { "foo_${foo::params::protocol}_
 ${foo::params::port}": protocol => "${foo::params::protocol}", target => "${foo::params::monitor_target_real}", port => "${foo::params::port}", enable => "${foo::params::monitor_port_enable}", tool => "${monitor_tool}", } monitor::process { "foo_process": process => "${foo::params::processname}", service => "${foo::params::servicename}", pidfile => "${foo::params::pidfile}", enable => "${foo::params::monitor_process_enable}", tool => "${monitor_tool}", } [ ... ] if $my_project { case $my_project_onmodule { yes,true: { include "${my_project}::foo::monitor" } default: { include "foo::monitor::${my_project}" } Control and Monitor
  • 34. Monitor Meta-module define monitor::process ( $process, $service, $pidfile, $tool, $enable ) { if ($enable != "false") and ($enable != "no") { if ($tool =~ /munin/) { # TODO } if ($tool =~ /collectd/) { # TODO } if ($tool =~ /monit/) { monitor::process::monit { "$name": pidfile => "$pidfile", process => "$process", service => "$service", } } if ($tool =~ /nagios/) { monitor::process::nagios { "$name": process => $process, } } } # End if $enable } Control and Monitor
  • 35. Monitor Meta-module define monitor::process::monit ( $pidfile='', $process='', $service='' ) { # Use for Example42 monit module monit::checkpid { "${process}": pidfile => "${pidfile}", startprogram => "/etc/init.d/${service} start", stopprogram => "/etc/init.d/${service} stop", } # Use for Camptocamp’s monit module (sample) # monit::config { "${process}": # ensure => present, # content => template(“monit/checkprocess.erb”), # To create # } # Use for Monit recipe on Puppet’s wiki (sample) # monit::package { "${process}": } } Control and Monitor
  • 36. Coherent naming conventions Predictable behaviors A name for Everything
  • 37. Naming conventions include foo - Installs and runs foo service 
 # If foo can be client or server include foo::server - Installs foo server include foo::client - Installs foo client # If foo is on every/many host either client or server: if ($foo_server_local == true) or ($foo_server == "$fqdn") { include puppet::server } else { include puppet::client } # If foo has to be disable or removed: include foo::absent - Remove foo
 include foo::disable - Disable foo service include foo::disableboot - Disable foo service but
 do not check if is running A name for Everything
  • 38. Quick cloning & customization Coherent Modules Infrastructure Modules Machine
  • 39. Quick cloning # Few seds for a script that clones foo module example42_module_clone.sh # Creates new module from foo template. Then you: # - Edit params.pp # - Add specific classes, defines, types, facts # - Eventually define modules variables and templates # # - Everything else is ready out of the box Modules Machine
  • 40. Quick customization # Script that adapts a module for a new project example42_project_rename.sh # Prepares custom classes for new project # foo/manifests/my_project.pp # foo/manifests/monitor/my_project.pp # foo/manifests/backup/my_project.pp # # - Use the logic that works for your project # - Choose how to provide your configuration files Modules Machine
  • 41. Coherent Infrastructure # Clone is GOOD # Modules are similar # They share a coherent naming convention
 # They have confined places where to apply # custom logic
 # Fixed files for fixes functions # Common approach for the Puppet team members # Reduced risks and better manageability # Quick update to template improvements # Could be more easily manageable/autogenerated
 # by GUI tools Modules Machine
  • 43. Centralized settings: foo::params Qualified variables Isolation of diversity Project classes || Project module Monitoring abstraction Monitor meta-module Filtering user variables Setting default values Coherent naming conventions Predictable behaviors Quick cloning of foo module Quick customization CrossVendor Reusable Plug & Play Modules Machine A name for Everything Dealing with Users Control and Monitor Adapt and Customize Facing Diversity small dreams turn easier into reality