How to make an Example42 nextgen module in 5 minutes

2,767 views
2,583 views

Published on

A ridiculously verbose ignite where is described how is possible to create a full featured Example42 Next-Gen module in 5 minutes.

Published in: Technology
0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
2,767
On SlideShare
0
From Embeds
0
Number of Embeds
640
Actions
Shares
0
Downloads
26
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide

How to make an Example42 nextgen module in 5 minutes

  1. 1. How to Create a Next-GenExample42 Puppet Module in 5 Minutes Prepare for an info overload rush and an Ignites verbosity world record Alessandro Franceschi DevOps Days Rome 2012
  2. 2. Example42 Next-Gen modules...Support for different OS (Default: RedHat / Debian)Fully parametrized classesData separation with Hiera/ENC parameters lookupExtreme customization optionsModule behavior customization optionsFull and partial decommissioning supportOptional automatic Monitoring / FirewallingOptional Puppi integrationOptional Debug and Auditing
  3. 3. Fetch the sourcesgit clone --recursivegit://github.com/example42/puppet-modules-nextgen.gitCloning into puppet-modules-nextgen...remote: Counting objects: 608, done.remote: Compressing objects: 100% (317/317), done.remote: Total 608 (delta 281), reused 578 (delta 252)Receiving objects: 100% (608/608), 102.59 KiB | 118 KiB/s, done.Resolving deltas: 100% (281/281), done.Submodule Example42-documentation (git://github.com/example42/Example42-documentation.git) registered for path Example42-documentationSubmodule Example42-tools (git://github.com/example42/Example42-tools.git) registered for path Example42-tools[...]
  4. 4. Enjoy modules varietycd puppet-modules-nextgen ; lsExample42-documentation! maven! ! ! ! puppiExample42-tools! ! ! mcollective! ! ! rclocalGemfile!! ! ! ! monitor! ! ! ! redisREADME.rdoc! ! ! ! munin! ! ! ! resolverRakefile! ! ! ! ! mysql! ! ! ! rsyncactivemq! ! ! ! ! nagios! ! ! ! rsyncsshapache! ! ! ! ! nginx! ! ! ! rvmconcat! ! ! ! ! nrpe!! ! ! ! solrexample42! ! ! ! ntp! ! ! ! ! splunkfirewall! ! ! ! ! openntpd!! ! ! stdlib42foo!! ! ! ! ! openssh! ! ! ! sudofoo_webapp! ! ! ! openvpn! ! ! ! tartarusforeman!! ! ! ! orientdb!! ! ! tftphaproxy!! ! ! ! pentaho! ! ! ! tomcaticinga! ! ! ! ! php! ! ! ! ! vagrantiptables! ! ! ! ! postfix! ! ! ! vsftpdjava! ! ! ! ! postgresql! ! ! wgetjboss! ! ! ! ! pupmod-concat! ! wordpressjenkins!! ! ! ! puppet! ! ! ! xinetdlibvirt!! ! ! ! puppetdashboard! ! yumlogstash! ! ! ! ! puppetdb
  5. 5. Create a new module from fooExample42-tools/module_clone.shThis 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: lighttpdCOPYING MODULEbuilding file list ... doneModulefileREADME.rdocRakefilemanifests/manifests/init.ppmanifests/params.ppmanifests/spec.ppspec/spec/spec_helper.rbspec/classes/spec/classes/foo_spec.rb[...]RENAMING FILESRenamed lighttpd/spec/classes/foo_spec.rb to lighttpd/spec/classes/lighttpd_spec.rb---------------------------------------------------CHANGING FILE CONTENTSChanged lighttpd/manifests/init.ppChanged lighttpd/manifests/params.ppChanged lighttpd/manifests/spec.ppChanged lighttpd/ModulefileChanged lighttpd/README.rdocChanged lighttpd/spec/classes/lighttpd_spec.rbChanged lighttpd/spec/spec_helper.rbModule lighttpd createdStart to edit lighttpd/manifests/params.pp to customize it
  6. 6. Explore modules contentsfind lighttpd/lighttpd/ git init git add . git commit -m "Example42-tools/module_clone.sh lighttpd"lighttpd/speclighttpd/spec/spec_helper.rblighttpd/spec/classeslighttpd/spec/classes/lighttpd_spec.rblighttpd/Rakefilelighttpd/Modulefilelighttpd/manifestslighttpd/manifests/init.pplighttpd/manifests/params.pplighttpd/manifests/spec.pplighttpd/README.rdoclighttpd/templateslighttpd/templates/spec.erb
  7. 7. Edit params.pp 1/2vi lighttpd/manifests/params.ppclass lighttpd::params { $package = $::operatingsystem ? { default => lighttpd, } $service = $::operatingsystem ? { default => lighttpd, }[...] $config_dir = $::operatingsystem ? { /(?i:Debian|Ubuntu|Mint)/ => /etc/lighttpd/conf-enabled, default => /etc/lighttpd/conf.d, } $config_file_init = $::operatingsystem ? { /(?i:Debian|Ubuntu|Mint)/ => /etc/default/lighttpd, default => /etc/sysconfig/lighttpd, } $data_dir = $::operatingsystem ? { /(?i:Debian|Ubuntu|Mint)/ => /var/run/lighttpd, default => /var/www, } $log_dir = $::operatingsystem ? { default => /var/log/lighttpd, } $log_file = $::operatingsystem ? { default => /var/log/lighttpd.log, } $port = 80 $protocol = tcp
  8. 8. Edit params.pp 2/2vi lighttpd/manifests/params.pp# You should not need to change the following onesclass 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. 9. Review and sign modulevi lighttpd/README.rdoc= Puppet module: lighttpdThis is a Puppet module for lighttpd based on the second generation layout ("NextGen") of Example42 Puppet Modules.Made by Alvagante / Example42Official site: http://www.example42.comOfficial git repository: http://github.com/example42/puppet-lighttpdReleased 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 modules author to ... me"* Activate automatic monitoring class { lighttpd: monitor => true, monitor_tool => [ nagios , monit , munin ], }
  10. 10. Explore the modules logic 1/4less lighttpd/manifests/init.pp# = Class: lighttpd# == Parameters## [*my_class*]# Name of a custom class to autoload to manage modules 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. 11. Explore the modules logic 2/4less lighttpd/manifests/init.ppclass 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, }, }, } [...]
  12. 12. Explore the modules logic 3/4less lighttpd/manifests/init.ppclass lighttpd ([...] ) inherits lighttpd::params { $manage_package = $lighttpd::bool_absent ? { true => absent, false => $lighttpd::version, <=[...] } package { lighttpd: ensure => $lighttpd::manage_package, $manage_service_enable = $lighttpd::bool_disableboot ? { name => $lighttpd::package, true => false, } default => $lighttpd::bool_disable ? { true => false, service { lighttpd: default => $lighttpd::bool_absent ? { ensure => $lighttpd::manage_service_ensure, true => false, name => $lighttpd::service, false => true, enable => $lighttpd::manage_service_enable, }, hasstatus => $lighttpd::service_status, }, pattern => $lighttpd::process, } require => Package[lighttpd], [...] } $manage_file_source = $lighttpd::source ? { => undef, file { lighttpd.conf: default => $lighttpd::source, ensure => $lighttpd::manage_file, } path => $lighttpd::config_file, [...] notify => $lighttpd::manage_service_autorestart, $manage_file_content = $lighttpd::template ? { source => $lighttpd::manage_file_source, => undef, content => $lighttpd::manage_file_content, default => template($lighttpd::template), replace => $lighttpd::manage_file_replace, } } [...]=>
  13. 13. Explore the modules logic 4/4less 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. 14. Add a parameter to the classvi lighttpd/manifests/params.pp### Module specific parameters$use_ssl = falsevi 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"
  15. 15. Create a sample templatevi lighttpd/templates/lighttpd.conf.erb# File Managed by Puppet## Sample /etc/lighttpd/lighttpd.conf based on Centos6 layout#var.log_root = "<%= scope.lookupvar(lighttpd::log_dir) %>"var.server_root = "<%= scope.lookupvar(lighttpd::data_dir) %>"var.conf_dir = "<%= scope.lookupvar(lighttpd::conf_dir) %>"[...]<% if bool_use_ssl == true %> ssl.engine = "enable" ssl.pemfile = "/path/to/server.pem"<% end %>[...]server.max-connections = <%= scope.function_options_lookup([server.max-connections,‘1024’]) %>server.server.max-keep-alive-idle = <%= scope.function_options_lookup([server.max-keep-alive-idle,‘5’]) %>server.max-request-size = <%= scope.function_options_lookup([server.max-request-size,‘0’]) %>server.max-read-idle = <%= scope.function_options_lookup([server.max-read-idle,‘60’]) %>server.max-write-idle = <%= scope.function_options_lookup([server.max-write-idle,‘360’]) %>server.kbytes-per-second = <%= scope.function_options_lookup([server.kbytes-per-second,‘128’]) %>server.connection.kbytes-per-second = <%= scope.function_options_lookup([connection.kbytes-per-second,‘32’]) %> git status #! modified: templates/lighttpd.conf.erb git add . git commit -m "Added sample lighttpd.conf template (not used by default)"
  16. 16. Add a define 1/2vi lighttpd/manifests/dotconf.ppdefine lighttpd::dotconf ( $source = , $template = , $options = , $ensure = present ) { $manage_file_source = $source ? { => undef, default => $source, } $manage_file_content = $template ? { => undef, default => template($template), } file { "Lighttpd_$name.conf": ensure => $ensure, path => "${lighttpd::config_dir}/${name}.conf", mode => $lighttpd::config_file_mode, owner => $lighttpd::config_file_owner, group => $lighttpd::config_file_group, require => Package[lighttpd], notify => $lighttpd::manage_service_autorestart, source => $manage_file_source, content => $manage_file_content, audit => $lighttpd::manage_audit, } git status} #! modified: manifests/dotconf.pp
  17. 17. Add rspec test for a definevi spec/defines/lighttpd_dotconf_spec.rbrequire "#{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. 18. Run Testscd 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 --colorRun 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.ppWARNING: line has more than 80 characters on line 108WARNING: line has more than 80 characters on line 437### ./manifests/params.pp### ./manifests/spec.pp
  19. 19. Job DoneModule 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. 20. Was it too fast?Get the module:http://github.com/example42/puppet-lighttpd.gitReview these slides:http://slideshare.net/alvaganteFollow Up on Twitter:@alvagante

×