puppetcamp ghent - what not to do with puppet

29
Puppet: What _not_ to do? An interactive journey through the ugly side of Puppet

Upload: olindata

Post on 25-Dec-2014

230 views

Category:

Technology


1 download

DESCRIPTION

An interactive journey through the ugly side of Puppet by Walter Heck, founder & CEO of OlinData, who presented at PuppetCamp Ghent 2013.

TRANSCRIPT

Page 1: PuppetCamp Ghent - What Not to Do with Puppet

Puppet: What_not_ to do?An interactive journey through the ugly side

of Puppet

Page 2: PuppetCamp Ghent - What Not to Do with Puppet

Walter Heck, Founder of OlinData

2,5 years experience with Puppet in 5+different environments

Experienced Puppet Fundamentals trainer

Had my eyes bleed many times with uglyPuppet code

Page 3: PuppetCamp Ghent - What Not to Do with Puppet

Design mistakesmight not be glaringly obvious or evenwrong at first, but will cause trouble later

Language mistakesPuppet provides functionality thatshouldn't be used, but is there for edge-cases or historical purposes

Page 4: PuppetCamp Ghent - What Not to Do with Puppet

Wake up...

Quiz time!

Page 5: PuppetCamp Ghent - What Not to Do with Puppet

== File: modules/ssh/manifests/ssh.pp

class ssh_install { package { 'ssh': ensure => present }}

class ssh_configure { file { '/etc/ssh/sshd_config': ensure => present }}

Page 6: PuppetCamp Ghent - What Not to Do with Puppet

== File: modules/ssh/manifests/ssh.pp

