@ü.li: Listing 1: Puppetlabs-Modul für einen HAProxy @li:class profile::wordpress::loadbalancer { class { 'haproxy': } haproxy::listen { 'wordpress': collect_exported => true, ipaddress => $::ipaddress, ports => '80', } } class profile::wordpress::balancermemeber { @@haproxy::balancermember { $::fqdn: listening_service => 'wordpress', server_names => $::fqdn, ipaddresses => $::ipaddress, ports => '80', options => 'check', } } class role::wordpress::app { contain profile::wordpress::app contain profile::wordpress::balancermemeber } class role::wordpress::balancer { contain profile::wordpress::loadbalancer } node 'haproxy' { contain role::wordpress::balancer } node /webserver\d+/ { contain role::webserver } @ü.li: Listing 2: Host dekommissionieren per PuppetDB-REST-API @li:curl -X POST -H "Accept: application/json" \ -H "Content-Type: application/json" \ -d '{ \ "command":"deactivate node", \ "version":3, \ "payload":{"certname":""} \ }' \ 'http://localhost:8080/pdb/cmd/v1' @ü.li: Listing 3: Verzeichnisstruktur bei Custom facts @li:/ lib/ |- facter/ # custom facts | `- .rb |- puppet/ | |- parser/ | | `- functions/ # custom functions (Puppet 3 style functions) | | `- .rb | |- type/ # custom types | | `- .rb | |- provider/ # custom provier | | `- / | | `- .rb | `- functions/ # custom functions (Puppet 4 functions) | `- .rb `- facts.d/ # Facter-Erweiterungen |- .txt `- .json @ü.li: Listing 4: Beispiel einer rvalue-Funktion @li:#/lib/puppet/parser/functions/heise_fqdn_to_ip_resolver.rb require 'resolv' module Puppet::Parser::Functions newfunction(:heise_fqdn_to_ip_resolver, :type => :rvalue) do |args| begin Resolv.getaddress(args.first) rescue raise Puppet::ParseError, "can not get address for name #{args.first}" end end end @ü.li: Listing 5:Typenvalidierung mit der dispatch-Methode @li:#/lib/puppet/functions/heise_resolver.rb require 'resolv' require 'socket' Puppet::Functions.create_function(:heise_resolver) do dispatch :ip_param do param 'Pattern[/^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$/]', :ip_param end dispatch :fqdn_param do param 'Pattern[/^([a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,}$/]', :fdqn end dispatch :no_param do end def fqdn_param(fqdn) begin Resolv.getaddress(fqdn) rescue raise Puppet::ParseError, "can not get address for name #{fqdn}" end end def ip_param(ip) begin Resolv.getname(ip) rescue raise Puppet::ParseError, "can not get address for IP #{ip}" end end def no_param Socket.gethostname end end @ü.li: Listing 6:Control-Repository für r10k @li:#/etc/puppetlabs/r10k/r10k.yaml --- cachedir: '/var/cache/r10k' sources: operations: remote: 'git.heise.de:/r10k' basedir: '/etc/puppetlabs/code/environments' git: provider: 'shellgit' # Either 'shellgit' or 'rugged', defaults to 'shellgit' #private_key: '/root/.ssh/id_rsa' #username: 'git' forge: #proxy: 'http://my.site.proxy:3128' @ü.li: Listing 7: Profile (Implementierungsmodule) anlegen @li:cd /root/repos/profile # manifests/puppetdb.pp class profile::puppetdb { class { '::puppetdb': manage_firewall => false, } class { '::puppetdb::master::config': manage_report_processor => true, enable_reports => true, } } # manifests/puppetexplorer.pp class profile::puppetexplorer { contain ::puppetexplorer # Bugfix: Reihenfolge Apt Repo und Package Apt::Source[puppetexplorer] -> Package[puppetexplorer] } git add . git commit git push origin master git tag '0.0.1' git push origin --tags @ü.li: Listing 8: Rolle für PuppetDB mit Puppet Explorer @li:cd ../role # manifests/puppetserver.pp class role::puppetserver { contain profile::puppetdb contain profile::puppetexplorer } git add . git commit git push origin master git tag '0.0.1' git push origin --tags cd ../r10k git checkout development # Puppetfile mod 'puppetdb', :ref => '5.0.0' mod 'apache', :ref => '1.6.0' # die neuren Versionen haben einen Bug mod 'apt', :ref => '2.2.1' mod 'concat', :ref => '2.0.1' mod 'stdlib', :ref => '4.9.1' mod 'postgresql', :ref => '4.6.1' mod 'inifile', :ref => '1.4.3' mod 'puppetexplorer', :ref => '1.0.1' mod 'role', :git => 'file:///var/repositories/modules/role', :ref => '0.0.1' mod 'profile', :git => 'file:///var/repositories/modules/profile', :ref => '0.0.1' # manifests/site.pp # die Rolle Puppet Explorer dem Puppet Server Node zuweisen node default { contain role::puppetserver } git add . git commit git push origin development @ü.li: Listing 9: Unit-Tests am Beispiel des my_apache-Moduls @li:# # my_apache/manifests/init.pp class my_apache ( String $pkgname = $my_apache::params::pkgname, Pattern[/^\/.*$/] $cfgdir = $my_apache::params::cfgdir, Pattern[/.*\.conf$/] $cfgfile = $my_apache::params::cfgfile, String $svcname = $my_apache::params::svcname, ) inherits my_apache::params { package { 'apache': ensure => present, name => $pkgname, } file { 'apache_cfg': ensure => file, path => "${cfgdir}/${cfgfile}", owner => 'root', group => 'root', mode => '0644', content => epp('my_apache/apache_config.epp'), #source => "puppet:///modules/my_apache/${cfgfile}", require => Package['apache'], } service { 'apache': ensure => running, enable => true, name => $svcname, subscribe => File['apache_cfg'], } } # # my_apache/manifests/params.pp class my_apache::params { case $::os['family'] { 'Debian': { $pkgname = 'apache2' $cfgdir = '/etc/apache2' $cfgfile = 'apache2.conf' $svcname = 'apache2' $runuser = 'www-data' $rungroup = 'www-data' } 'RedHat': { $pkgname = 'httpd' $cfgdir = '/etc/httpd/conf' $cfgfile = 'httpd.conf' $svcname = 'httpd' $runuser = 'apache' $rungroup = 'apache' } default: { fail("Das Betriebssystem ${::operatingsystem} wird nicht unterstützt") } } } # # my_apache/manifests/vhost.pp define my_apache::vhost ( Pattern[/\/.*$/] $docroot = '/var/www/html', Integer $port = 80, ){ file { "vhostcfg_${title}": ensure => file, path => "${my_apache::cfgdir}/vhost/${title}.cfg", content => epp('my_apache/vhost.epp'), } } # # my_apache/templates/apache.conf.epp # Security ServerTokens OS ServerSignature On TraceEnable On ServerName "<%= $fqdn %>" ServerRoot "<%= $my_apache::cfgdir %>" PidFile ${APACHE_PID_FILE} Timeout 120 KeepAlive Off MaxKeepAliveRequests 100 KeepAliveTimeout 15 User <%= $my_apache::runuser %> Group <%= $my_apache::rungroup %> AccessFileName .htaccess Require all denied Options FollowSymLinks AllowOverride None HostnameLookups Off ErrorLog "/var/log/apache2/error.log" LogLevel warn EnableSendfile On Include "/etc/apache2/mods-enabled/*.load" Include "/etc/apache2/mods-enabled/*.conf" Include "/etc/apache2/ports.conf" LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined LogFormat "%h %l %u %t \"%r\" %>s %b" common LogFormat "%{Referer}i -> %U" referer LogFormat "%{User-agent}i" agent IncludeOptional "/etc/apache2/conf.d/*.conf" IncludeOptional "/etc/apache2/sites-enabled/*" IncludeOptional "<%= $my_apache::cfgdir %>/vhosts/*.conf" # # my_apache/templates/vhost.epp Listen <%= $my_apache::vhost::port %> > ServerName <%= $my_apache::vhost::title %> ServerAdmin root@localhost ## Vhost docroot DocumentRoot "<%= $my_apache::vhost::docroot %>" ## Directories, there should at least be a declaration for /var/www "> Options Indexes FollowSymLinks MultiViews AllowOverride None Require all granted ## Logging ErrorLog "/var/log/apache2/<%= $my_apache::vhost::title %>_error.log" ServerSignature Off CustomLog "/var/log/apache2/<%= $my_apache::vhost::title %>access.log" combined ## Script alias directives ScriptAlias /cgi-bin "/usr/lib/cgi-bin" @ü.li: Listing 10: Erster Rake-Test @li:# spec/classes/my_apache_spec.rb require 'spec_helper' describe 'my_apache', :type => :class do context "on a Debian OS" do let :facts do { :os => { 'family' => 'Debian', }, } end it { should compile.with_all_deps } end end @ü.li: Listing 11: spec-Rake-Task @li:bundle exec rake spec Cloning into 'spec/fixtures/modules/stdlib'... remote: Counting objects: 441, done. remote: Compressing objects: 100% (317/317), done. remote: Total 441 (delta 154), reused 256 (delta 108), pack-reused 0 Receiving objects: 100% (441/441), 190.16 KiB | 0 bytes/s, done. Resolving deltas: 100% (154/154), done. Checking connectivity... done. /opt/puppetlabs/puppet/bin/ruby -I/root/repos/my_apache/vendor/ruby/2.1.0/gems/rspec-core-3.4.1/lib:/root/repos/my_apache/vendor/ruby/2.1.0/gems/rspec-support-3.4.1/lib /root/repos/my_apache/vendor/ruby/2.1.0/gems/rspec-core-3.4.1/exe/rspec --pattern spec/\{classes,defines,unit,functions,hosts,integration,types\}/\*\*/\*_spec.rb --color . Finished in 1.52 seconds (files took 0.66088 seconds to load) 1 example, 0 failures