Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Puppet For Developers

Puppet For Developers

How to not fuck off your future sysadmin - a whirlwind tour of puppet and how to start automating your server configuration.

Daniel Knell

February 18, 2013
Tweet

More Decks by Daniel Knell

Other Decks in Programming

Transcript

  1. Resources package { "nodejs": ensure => present } file {

    "/etc/motd": ensure => present, content => "HELLO!" } service { "redis-server": ensure => running }
  2. Variables $greeting = "HELLO" $ensure = present file { "/etc/motd":

    ensure => $ensure, content => "${greeting} WORLD!" }
  3. Classes class nodejs ($ensure = present) { package { "nodejs":

    ensure => $ensure } } class { "nodejs": ensure => present } include nodejs
  4. Nodes node "www.example.com" { include nodejs } node "www01.example.com", "www02.example.com",

    "www03.example.com" { include nodejs } node /^www\d+\.example\.com/ { include nodejs } node "default" { include nodejs }
  5. Facter $ facter architecture => x86_64 domain => local facterversion

    => 1.6.17 fqdn => Obsidian.local hardwareisa => i386 hardwaremodel => x86_64 hostname => Obsidian id => daniel interfaces => lo0,gif0,stf0,en0,p2p0,vboxnet0,vboxnet1,utun1,utun0 ipaddress => 10.0.1.8 ipaddress6 => fd29:252f:ec95:f2ff:f4ba:3854:6dd:ea40 ipaddress_en0 => 10.0.1.8 ipaddress_lo0 => 127.0.0.1 ipaddress_vboxnet0 => 192.168.33.1 ipaddress_vboxnet1 => 172.16.0.1 is_virtual => false kernel => Darwin kernelmajversion => 12.2 kernelrelease => 12.2.1 kernelversion => 12.2.1
  6. Facts class custom_motd { file { "/etc/motd": ensure => present,

    content => "Welcome to ${::hostname}!" } }
  7. Files # /etc/puppet/modules/custom_motd/manifests/init.pp class custom_motd { file { "/etc/motd": ensure

    => present, source => "puppet:///custom_motd/motd" } } # /etc/puppet/modules/custom_motd/files/motd Hello!
  8. Templates # /etc/puppet/modules/custom_motd/manifests/init.pp class custom_motd { file { "/etc/motd": ensure

    => present, content => template("custom_motd/motd.erb") } } # /etc/puppet/modules/custom_motd/templates/motd.erb Welcome to <%= @hostname %>!
  9. Custom Resource Types # /etc/puppet/modules/nginx/manifests/site.pp define nginx::site ( $aliases )

    { file { "/etc/nginx/conf/sites/${name}": ensure => present, content => template("nginx/site.erb") } file { "/var/www/${name}": ensure => directory } } # /etc/puppet/modules/websites/manifests/example.pp class websites::example { nginx::site { "www.example.com": aliases => [ "example.com" ] } }
  10. RSpec Puppet # /etc/puppet/modules/ntp/spec/classes/ntp_spec.rb require 'spec_helper' describe 'ntp', :type =>

    :class do it { should include_class('ntp') } it do should contain_file('ntp::config').with({ :ensure => 'present', :path => '/etc/ntp.conf' }) end context "with ensure => absent" do let(:params) { {:ensure => 'absent'} } it { should contain_package('ntp').with_ensure('absent') } it { should_not contain_service('ntp') } it { should contain_file('ntp::config').with_ensure('absent') } end end
  11. RSpec Puppet $ rake spec /usr/local/Cellar/ruby/1.9.3-p286/bin/ruby -S rspec spec/classes/ ntp_spec.rb

    ....F...................................................................... Failures: 1) ntp with discard => 'average 3 minimum 1' Failure/Error: it { should contain_file('ntp::config').with_content(content) } expected that the catalogue would contain File[ntp::config] with content matching `/discard average 3 minimum 1\n/` but its value of `"discard !!BROKEN!! average 3 minimum 1\n"` does not # ./spec/classes/ntp_spec.rb:30:in `block (3 levels) in <top (required)>' Finished in 3.54 seconds 75 examples, 1 failure Failed examples: rspec ./spec/classes/ntp_spec.rb:30 # ntp with discard => 'average 3 minimum 1'
  12. • redis/ • manifests/ • init.pp • files/ • config

    • spec/ • classes/ • redis_spec.rb • spec_helper.rb Module
  13. Manifest # modules/redis/manifests/init.pp class redis { package { ‘redis-server’: ensure

    => present } file { ‘/etc/redis.conf’: ensure => present, source => ‘puppet:///redis/config’, require => Package[‘redis-server’], notify => Service[‘redis-server’] } service { ‘redis-server’: ensure => running require => File[‘/etc/redis.conf’] } }
  14. Spec # /etc/puppet/modules/redis/spec/classes/redis_spec.rb require 'spec_helper' describe 'ntp', :type => :class

    do it { should include_class('ntp') } it do should contain_package('redis-server').with({ :ensure => 'present' }) end it do should contain_file('/etc/redis.config').with({ :ensure => 'present', :source => 'puppet:///redis/config' }) end it do should contain_service('redis-server').with({ :ensure => 'running' }) end end
  15. Spec Helper # /etc/puppet/modules/redis/spec/spec_helper.rb require 'rspec-puppet' fixture_path = File.expand_path(File.join(__FILE__, '..',

    'fixtures')) RSpec.configure do |c| c.module_path = File.join(fixture_path, 'modules') c.manifest_dir = File.join(fixture_path, 'manifests') end
  16. File # Redis configuration file example # Note on units:

    when memory size is needed, it is possible to specify # it in the usual form of 1k 5GB 4M and so forth: # # 1k => 1000 bytes # 1kb => 1024 bytes # 1m => 1000000 bytes # 1mb => 1024*1024 bytes # 1g => 1000000000 bytes # 1gb => 1024*1024*1024 bytes # # units are case insensitive so 1GB 1Gb 1gB are all the same. # By default Redis does not run as a daemon. Use 'yes' if you need it. # Note that Redis will write a pid file in /var/run/redis.pid when daemonized. daemonize no # When running daemonized, Redis writes a pid file in /var/run/redis.pid by # default. You can specify a custom pid file location here.
  17. Links • Puppet Labs - http://puppetlabs.com/ • Hiera - http://projects.puppetlabs.com/projects/hiera

    • Librarian Puppet - http://librarian-puppet.com/ • Puppet Forge - http://forge.puppetlabs.com/ • Puppet Lint - http://puppet-lint.com/ • RSpec Puppet - http://rspec-puppet.com/ • Vagrant - http://vagrantup.com/ • Boxen - http://boxen.github.com/