class ssh($state = ‘present’ { package { 'ssh': ensure => $state }

file { '/etc/ssh/sshd_config': ensure => $state }}

# problem: classnames won't be autoloaded, classnames shouldn't have verbs in them,classes should be combined, don't put multiple classes in a file

Page 7: PuppetCamp Ghent - What Not to Do with Puppet

==

schedule { 'maint': range => '2 - 4', period => daily, repeat => 1,}

exec { '/usr/bin/apt-get update': schedule => 'maint',}

Page 8: PuppetCamp Ghent - What Not to Do with Puppet

==

schedule { 'maint': range => '2 - 4', period => daily, repeat => 1,}exec { '/usr/bin/apt-get update': schedule => 'maint',}# problem: schedule doesn't mean something will execute, a common pitfall. If there is no puppet run between these hours, the apt-get exec will not be run

Page 9: PuppetCamp Ghent - What Not to Do with Puppet

==$myvar = ‘false’

if ($myvar) { notice(‘this is true’)} else { notice(‘This is false’)}

Page 10: PuppetCamp Ghent - What Not to Do with Puppet

==$myvar = ‘false’

if ($myvar) { notice(‘this is true’)} else { notice(‘This is false’)}#problem: 'false' evaluates totrue

Page 11: PuppetCamp Ghent - What Not to Do with Puppet

==

exec { '/etc/init.d/apache start': onlyif => ‘ps aux | grep apache | grep -v grep |wc -l’}

Page 12: PuppetCamp Ghent - What Not to Do with Puppet

==

exec { '/etc/init.d/apache start': onlyif => ‘ps aux | grep apache | grep -v grep |wc -l’}

# problem: this shouldn't be an exec, but aservice

Page 13: PuppetCamp Ghent - What Not to Do with Puppet

==

package { 'ssh': ensure => present, name => $::operatingsystem ? { 'Ubuntu' => 'openssh-server', default => 'ssh', },}

Page 14: PuppetCamp Ghent - What Not to Do with Puppet

== $sshpkgname = $::operatingsystem ? { 'Ubuntu' => 'openssh-server', default => undef,}

if ($sshpkgname == undef) { fail(‘unsupported OS’)} else { package { 'ssh': ensure => present, name => $sshpkgname, }}

#problem: they encourage behaviour that is not scalable, using default options toassume things, etc.

Page 15: PuppetCamp Ghent - What Not to Do with Puppet

==case $::operatingsystem { 'RedHat', 'CentOS': { file { ‘/etc/httpd/http.conf’: ensure => ‘present’, } } default: { file { ‘/etc/apache2/apache2.conf’: ensure => ‘present’, } } }

Page 16: PuppetCamp Ghent - What Not to Do with Puppet

==case $::operatingsystem { 'RedHat', 'CentOS': { file { ‘/etc/httpd/http.conf’: ensure => ‘present’, } } default: { file { ‘/etc/apache2/apache2.conf’: ensure => ‘present’, } } }#problem: case without default that fails, instead it assumes

Page 17: PuppetCamp Ghent - What Not to Do with Puppet

==class wordpress {

$wordpress_archive = 'wordpress-3.4.1.zip'

$apache = $::operatingsystem ? { Ubuntu => apache2, CentOS => httpd, Debian => apache2, default => httpd }

$phpmysql = $::operatingsystem ? { Ubuntu => php5-mysql, CentOS => php-mysql, Debian => php5-mysql, default => php-mysql }

$php = $::operatingsystem ? { Ubuntu => libapache2-mod-php5, CentOS => php, Debian => libapache2-mod-php5, default => php }

package { ['unzip',$apache,$php,$phpmysql]: ensure => latest }}

Page 18: PuppetCamp Ghent - What Not to Do with Puppet

==class wordpress {

$wordpress_archive == 'wordpress-3.4.1.zip'

$apache == $::operatingsystem ? { Ubuntu => apache2, CentOS => httpd, Debian => apache2, defaultdefault => httpd }

$phpmysql == $::operatingsystem ? { Ubuntu => php5-mysql, CentOS => php-mysql, Debian => php5-mysql, defaultdefault => php-mysql }

$php == $::operatingsystem ? { Ubuntu => libapache2-mod-php5, CentOS => php, Debian => libapache2-mod-php5, defaultdefault => php }

packagepackage { ['unzip',$apache,$php,$phpmysql]: ensure => latest }}#wordpress class shouldn't touch apache, should be a different module

Page 19: PuppetCamp Ghent - What Not to Do with Puppet

== $files = [ '/etc/mysql', '/var/log/mysql','/var/run/mysql' ]

file { $files: ensure => present, user => mysql, group => mysql, mode => 0755,}

Page 20: PuppetCamp Ghent - What Not to Do with Puppet

== #arrays of resources are not wrong, but dangerous.

file { '/etc/mysql': ensure => present, user => mysql, group => mysql, mode => 0700, <=== careful with this!}

file { '/var/log/mysql': ensure => present, user => mysql, group => mysql, mode => 0755,}

file { '/var/run/mysql': ensure => present, user => mysql, group => mysql, mode => 0755,}

Page 21: PuppetCamp Ghent - What Not to Do with Puppet

==

if defined(File['/tmp/foo']) { notify('This configuration includes the /tmp/foo file.')} else { file {'/tmp/foo': ensure => present, }}

Page 22: PuppetCamp Ghent - What Not to Do with Puppet

==class test {

if defined(File['/tmp/foo']) { notice('This configuration includes the /tmp/foo file.') } else { file {'/tmp/foo': ensure => present, group => root } }

if defined(File['/tmp/foo']) { notice('This configuration includes the /tmp/foo file.') } else { file {'/tmp/foo': ensure => present, group => puppet } }}

include test

defined() is (usually) the wrong solution to a resource defined in two locations. It isdangerous, because it only checks if the resource has been defined elsewhere, not withwhat attributes.

Page 23: PuppetCamp Ghent - What Not to Do with Puppet

==

class apache2 {

file { '/etc/apache2': ensure => directory, require => Service['apache2'] }

file { '/etc/apache2/apache2.conf': ensure => present, require => File['/etc/apache2'], notify => Service['apache2'],}

package { 'apache2': ensure => present, allowcdrom => true, before => File['/etc/apache2/apache2.conf']}

service { 'apache2': ensure => running, subscribe => File['/etc/apache2/apache2.conf']}}

include apache2

Page 24: PuppetCamp Ghent - What Not to Do with Puppet

==# dependency loop

class apache2 {

file { '/etc/apache2': ensure => directory, require => Service['apache2'] }

file { '/etc/apache2/apache2.conf': ensure => present, require => File['/etc/apache2'], notify => Service['apache2'], # <=== The notify metaparameter implies before.}

package { 'apache2': ensure => present, allowcdrom => true, before => File['/etc/apache2/apache2.conf']}

service { 'apache2': ensure => running, subscribe => File['/etc/apache2/apache2.conf'] # <=== The subscribe metaparameter impliesrequire.

}

Page 25: PuppetCamp Ghent - What Not to Do with Puppet

class test {

file { '/tmp/somefile.txt': ensure => 'file', mode => 0600, owner => 'root', group => 'root', source => '/etc/puppet/modules/test/somefile.txt' }

}

include test

Page 26: PuppetCamp Ghent - What Not to Do with Puppet

==

# use puppet:///modules/ instead of the full path on the puppet master

class test {

file { '/tmp/somefile.txt': ensure => 'file', mode => 0600, owner => 'root', group => 'root', source => 'puppet:///modules/test/somefile.txt' }

}

include test

Page 27: PuppetCamp Ghent - What Not to Do with Puppet

==class test { file {‘/tmp/large/dir/with/many/subdirs/and/many/files’: ensure => present, owner => root, group => root, recurse => true }}

include test

Page 28: PuppetCamp Ghent - What Not to Do with Puppet

==

# do not use recurse => true on a dir with over 100+ files

class test {

file {‘/tmp/large/dir/with/many/files’: ensure => present, owner => root, group => root, recurse => true }}

include test

# alternative :’(

class test {

exec {'/bin/chown -R root:root /tmp/large/dir/with/many/files': }}

include test

Page 29: PuppetCamp Ghent - What Not to Do with Puppet

Questions? Feel free to get in touch!

Walter Heck - OlinDataEmail: [email protected]: @walterheck / @olindata

Web: http://olindata.com