SlideShare una empresa de Scribd logo
1 de 50
Descargar para leer sin conexión
Anatomy of a
Reusable Module
Alessandro Franceschi
github.com/example42
PuppetConf 2013
Be
 patient
please
How
 do
we
 use
Puppet
today?
Include classes
Set Params 
Variables
Define
Business 
Integration Logic
Provide
Configuration Files
Manage
Resources
How do we use Puppet today
Include classes
manifests/
site.pp
Set Parameters / Variables
Integration logic
Resources
ENC HIERA
SITE
MODULES
SHARED
MODULES
BAD
EDGE
Configuration files
manifests/
site.pp
ENC HIERA
manifests/
site.pp
BAD?
BAD?
BAD
SITE
MODULES
SITE
MODULES
SHARED
MODULES
SITE
MODULES
SHARED
MODULES
manifests/
site.pp
BAD?
ENC
BAD?
A
 reusable
 
module
is
 all
 about
CHOICE
Operating Systems
Infrastructures
Scales
Node classifiers
Installation methods
Alternative setups
The
 cons
of
 a
reusable
module
Harder  Longer
Development
Complexity
Verbosity
Not Optimized for
performance
THE PARAMETERS
DILEMMA
Managed resources attributes
Application specific config options
Application logic and behaviour
Integration with other modules
Parameters: Resources attributes
Enough:
$package = $redis::params::package,
$service = $redis::params::service,
$service_ensure = 'running',
$service_enable = true,
$file = $redis::params::file,
$file_notify = Service['redis'],
$file_source = undef,
$file_content = undef,
Too much?
$package_provider = undef,
$file_owner = $redis::params::file_owner,
$file_group = $redis::params::file_group,
$file_mode = $redis::params::file_mode,
$file_replace = $redis::params::file_replace,
Benefits from: A standard naming convention
Parameters: Application options
Enough:
$puppet_server = “puppet.${::domain}”,
$syslog_server = “syslog.${::domain}”,
$munin_server = “munin.${::domain}”,
$dns_servers = [ '8.8.8.8' , '8.8.4.4' ],
Too much!
$anonymous_enable = true,
$anon_mkdir_write_enable = true,
$anon_upload_enable = false,
$chroot_list_enable = true,
$chroot_list_file = '/etc/vsftpd/chroot_list',
$resourcefile = $nagios::params::resourcefile,
$statusfile = $nagios::params::statusfile,
$commandfile = $nagios::params::commandfile,
$resultpath = $nagios::params::resultpath,
$retentionfile = $nagios::params::retentionfile,
$p1file = $nagios::params::p1file,
Benefits from: Template + Options Hash pattern
Parameters: Application logic
Examples:
$install_client = true,
$install_stomp_server = true,
$install_plugins = true,
$use_ssl = false,
$munin_autoconfigure = true,
$service_autorestart = true,
$manage_package_repo = true,
$run_initdb = undef,
Benefits from: A standard naming convention
Parameters: Modules Integrations
Examples:
$mongo_db_host = $graylog2::params::mongo_db_host,
$mongo_db_port = $graylog2::params::mongo_db_port,
$mongo_db_name = $graylog2::params::mongo_db_name,
$mongo_user = $graylog2::params::mongo_user,
$mongo_password = $graylog2::params::mongo_password,
$elasticsearch_template = $graylog2::params::elasticsearch_template,
$elasticsearch_path = $graylog2::params::elasticsearch_path,
$database = $puppetdb::params::database,
$manage_redhat_firewall = $puppetdb::params::manage_redhat_firewall,
$db_type = 'mysql',
Benefits from: Shared Stacks
PATTERNS
REUSABILITY
Managing
 
files
Let user decide how
to manage
configuration files.
Alternatives:
source
content
concat
augeas
custom types
Managing files: source  content
redis/manifests/init.pp
class redis (
$file = $redis::params::file,
$file_source = undef,
$file_template = undef,
$file_content = undef,
) {
[...]
$managed_file_content = $file_content ? {
undef = $file_template ? {
undef = undef,
default = template($file_template),
},
default = $file_content,
}
[...]
if $redis::file {
file { 'redis.conf':
path = $redis::file,
source = $redis::file_source,
content = $redis::managed_file_content,
}
}
}
Provide the Puppet path of an erb template
class { ‘redis’:
file_template = ‘site/redis/
redis.conf.erb’,
}
Provide directly the content attribute
class { ‘redis’:
file_content = “template(‘site/redis/
redis.conf.erb’)”,
}
Provide a fileserver source path
class { ‘redis’:
file_source = ‘puppet:///modules/site/
redis/redis.conf’,
}
Manage the configuration file with other methods
(augeas, concat...)
class { ‘redis’: }
Multiple
 
config
 files
 
