SlideShare uses cookies to improve functionality and performance, and to provide you with relevant advertising. If you continue browsing the site, you agree to the use of cookies on this website. See our User Agreement and Privacy Policy.
SlideShare uses cookies to improve functionality and performance, and to provide you with relevant advertising. If you continue browsing the site, you agree to the use of cookies on this website. See our Privacy Policy and User Agreement for details.
Successfully reported this slideshow.
Activate your 30 day free trial to unlock unlimited reading.
How to make an Example42 nextgen module in 5 minutes
How to make an Example42 nextgen module in 5 minutes
1.
How to Create a Next-Gen
Example42 Puppet Module
in 5 Minutes
Prepare for an info overload rush
and an Ignite's verbosity world record
Alessandro Franceschi
DevOps Days Rome 2012
2.
Example42 Next-Gen modules...
Support for different OS (Default: RedHat / Debian)
Fully parametrized classes
Data separation with Hiera/ENC parameters lookup
Extreme customization options
Module behavior customization options
Full and partial decommissioning support
Optional automatic Monitoring / Firewalling
Optional Puppi integration
Optional Debug and Auditing
5.
Create a new module from foo
Example42-tools/module_clone.sh
This script creates a skeleton for a new module based on different Example42 foo module templates.
[...]
Enter the name of the new module based on foo: lighttpd
COPYING MODULE
building file list ... done
Modulefile
README.rdoc
Rakefile
manifests/
manifests/init.pp
manifests/params.pp
manifests/spec.pp
spec/
spec/spec_helper.rb
spec/classes/
spec/classes/foo_spec.rb
[...]
RENAMING FILES
Renamed lighttpd/spec/classes/foo_spec.rb to lighttpd/spec/classes/lighttpd_spec.rb
---------------------------------------------------
CHANGING FILE CONTENTS
Changed lighttpd/manifests/init.pp
Changed lighttpd/manifests/params.pp
Changed lighttpd/manifests/spec.pp
Changed lighttpd/Modulefile
Changed lighttpd/README.rdoc
Changed lighttpd/spec/classes/lighttpd_spec.rb
Changed lighttpd/spec/spec_helper.rb
Module lighttpd created
Start to edit lighttpd/manifests/params.pp to customize it
8.
Edit params.pp 2/2
vi lighttpd/manifests/params.pp
# You should not need to change the following ones
class lighttpd::params {
[...]
# General Settings
$my_class = ''
$source = ''
$source_dir = ''
$source_dir_purge = false
$template = ''
$options = ''
$service_autorestart = true
$version = 'present'
$absent = false
$disable = false
$disableboot = false
### General module variables that can have a site or per module default
$monitor = false
$monitor_tool = ''
git status
$monitor_target = $::ipaddress
$firewall = false
#! modified: manifests/params.pp
$firewall_tool = ''
$firewall_src = '0.0.0.0/0' git add .
$firewall_dst = $::ipaddress git commit -m "Basic support for Ubuntu/RedHat families"
$puppi = false
$puppi_helper = 'standard'
$debug = false
$audit_only = false
9.
Review and sign module
vi lighttpd/README.rdoc
= Puppet module: lighttpd
This is a Puppet module for lighttpd based on the second generation layout ("NextGen") of Example42 Puppet Modules.
Made by Alvagante / Example42
Official site: http://www.example42.com
Official git repository: http://github.com/example42/puppet-lighttpd
Released under the terms of Apache 2 License.
== USAGE - Basic management
* Install lighttpd with default settings
class { 'lighttpd': }
* Use custom source directory for the whole configuration dir
class { 'lighttpd':
source_dir => 'puppet:///modules/example42/lighttpd/conf/',
}
* Use custom template for main config file. Note that template and source arguments are alternative.
class { 'lighttpd':
template => 'example42/lighttpd/lighttpd.conf.erb',
}
* Automatically include a custom subclass git status
class { 'lighttpd': #! modified: README.rdoc
my_class => 'example42::my_lighttpd',
} git add .
git commit -m "Changed module's author to ... me"
* Activate automatic monitoring
class { 'lighttpd':
monitor => true,
monitor_tool => [ 'nagios' , 'monit' , 'munin' ],
}
10.
Explore the module's logic 1/4
less lighttpd/manifests/init.pp
# = Class: lighttpd
# == Parameters
#
# [*my_class*]
# Name of a custom class to autoload to manage module's customizations
# If defined, lighttpd class will automatically "include $my_class"
# Can be defined also by the (top scope) variable $lighttpd_myclass
#
# [*source*]
# Sets the content of source parameter for main configuration file
# If defined, lighttpd main config file will have the param: source => $source
# Can be defined also by the (top scope) variable $lighttpd_source
[...]
class lighttpd (
$my_class = params_lookup( 'my_class' ),
$source = params_lookup( 'source' ),
$source_dir = params_lookup( 'source_dir' ),
$source_dir_purge = params_lookup( 'source_dir_purge' ),
$template = params_lookup( 'template' ),
$service_autorestart = params_lookup( 'service_autorestart' , 'global' ),
$options = params_lookup( 'options' ),
$version = params_lookup( 'version' ),
$disable = params_lookup( 'disable' ),
[...]
$data_dir = params_lookup( 'data_dir' ),
$log_dir = params_lookup( 'log_dir' ),
$log_file = params_lookup( 'log_file' ),
$port = params_lookup( 'port' ),
$protocol = params_lookup( 'protocol' )
) inherits lighttpd::params {
11.
Explore the module's logic 2/4
less lighttpd/manifests/init.pp
class lighttpd (
[...]
) inherits lighttpd::params {
$bool_source_dir_purge=any2bool($source_dir_purge)
$bool_service_autorestart=any2bool($service_autorestart)
$bool_absent=any2bool($absent)
$bool_disable=any2bool($disable)
$bool_disableboot=any2bool($disableboot)
$bool_monitor=any2bool($monitor)
[...]
### Definition of some variables used in the module
$manage_package = $lighttpd::bool_absent ? {
true => 'absent',
false => $lighttpd::version,
}
$manage_service_enable = $lighttpd::bool_disableboot ? {
true => false,
default => $lighttpd::bool_disable ? {
true => false,
default => $lighttpd::bool_absent ? {
true => false,
false => true,
},
},
}
[...]
13.
Explore the module's logic 4/4
less lighttpd/manifests/init.pp
[...]
# The whole lighttpd configuration directory can be recursively overriden
if $lighttpd::source_dir {
file { 'lighttpd.dir':
ensure => directory,
path => $lighttpd::config_dir,
require => Package['lighttpd'],
notify => $lighttpd::manage_service_autorestart,
source => $lighttpd::source_dir,
recurse => true,
purge => $lighttpd::bool_source_dir_purge,
replace => $lighttpd::manage_file_replace,
audit => $lighttpd::manage_audit,
}
}
### Include custom class if $my_class is set
if $lighttpd::my_class {
# With
include $lighttpd::my_class class { 'lighttpd':
} my_class => 'example42::my_lighttpd',
}
### Provide puppi data, if puppi is enabled
if $lighttpd::bool_puppi == true { # You can autoload example42/manifests/my_lighttpd.pp:
$classvars=get_class_args() class example42::my_lighttpd {
puppi::ze { 'lighttpd': # My extra custom resources
ensure => $lighttpd::manage_file,
}
variables => $classvars,
helper => $lighttpd::puppi_helper,
}
}
14.
Add a parameter to the class
vi lighttpd/manifests/params.pp
### Module specific parameters
$use_ssl = false
vi lighttpd/manifests/init.pp
# == Parameters
# [*use_ssl*]
# Set to true to activate ssl.
# In order to use this option you need to use a template that honours it:
# template => 'site/lighttpd/lighttpd.conf.erb',
# (cp lighttpd/templates/lighttpd.conf.erb site/templates/lighttpd/lighttpd.conf.erb)
[...]
class lighttpd (
$use_ssl = params_lookup( 'use_ssl' ),
) inherits lighttpd::params {
[...]
$bool_use_ssl=any2bool($use_ssl)
[...]
### Include ssl subclass (if it were of any use)
# if $lighttpd::bool_use_ssl == true {
# include $lighttpd::ssl
# fi
git status
#! modified: manifests/init.pp
#! modified: manifests/params.pp
git add .
git commit -m "Added (mostly useless) use_ssl parameter"
17.
Add rspec test for a define
vi spec/defines/lighttpd_dotconf_spec.rb
require "#{File.join(File.dirname(__FILE__),'..','spec_helper.rb')}"
describe 'lighttpd::dotconf' do
let(:title) { 'lighttpd::dotconf' }
let(:node) { 'rspec.example42.com' }
let(:facts) { { :arch => 'i386' , :operatingsystem => 'redhat' } }
let(:params) {
{ 'ensure' => 'present',
'name' => 'www.example42.com',
'source' => 'puppet:///modules/site/lighttpd/www.example42.com.conf',
}
}
describe 'Test lighttpd::dotconf' do
it 'should create a lighttpd::dotconf' do
should contain_file('Lighttpd_www.example42.com.conf').with_ensure('present')
end
end
describe 'Test lighttpd::dotconf source parameter' do
it 'should create a lighttpd::dotconf' do
content = catalogue.resource('file', 'Lighttpd_www.example42.com.conf').send(:parameters)[:source]
content.should == "puppet:///modules/site/lighttpd/www.example42.com.conf"
end
end
describe 'Test lighttpd::virtualhost decommissioning' do
let(:facts) { { :arch => 'i386' , :operatingsystem => 'ubuntu' } }
let(:params) {
{ 'ensure' => 'absent' git status
} #! modified: spec/defines/lighttpd_dotconf_spec.rb
}
it 'should remove a lighttpd::dotconf file with ensure => absent' do
git add .
should contain_file('Lighttpd_www.example42.com.conf').with_ensure('absent')
end git commit -m "Added lighttpd::dotconf spec tests"
end
18.
Run Tests
cd lighttpd;./Example42-tools/check-module.sh
############################
### Executing rake tasks ###
############################
/usr/local/rvm/rubies/ruby-1.8.7-head/bin/ruby -S rspec spec/classes/lighttpd_spec.rb --format doc --color
Run options: exclude {:broken=>true}
lighttpd
Test standard installation
should contain Package[lighttpd] with ensure => "present"
should contain Service[lighttpd] with ensure => "running"
should contain Service[lighttpd] with enable => "true"
should contain File[lighttpd.conf] with ensure => "present"
Test installation of a specific version
should contain Package[lighttpd] with ensure => "1.0.42"
Test standard installation with monitoring and firewalling
should contain Package[lighttpd] with ensure => "present"
should contain Service[lighttpd] with ensure => "running"
should contain Service[lighttpd] with enable => "true"
should contain File[lighttpd.conf] with ensure => "present"
should monitor the process
should place a firewall rule
[...]
############################
### Executing puppetlint ###
############################
### ./manifests/init.pp
WARNING: line has more than 80 characters on line 108
WARNING: line has more than 80 characters on line 437
### ./manifests/params.pp
### ./manifests/spec.pp
19.
Job Done
Module is ready to use:
node test {
class { 'lighttpd':
# Custom configuration provided as a template created in:
# MODULEPATH/site/templates/lighttpd/lighttpd.conf.erb
template => 'site/lighttpd/lighttpd.conf.erb'
# Custom options used in template:
options => {
'server.kbytes-per-second' => 254,
'server.max-keep-alive-idle' => 3,
}
}
}
git remote add origin https://github.com/example42/puppet-lighttpd.git
git push -u origin master
20.
Was it too fast?
Get the module:
http://github.com/example42/
puppet-lighttpd.git
Review these slides:
http://slideshare.net/alvagante
Follow Up on Twitter:
@alvagante