Add parameters
to main class
Use a generic
conf define
Manage the whole
configuration dir
Multiple files: Add parameters
elasticsearch/manifests/init.pp
class elasticsearch (
$file = $elasticsearch::params::file,
$file_source = undef,
$file_template = undef,
$file_content = undef,
[...]
$init_script_file = '/etc/init.d/elasticsearch',
$init_script_file_template = 'elasticsearch/init.erb',
$init_options_file = $elasticsearch::params::init_options_file,
$init_options_file_template = 'elasticsearch/init_options.erb',
Provide custom templates for the main file and the init script
class { ‘elasticsearch’:
file_template = ‘site/elasticsearch/elasticsearch.yml.erb’,
init_script_file_template = ‘site/elasticsearch/elasticsearch.init.erb’,
}
Multiple files: Generic conf define
nova/manifests/conf.pp
define nova::conf (
$source = undef,
$template = undef,
$content = undef,
$path = undef,
[...]
$options_hash = undef,
$ensure = present ) {
include nova
$managed_path = $path ? {
undef = ${nova::config_dir}/${name},
default = $path,
}
[...]
file { nova_conf_${name}:
ensure = $ensure,
source = $source,
content = $managed_content,
path = $managed_path,
mode = $managed_mode,
owner = $managed_owner,
group = $managed_group,
require = $managed_require,
notify = $managed_notify,
replace = $managed_replace,
}
}
Provide a custom template for an alternative config file in config_dir
nova::conf { ‘rootwrap.conf’:
template = ‘site/nova/rootwrap.conf.erb’,
}
Multiple files: Whole config dir
redis/manifests/init.pp
class redis (
$dir = $redis::params::dir,
$dir_source = undef,
$dir_purge = false,
$dir_recurse = true,
) {
[...]
$dir_ensure = $ensure ? {
'absent' = 'absent',
'present' = 'directory',
}
if $redis::dir_source {
file { 'redis.dir':
ensure = $redis::dir_ensure,
path = $redis::dir,
source = $redis::dir_source,
recurse = $redis::dir_recurse,
purge = $redis::dir_purge,
force = $redis::dir_purge,
notify = $redis::file_notify,
require = $redis::file_require,
}
}
}
Provide a custom source for the whole config_dir
class { ‘redis’:
dir_source = ‘puppet:///modules/site/redis/conf/’,
}
Provide a custom source for the whole config_dir and purge any
not managed config file
class { ‘redis’:
dir_source = ‘puppet:///modules/site/redis/conf/’,
dir_purge = true,
}
Managing
 
Users
Everyone has his
own users...
Leave options to
decide
if, how and where to
manage the ones
the module requires.
Managing Users
elasticsearch/manifests/init.pp
class elasticsearch {
$ensure = 'present',
[...]
$user = 'elasticsearch',
$user_uid = undef,
$user_gid = undef,
$user_groups = undef,
$user_class = 'elasticsearch::user',
[...]
if $elasticsearch::user_class {
require $elasticsearch::user_class
}
elasticsearch/manifests/user.pp
class elasticsearch::user {
@user { $elasticsearch::user :
ensure = $elasticsearch::ensure,
comment = ${elasticsearch::user} user,
password = '!',
managehome = false,
uid = $elasticsearch::user_uid,
gid = $elasticsearch::user_gid,
groups = $elasticsearch::user_groups,
shell = '/bin/bash',
}
User | title == $elasticsearch::user |
}
Do not create the requested user
class { ‘elasticsearch’:
user_class = undef,
}
Provide the user in a different custom class
class { ‘elasticsearch’:
user_class = 'site::users',
}
Run elasticsearch with a different user
class { ‘elasticsearch’:
user = 'apache',
}
Managing
extra
 
resources
Options to specify
custom classes
Options to pass
an hash to
create_resources
Extra Resources: Custom classes
elasticsearch/manifests/init.pp
class elasticsearch (
$dependency_class = 'elasticsearch::dependency',
$monitor_class = 'elasticsearch::monitor',
$firewall_class = 'elasticsearch::firewall',
$my_class = undef,
) {
[...]
if $elasticsearch::dependency_class {
include $elasticsearch::dependency_class
}
if $elasticsearch::monitor and $elasticsearch::monitor_class {
include $elasticsearch::monitor_class
}
if $elasticsearch::firewall and $elasticsearch::firewall_class {
include $elasticsearch::firewall_class
}
if $elasticsearch::my_class {
include $elasticsearch::my_class
}[...]
Provide the modules dependencies with a custom class
class { ‘elasticsearch’:
dependency_class = 'site::dep_elasticsearch',
}
Extra Resources: Resources Hash
elasticsearch/manifests/init.pp
class elasticsearch (
$create_resource = undef,
$resources_hash = undef,
) {
[...]
if $create_resource {
create_resources( $create_resource , $resources_hash )
}
Alternative: A single hash that includes resources and
resources_hash
Provide the modules dependencies with a custom class
class { ‘elasticsearch’:
create_resource = 'file',
resources_hash = {
path = '/etc/elasticsearch/my_file',
content = template('site/elasticsearch/my_file.erb),
mode = '0600',
},
}
Managing
Packages
and
Services
Names change
Custom packages
are common
Leave choice,
optionally
Managing packages
openssh/manifests/init.pp
class openssh (
$ensure = 'present',
$version = undef,
$package = $openssh::params::package,
[...]
) {
if $version and $ensure == 'present' {
$managed_package_ensure = $version
} else {
$managed_package_ensure = $ensure
}
if $openssh::package {
package { $openssh::package:
ensure = $openssh::managed_package_ensure,
}
}
openssh/manifests/params.pp
class openssh::params {
$package = $::osfamily ? {
Suse = 'openssh',
OpenBSD = '',
default = 'openssh-server',
}
Install a custom company-openssh package
class { ‘openssh’:
package = 'company-openssh',
}
Managing services
openssh/manifests/init.pp
class openssh (
$service = $openssh::params::service,
$service_ensure = 'running',
$service_enable = true,
[...]
) {
if $ensure == 'absent' {
$managed_service_enable = undef
$managed_service_ensure = stopped
} else {
$managed_service_enable = $service_enable
$managed_service_ensure = $service_ensure
}
if $openssh::service {
service { $openssh::service:
ensure = $openssh::managed_service_ensure,
enable = $openssh::managed_service_enable,
}
}
openssh/manifests/params.pp
class openssh::params {
$service = $::osfamily ? {
Debian = 'ssh',
default = 'sshd',
}
[...]
Manage a custom company-openssh service
class { ‘openssh’:
service = 'company-openssh',
}
Managing
Installation
 
options
Let users decide:
OS Packages
Upstream tarballs
Provider
Installation options
elasticsearch/manifests/init.pp
class elasticsearch (
$package_provider = undef,
$install = 'package',
$install_base_url = $elasticsearch::params::install_base_url,
$install_source = undef,
$install_destination = '/opt',
) {
[...]
$managed_file = $elasticsearch::install ? {
package = $elasticsearch::file,
default = ${elasticsearch::home_dir}/config/elasticsearch.yml,
}
[...]
case $elasticsearch::install {
package: {
package { $elasticsearch::package:
ensure = $elasticsearch::managed_package_ensure,
provider = $elasticsearch::package_provider,
}
}
upstream: {
puppi::netinstall { 'netinstall_elasticsearch':
url = $elasticsearch::managed_install_source,
destination_dir = $elasticsearch::install_destination,
owner = $elasticsearch::user,
group = $elasticsearch::user,
}
[...]
Install elasticsearch from upstream source
class { ‘elasticsearch’:
install = 'upstream',
install_source = 'https://download.elasticsearch.org/
elasticsearch/elasticsearch/elasticsearch-0.90.3.zip',
}
Templates
and
 hashes
Managing specific
application configs
parameters may get
out of control
A single config hash
to show them all
A custom template
to use them
Application specific configs
THE PARAMETERS
DILEMMA
Options Hash: Setup
openssh/manifests/init.pp
class openssh (
[...]
$file_template = undef,
$options_hash = undef,
site/templates/openssh/sshd_config.erb
# File Managed by Puppet
[...]
Port %= scope.function_options_lookup(['Port','22']) %
PermitRootLogin %= scope.function_options_lookup(['PermitRootLogin','yes']) %
UsePAM %= scope.function_options_lookup(['UsePAM','yes']) %
[...]
* Function options_lookup currently in Example42's Puppi module
Alternative site/templates/openssh/sshd_config.erb
Port %= scope.lookupvar('openssh::options_hash')['Port'] ||='22' %
PermitRootLogin %= scope.lookupvar('openssh::options_hash')['PermitRootLogin'] ||='yes' %
UsePAM %= scope.lookupvar('openssh::options_hash')['UsePAM'] ||='yes' %
[...]
Options Hash: Usage
Usage (with Hiera):
include openssh
/etc/puppet/hieradata/global.yml:
---
openssh::file_template: 'site/openssh/sshd_config.erb'
openssh::file_options_hash:
Port: '22222'
PermitRootLogin: 'no'
Usage (with parametrized class):
class { 'openssh':
file_template = 'site/openssh/sshd_config.erb'
file_options_hash = {
Port = '22222',
PermitRootLogin = 'no',
}
STANDARDS
NAMING
Managed resources attributes
THE PARAMETERS
DILEMMA
The
Handy

Más contenido relacionado

La actualidad más candente

La actualidad más candente (20)

Puppet modules: An Holistic Approach
Puppet modules: An Holistic ApproachPuppet modules: An Holistic Approach
Puppet modules: An Holistic Approach
 
Troubleshooting Puppet
Troubleshooting PuppetTroubleshooting Puppet
Troubleshooting Puppet
 
Doing It Wrong with Puppet -
Doing It Wrong with Puppet - Doing It Wrong with Puppet -
Doing It Wrong with Puppet -
 
Puppet: From 0 to 100 in 30 minutes
Puppet: From 0 to 100 in 30 minutesPuppet: From 0 to 100 in 30 minutes
Puppet: From 0 to 100 in 30 minutes
 
Intro to-puppet
Intro to-puppetIntro to-puppet
Intro to-puppet
 
PECL Picks - Extensions to make your life better
PECL Picks - Extensions to make your life betterPECL Picks - Extensions to make your life better
PECL Picks - Extensions to make your life better
 
Spl in the wild
Spl in the wildSpl in the wild
Spl in the wild
 
Puppet for Sys Admins
Puppet for Sys AdminsPuppet for Sys Admins
Puppet for Sys Admins
 
More tips n tricks
More tips n tricksMore tips n tricks
More tips n tricks
 
Replacing "exec" with a type and provider: Return manifests to a declarative ...
Replacing "exec" with a type and provider: Return manifests to a declarative ...Replacing "exec" with a type and provider: Return manifests to a declarative ...
Replacing "exec" with a type and provider: Return manifests to a declarative ...
 
Refactor Dance - Puppet Labs 'Best Practices'
Refactor Dance - Puppet Labs 'Best Practices'Refactor Dance - Puppet Labs 'Best Practices'
Refactor Dance - Puppet Labs 'Best Practices'
 
Puppet control-repo 
to the next level
Puppet control-repo 
to the next levelPuppet control-repo 
to the next level
Puppet control-repo 
to the next level
 
Puppet Camp Paris 2015: Power of Puppet 4 (Beginner)
Puppet Camp Paris 2015: Power of Puppet 4 (Beginner) Puppet Camp Paris 2015: Power of Puppet 4 (Beginner)
Puppet Camp Paris 2015: Power of Puppet 4 (Beginner)
 
Php on the Web and Desktop
Php on the Web and DesktopPhp on the Web and Desktop
Php on the Web and Desktop
 
PuppetCamp SEA 1 - Version Control with Puppet
PuppetCamp SEA 1 - Version Control with PuppetPuppetCamp SEA 1 - Version Control with Puppet
PuppetCamp SEA 1 - Version Control with Puppet
 
Doing the Refactor Dance - Making Your Puppet Modules More Modular - PuppetCo...
Doing the Refactor Dance - Making Your Puppet Modules More Modular - PuppetCo...Doing the Refactor Dance - Making Your Puppet Modules More Modular - PuppetCo...
Doing the Refactor Dance - Making Your Puppet Modules More Modular - PuppetCo...
 
The Puppet Debugging Kit: Building Blocks for Exploration and Problem Solving...
The Puppet Debugging Kit: Building Blocks for Exploration and Problem Solving...The Puppet Debugging Kit: Building Blocks for Exploration and Problem Solving...
The Puppet Debugging Kit: Building Blocks for Exploration and Problem Solving...
 
Ansible leveraging 2.0
Ansible leveraging 2.0Ansible leveraging 2.0
Ansible leveraging 2.0
 
Puppet: What _not_ to do
Puppet: What _not_ to doPuppet: What _not_ to do
Puppet: What _not_ to do
 
SPL to the Rescue - Tek 09
SPL to the Rescue - Tek 09SPL to the Rescue - Tek 09
SPL to the Rescue - Tek 09
 

Similar a Anatomy of a reusable module

Dependency injection in Drupal 8
Dependency injection in Drupal 8Dependency injection in Drupal 8
Dependency injection in Drupal 8
Alexei Gorobets
 
How to disassemble one monster app into an ecosystem of 30
How to disassemble one monster app into an ecosystem of 30How to disassemble one monster app into an ecosystem of 30
How to disassemble one monster app into an ecosystem of 30
fiyuer
 
modern module development - Ken Barber 2012 Edinburgh Puppet Camp
modern module development - Ken Barber 2012 Edinburgh Puppet Campmodern module development - Ken Barber 2012 Edinburgh Puppet Camp
modern module development - Ken Barber 2012 Edinburgh Puppet Camp
Puppet
 
From Dev to DevOps - Apache Barcamp Spain 2011
From Dev to DevOps - Apache Barcamp Spain 2011From Dev to DevOps - Apache Barcamp Spain 2011
From Dev to DevOps - Apache Barcamp Spain 2011
Carlos Sanchez
 
Decoupled Libraries for PHP
Decoupled Libraries for PHPDecoupled Libraries for PHP
Decoupled Libraries for PHP
Paul Jones
 

Similar a Anatomy of a reusable module (20)

Puppet Modules for Fun and Profit
Puppet Modules for Fun and ProfitPuppet Modules for Fun and Profit
Puppet Modules for Fun and Profit
 
Dependency injection in Drupal 8
Dependency injection in Drupal 8Dependency injection in Drupal 8
Dependency injection in Drupal 8
 
How to disassemble one monster app into an ecosystem of 30
How to disassemble one monster app into an ecosystem of 30How to disassemble one monster app into an ecosystem of 30
How to disassemble one monster app into an ecosystem of 30
 
modern module development - Ken Barber 2012 Edinburgh Puppet Camp
modern module development - Ken Barber 2012 Edinburgh Puppet Campmodern module development - Ken Barber 2012 Edinburgh Puppet Camp
modern module development - Ken Barber 2012 Edinburgh Puppet Camp
 
Asset management with Zend Framework 2
Asset management with Zend Framework 2Asset management with Zend Framework 2
Asset management with Zend Framework 2
 
Migrate yourself. code -> module -> mind
Migrate yourself. code -> module -> mindMigrate yourself. code -> module -> mind
Migrate yourself. code -> module -> mind
 
Валентин Мацвейко та Владислав Мойсеєнко — D8: Migrate Yourself: code->module...
Валентин Мацвейко та Владислав Мойсеєнко — D8: Migrate Yourself: code->module...Валентин Мацвейко та Владислав Мойсеєнко — D8: Migrate Yourself: code->module...
Валентин Мацвейко та Владислав Мойсеєнко — D8: Migrate Yourself: code->module...
 
From Dev to DevOps - Apache Barcamp Spain 2011
From Dev to DevOps - Apache Barcamp Spain 2011From Dev to DevOps - Apache Barcamp Spain 2011
From Dev to DevOps - Apache Barcamp Spain 2011
 
Symfony2 revealed
Symfony2 revealedSymfony2 revealed
Symfony2 revealed
 
Zend Framework 1.9 Setup & Using Zend_Tool
Zend Framework 1.9 Setup & Using Zend_ToolZend Framework 1.9 Setup & Using Zend_Tool
Zend Framework 1.9 Setup & Using Zend_Tool
 
Services Drupalcamp Stockholm 2009
Services Drupalcamp Stockholm 2009Services Drupalcamp Stockholm 2009
Services Drupalcamp Stockholm 2009
 
8 things to know about theming in drupal 8
8 things to know about theming in drupal 88 things to know about theming in drupal 8
8 things to know about theming in drupal 8
 
Symfony tips and tricks
Symfony tips and tricksSymfony tips and tricks
Symfony tips and tricks
 
Zend Framework 2 - Basic Components
Zend Framework 2  - Basic ComponentsZend Framework 2  - Basic Components
Zend Framework 2 - Basic Components
 
PHP: 4 Design Patterns to Make Better Code
PHP: 4 Design Patterns to Make Better CodePHP: 4 Design Patterns to Make Better Code
PHP: 4 Design Patterns to Make Better Code
 
Ruby meetup-dry
Ruby meetup-dryRuby meetup-dry
Ruby meetup-dry
 
Drupal Javascript for developers
Drupal Javascript for developersDrupal Javascript for developers
Drupal Javascript for developers
 
Demystifying Object-Oriented Programming - PHP UK Conference 2017
Demystifying Object-Oriented Programming - PHP UK Conference 2017Demystifying Object-Oriented Programming - PHP UK Conference 2017
Demystifying Object-Oriented Programming - PHP UK Conference 2017
 
Drupal 7 Theming - Behind the scenes
Drupal 7 Theming - Behind the scenes Drupal 7 Theming - Behind the scenes
Drupal 7 Theming - Behind the scenes
 
Decoupled Libraries for PHP
Decoupled Libraries for PHPDecoupled Libraries for PHP
Decoupled Libraries for PHP
 

Más de Alessandro Franceschi

Más de Alessandro Franceschi (14)

Strategies for Puppet code upgrade and refactoring
Strategies for Puppet code upgrade and refactoringStrategies for Puppet code upgrade and refactoring
Strategies for Puppet code upgrade and refactoring
 
DevOps - Evoluzione della specie - DevOps Heroes.pdf
DevOps - Evoluzione della specie - DevOps Heroes.pdfDevOps - Evoluzione della specie - DevOps Heroes.pdf
DevOps - Evoluzione della specie - DevOps Heroes.pdf
 
Tiny Puppet Can Install Everything. Prove me wrong!
Tiny Puppet Can Install Everything. Prove me wrong!Tiny Puppet Can Install Everything. Prove me wrong!
Tiny Puppet Can Install Everything. Prove me wrong!
 
Ten years of [Puppet] installations. What now?
Ten years of [Puppet] installations. What now?Ten years of [Puppet] installations. What now?
Ten years of [Puppet] installations. What now?
 
Puppet Systems Infrastructure Construction Kit
Puppet Systems Infrastructure Construction KitPuppet Systems Infrastructure Construction Kit
Puppet Systems Infrastructure Construction Kit
 
Puppet Continuous Integration with PE and GitLab
Puppet Continuous Integration with PE and GitLabPuppet Continuous Integration with PE and GitLab
Puppet Continuous Integration with PE and GitLab
 
Tp install anything
Tp install anythingTp install anything
Tp install anything
 
Puppet evolutions
Puppet evolutionsPuppet evolutions
Puppet evolutions
 
Essential applications management with Tiny Puppet
Essential applications management with Tiny PuppetEssential applications management with Tiny Puppet
Essential applications management with Tiny Puppet
 
Raise the bar! Reloaded
Raise the bar! ReloadedRaise the bar! Reloaded
Raise the bar! Reloaded
 
Raise the bar!
Raise the bar!Raise the bar!
Raise the bar!
 
Puppet modules: A Holistic Approach - Geneva
Puppet modules: A Holistic Approach - GenevaPuppet modules: A Holistic Approach - Geneva
Puppet modules: A Holistic Approach - Geneva
 
Developing IT infrastructures with Puppet
Developing IT infrastructures with PuppetDeveloping IT infrastructures with Puppet
Developing IT infrastructures with Puppet
 
Spaghetti devops
Spaghetti devopsSpaghetti devops
Spaghetti devops
 

Último

Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
Joaquim Jorge
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
panagenda
 

Último (20)

Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
Top 10 Most Downloaded Games on Play Store in 2024
Top 10 Most Downloaded Games on Play Store in 2024Top 10 Most Downloaded Games on Play Store in 2024
Top 10 Most Downloaded Games on Play Store in 2024
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
 

Anatomy of a reusable module

  • 1. Anatomy of a Reusable Module Alessandro Franceschi github.com/example42 PuppetConf 2013
  • 2. Be
  • 4. How
  • 6.  use Puppet today? Include classes Set Params Variables Define Business Integration Logic Provide Configuration Files Manage Resources
  • 7. How do we use Puppet today Include classes manifests/ site.pp Set Parameters / Variables Integration logic Resources ENC HIERA SITE MODULES SHARED MODULES BAD EDGE Configuration files manifests/ site.pp ENC HIERA manifests/ site.pp BAD? BAD? BAD SITE MODULES SITE MODULES SHARED MODULES SITE MODULES SHARED MODULES manifests/ site.pp BAD? ENC BAD?
  • 8. A
  • 11.  all
  • 13. The
  • 16. THE PARAMETERS DILEMMA Managed resources attributes Application specific config options Application logic and behaviour Integration with other modules
  • 17. Parameters: Resources attributes Enough: $package = $redis::params::package, $service = $redis::params::service, $service_ensure = 'running', $service_enable = true, $file = $redis::params::file, $file_notify = Service['redis'], $file_source = undef, $file_content = undef, Too much? $package_provider = undef, $file_owner = $redis::params::file_owner, $file_group = $redis::params::file_group, $file_mode = $redis::params::file_mode, $file_replace = $redis::params::file_replace, Benefits from: A standard naming convention
  • 18. Parameters: Application options Enough: $puppet_server = “puppet.${::domain}”, $syslog_server = “syslog.${::domain}”, $munin_server = “munin.${::domain}”, $dns_servers = [ '8.8.8.8' , '8.8.4.4' ], Too much! $anonymous_enable = true, $anon_mkdir_write_enable = true, $anon_upload_enable = false, $chroot_list_enable = true, $chroot_list_file = '/etc/vsftpd/chroot_list', $resourcefile = $nagios::params::resourcefile, $statusfile = $nagios::params::statusfile, $commandfile = $nagios::params::commandfile, $resultpath = $nagios::params::resultpath, $retentionfile = $nagios::params::retentionfile, $p1file = $nagios::params::p1file, Benefits from: Template + Options Hash pattern
  • 19. Parameters: Application logic Examples: $install_client = true, $install_stomp_server = true, $install_plugins = true, $use_ssl = false, $munin_autoconfigure = true, $service_autorestart = true, $manage_package_repo = true, $run_initdb = undef, Benefits from: A standard naming convention
  • 20. Parameters: Modules Integrations Examples: $mongo_db_host = $graylog2::params::mongo_db_host, $mongo_db_port = $graylog2::params::mongo_db_port, $mongo_db_name = $graylog2::params::mongo_db_name, $mongo_user = $graylog2::params::mongo_user, $mongo_password = $graylog2::params::mongo_password, $elasticsearch_template = $graylog2::params::elasticsearch_template, $elasticsearch_path = $graylog2::params::elasticsearch_path, $database = $puppetdb::params::database, $manage_redhat_firewall = $puppetdb::params::manage_redhat_firewall, $db_type = 'mysql', Benefits from: Shared Stacks
  • 23.   files Let user decide how to manage configuration files. Alternatives: source content concat augeas custom types
  • 24. Managing files: source content redis/manifests/init.pp class redis ( $file = $redis::params::file, $file_source = undef, $file_template = undef, $file_content = undef, ) { [...] $managed_file_content = $file_content ? { undef = $file_template ? { undef = undef, default = template($file_template), }, default = $file_content, } [...] if $redis::file { file { 'redis.conf': path = $redis::file, source = $redis::file_source, content = $redis::managed_file_content, } } } Provide the Puppet path of an erb template class { ‘redis’: file_template = ‘site/redis/ redis.conf.erb’, } Provide directly the content attribute class { ‘redis’: file_content = “template(‘site/redis/ redis.conf.erb’)”, } Provide a fileserver source path class { ‘redis’: file_source = ‘puppet:///modules/site/ redis/redis.conf’, } Manage the configuration file with other methods (augeas, concat...) class { ‘redis’: }
  • 28.   Add parameters to main class Use a generic conf define Manage the whole configuration dir
  • 29. Multiple files: Add parameters elasticsearch/manifests/init.pp class elasticsearch ( $file = $elasticsearch::params::file, $file_source = undef, $file_template = undef, $file_content = undef, [...] $init_script_file = '/etc/init.d/elasticsearch', $init_script_file_template = 'elasticsearch/init.erb', $init_options_file = $elasticsearch::params::init_options_file, $init_options_file_template = 'elasticsearch/init_options.erb', Provide custom templates for the main file and the init script class { ‘elasticsearch’: file_template = ‘site/elasticsearch/elasticsearch.yml.erb’, init_script_file_template = ‘site/elasticsearch/elasticsearch.init.erb’, }
  • 30. Multiple files: Generic conf define nova/manifests/conf.pp define nova::conf ( $source = undef, $template = undef, $content = undef, $path = undef, [...] $options_hash = undef, $ensure = present ) { include nova $managed_path = $path ? { undef = ${nova::config_dir}/${name}, default = $path, } [...] file { nova_conf_${name}: ensure = $ensure, source = $source, content = $managed_content, path = $managed_path, mode = $managed_mode, owner = $managed_owner, group = $managed_group, require = $managed_require, notify = $managed_notify, replace = $managed_replace, } } Provide a custom template for an alternative config file in config_dir nova::conf { ‘rootwrap.conf’: template = ‘site/nova/rootwrap.conf.erb’, }
  • 31. Multiple files: Whole config dir redis/manifests/init.pp class redis ( $dir = $redis::params::dir, $dir_source = undef, $dir_purge = false, $dir_recurse = true, ) { [...] $dir_ensure = $ensure ? { 'absent' = 'absent', 'present' = 'directory', } if $redis::dir_source { file { 'redis.dir': ensure = $redis::dir_ensure, path = $redis::dir, source = $redis::dir_source, recurse = $redis::dir_recurse, purge = $redis::dir_purge, force = $redis::dir_purge, notify = $redis::file_notify, require = $redis::file_require, } } } Provide a custom source for the whole config_dir class { ‘redis’: dir_source = ‘puppet:///modules/site/redis/conf/’, } Provide a custom source for the whole config_dir and purge any not managed config file class { ‘redis’: dir_source = ‘puppet:///modules/site/redis/conf/’, dir_purge = true, }
  • 33.   Users Everyone has his own users... Leave options to decide if, how and where to manage the ones the module requires.
  • 34. Managing Users elasticsearch/manifests/init.pp class elasticsearch { $ensure = 'present', [...] $user = 'elasticsearch', $user_uid = undef, $user_gid = undef, $user_groups = undef, $user_class = 'elasticsearch::user', [...] if $elasticsearch::user_class { require $elasticsearch::user_class } elasticsearch/manifests/user.pp class elasticsearch::user { @user { $elasticsearch::user : ensure = $elasticsearch::ensure, comment = ${elasticsearch::user} user, password = '!', managehome = false, uid = $elasticsearch::user_uid, gid = $elasticsearch::user_gid, groups = $elasticsearch::user_groups, shell = '/bin/bash', } User | title == $elasticsearch::user | } Do not create the requested user class { ‘elasticsearch’: user_class = undef, } Provide the user in a different custom class class { ‘elasticsearch’: user_class = 'site::users', } Run elasticsearch with a different user class { ‘elasticsearch’: user = 'apache', }
  • 36.   resources Options to specify custom classes Options to pass an hash to create_resources
  • 37. Extra Resources: Custom classes elasticsearch/manifests/init.pp class elasticsearch ( $dependency_class = 'elasticsearch::dependency', $monitor_class = 'elasticsearch::monitor', $firewall_class = 'elasticsearch::firewall', $my_class = undef, ) { [...] if $elasticsearch::dependency_class { include $elasticsearch::dependency_class } if $elasticsearch::monitor and $elasticsearch::monitor_class { include $elasticsearch::monitor_class } if $elasticsearch::firewall and $elasticsearch::firewall_class { include $elasticsearch::firewall_class } if $elasticsearch::my_class { include $elasticsearch::my_class }[...] Provide the modules dependencies with a custom class class { ‘elasticsearch’: dependency_class = 'site::dep_elasticsearch', }
  • 38. Extra Resources: Resources Hash elasticsearch/manifests/init.pp class elasticsearch ( $create_resource = undef, $resources_hash = undef, ) { [...] if $create_resource { create_resources( $create_resource , $resources_hash ) } Alternative: A single hash that includes resources and resources_hash Provide the modules dependencies with a custom class class { ‘elasticsearch’: create_resource = 'file', resources_hash = { path = '/etc/elasticsearch/my_file', content = template('site/elasticsearch/my_file.erb), mode = '0600', }, }
  • 40. Managing packages openssh/manifests/init.pp class openssh ( $ensure = 'present', $version = undef, $package = $openssh::params::package, [...] ) { if $version and $ensure == 'present' { $managed_package_ensure = $version } else { $managed_package_ensure = $ensure } if $openssh::package { package { $openssh::package: ensure = $openssh::managed_package_ensure, } } openssh/manifests/params.pp class openssh::params { $package = $::osfamily ? { Suse = 'openssh', OpenBSD = '', default = 'openssh-server', } Install a custom company-openssh package class { ‘openssh’: package = 'company-openssh', }
  • 41. Managing services openssh/manifests/init.pp class openssh ( $service = $openssh::params::service, $service_ensure = 'running', $service_enable = true, [...] ) { if $ensure == 'absent' { $managed_service_enable = undef $managed_service_ensure = stopped } else { $managed_service_enable = $service_enable $managed_service_ensure = $service_ensure } if $openssh::service { service { $openssh::service: ensure = $openssh::managed_service_ensure, enable = $openssh::managed_service_enable, } } openssh/manifests/params.pp class openssh::params { $service = $::osfamily ? { Debian = 'ssh', default = 'sshd', } [...] Manage a custom company-openssh service class { ‘openssh’: service = 'company-openssh', }
  • 43.   options Let users decide: OS Packages Upstream tarballs Provider
  • 44. Installation options elasticsearch/manifests/init.pp class elasticsearch ( $package_provider = undef, $install = 'package', $install_base_url = $elasticsearch::params::install_base_url, $install_source = undef, $install_destination = '/opt', ) { [...] $managed_file = $elasticsearch::install ? { package = $elasticsearch::file, default = ${elasticsearch::home_dir}/config/elasticsearch.yml, } [...] case $elasticsearch::install { package: { package { $elasticsearch::package: ensure = $elasticsearch::managed_package_ensure, provider = $elasticsearch::package_provider, } } upstream: { puppi::netinstall { 'netinstall_elasticsearch': url = $elasticsearch::managed_install_source, destination_dir = $elasticsearch::install_destination, owner = $elasticsearch::user, group = $elasticsearch::user, } [...] Install elasticsearch from upstream source class { ‘elasticsearch’: install = 'upstream', install_source = 'https://download.elasticsearch.org/ elasticsearch/elasticsearch/elasticsearch-0.90.3.zip', }
  • 46.  hashes Managing specific application configs parameters may get out of control A single config hash to show them all A custom template to use them Application specific configs THE PARAMETERS DILEMMA
  • 47. Options Hash: Setup openssh/manifests/init.pp class openssh ( [...] $file_template = undef, $options_hash = undef, site/templates/openssh/sshd_config.erb # File Managed by Puppet [...] Port %= scope.function_options_lookup(['Port','22']) % PermitRootLogin %= scope.function_options_lookup(['PermitRootLogin','yes']) % UsePAM %= scope.function_options_lookup(['UsePAM','yes']) % [...] * Function options_lookup currently in Example42's Puppi module Alternative site/templates/openssh/sshd_config.erb Port %= scope.lookupvar('openssh::options_hash')['Port'] ||='22' % PermitRootLogin %= scope.lookupvar('openssh::options_hash')['PermitRootLogin'] ||='yes' % UsePAM %= scope.lookupvar('openssh::options_hash')['UsePAM'] ||='yes' % [...]
  • 48. Options Hash: Usage Usage (with Hiera): include openssh /etc/puppet/hieradata/global.yml: --- openssh::file_template: 'site/openssh/sshd_config.erb' openssh::file_options_hash: Port: '22222' PermitRootLogin: 'no' Usage (with parametrized class): class { 'openssh': file_template = 'site/openssh/sshd_config.erb' file_options_hash = { Port = '22222', PermitRootLogin = 'no', }
  • 53.   Standards A blog post* Some discussions on Puppet-Users github.com/stdmod Naming standards for modules parameters Community driven (draft 0.0.2) * http://www.example42.com/?q=The_handy_Grail_of_Modules_Standards
  • 55.  of
  • 59. Stdmod Params: Main resources ### General parameters ensure (enable?) version (package_version?) ### Package - Service - Main configuration file package (package_name?) package_ensure package_provider package_* [any relevant package type attribute] service (service_name?) service_ensure service_enable service_subscribe service_* file (file_path? config_file? config?) file_source (source? config_file_source? config_source?) file_template (template? config_file_template? config_template?) file_content (content? config_file_content? config_content?) file_* (config_file_*? config_*?) file_options_hash (options? options_hash? file_options?)
  • 60. Stdmod Params: Extra resources other_package other_package_* client_package client_package_* server_package server_package_* other_service other_service_* log_file log_file_* pid_file pid_file_* init_script_file init_script_file_* init_config_file init_config_file_*
  • 61. Stdmod Params: Installation ### Parameter related parameters install install_url install_base_url install_source install_destination install_pre_exec install_pre_exec_* install_post_exec install_post_exec_* install_script_file install_script_file_* install_response_file install_response_file_*
  • 65. Why
  • 68.  stack? We always use stacks. We need them to make something useful with modules. What about: Sharing? Best practices? Standardization?
  • 69. Stacks - A Simple Sample class stack::logs ( $ensure = 'present', $syslog_server = false, $syslog_server_port = '5544', $elasticsearch_server = false, $elasticsearch_server_port = '9200', $elasticsearch_cluster = 'logs', $elasticsearch_java_opts = '-Xmx2g -Xms1g', $install_logstash = false, $install_elasticsearch = false, $install_kibana = false, $install_graylog2 = false, $install_graylog2_webinterface = false, $syslog_config_template = 'stack/logs/syslog.conf.erb', $logstash_config_template = 'stack/logs/logstash.conf.erb', $elasticsearch_config_template = 'stack/logs/elasticsearch.yml.erb', $kibana_config_template = 'stack/logs/config.js.erb', $graylog2_config_template = 'stack/logs/graylog2.conf.erb', ) { [... TO BE CONTINUED ...]
  • 70. Stacks - A Simple Sample [...] if $syslog_server { rsyslog::config { 'logstash_stack': content = template($syslog_config_template), } } if $install_logstash { class { 'logstash': template = $logstash_config_template, } } if $install_elasticsearch { class { 'elasticsearch': java_opts = $elasticsearch_java_opts, template = $elasticsearch_config_template, } } [...]
  • 71. Stacks - Usage On any host: stack::logs { 'central': syslog_server = 'syslog.example42.com', } On the Logstash (syslog) server: stack::logs { 'central': syslog_server = 'syslog.example42.com', install_logstash = true, elasticsearch_server = 'el.example42.com', } On the Elasticsearch server(s), with a custom configuration file: stack::logs { 'central': syslog_server = 'syslog.example42.com', install_elasticsearch = true, elasticsearch_server = 'el.example42.com', elasticsearch_config_template = 'site/logs/elasticsearch.yml.erb', } On the Kibana server: stack::logs { 'central': syslog_server = 'syslog.example42.com', install_kibana = true, elasticsearch_server = 'el.example42.com', }
  • 72. The Stacks Logic Stacks are local Modules are shared Higher level interface Integrate different set of modules Preserve modules local change
  • 73. How do we use Puppet today Include classes manifests/ site.pp Set Parameters / Variables Integration logic Resources ENC HIERA SITE MODULES SHARED MODULES BAD EDGE Configuration files manifests/ site.pp ENC HIERA manifests/ site.pp BAD? BAD? BAD SITE MODULES SITE MODULES SHARED MODULES SITE MODULES SHARED MODULES manifests/ site.pp BAD? ENC BAD? STACKS STACKS STACKS
  • 75. Steps Define stdmod naming conventions Explore Stacks design and approach Create templates for stacks and modules Explore GUI integrations
  • 76. SO
  • 77.  Long and thanks for all the fish! Graphics: www.tatlin.net @alvagante
  • 78. SO
  • 79.  Long and thanks for all the fish! Graphics: www.tatlin.net @alvagante