Slide 1

Slide 1 text

Complete Beginners' Guide to Puppet - Through Types!

Slide 2

Slide 2 text

Guide to Puppet - Through Types!

Slide 3

Slide 3 text

whoami Igor Galić igalic (gh/irc) @hirojin (twitter)

Slide 4

Slide 4 text

whoami

Slide 5

Slide 5 text

how i got here ✈

Slide 6

Slide 6 text

how i got here c ... bash ... perl linux ... make ... ansible puppet

Slide 7

Slide 7 text

how i got here

Slide 8

Slide 8 text

why this talk exists

Slide 9

Slide 9 text

why this talk exists

Slide 10

Slide 10 text

dijkstra "The art of programming is the art of organizing complexity, of mastering multitude and avoiding its bastard chaos as effectively as possible."

Slide 11

Slide 11 text

dijkstra "Simplicity is a great virtue but it requires hard work to achieve it and education to appreciate it. And to make matters worse: complexity sells better."

Slide 12

Slide 12 text

nooop include 'ssh'

Slide 13

Slide 13 text

hiera class { 'ssh': permit_root_login => false, }

Slide 14

Slide 14 text

include include 'ssh'

Slide 15

Slide 15 text

resources igalic@levix ~ % puppet resource user igalic user { 'igalic': ensure => 'present', comment => 'Igor Galić,,,', gid => '1000', groups => ['adm', 'cdrom', 'sudo', 'dip', 'plugdev', 'lpadmin', 'sambashare', ' home => '/home/igalic', shell => '/bin/zsh', uid => '1000', } igalic@levix ~ %

Slide 16

Slide 16 text

differences dsl detail types & providers nope access to the RAL yupp sub-types branching impl diff platforms providers same/same contract/impl type/provider "easy" overload $name messy

Slide 17

Slide 17 text

defined type define trafficserver::config::records ( $changes = [ $title ], ) { include 'trafficserver' $configfile = "${::trafficserver::sysconfdir}/records.config" $lens = 'Trafficserver_records.lns' $context = "/files${configfile}" $incl = $configfile augeas { "${lens}_${title}": lens => $lens, context => $context, incl => $incl, changes => $changes, notify => Exec[trafficserver-config-reload], } }

Slide 18

Slide 18 text

symmetry @@trafficserver_record { 'proxy.config.http.server_ports': changes => '80:ipv4 80:ipv6', }

Slide 19

Slide 19 text

"simple" type Puppet::Type.newtype(:trafficserver_record) do desc 'trafficserver_record is a type to manage records.config entries' newparam(:record, :namevar => true) do desc "record entry" end newproperty(:value) do desc "Value of this record" end end

Slide 20

Slide 20 text

intermezzo

Slide 21

Slide 21 text

"simple" provider Puppet::Type.type(:trafficserver_record).provide(:traffic_line) do desc 'Manage traffic server records.config entries using traffic_line command' commands :traffic_line => 'traffic_line' mk_resource_methods ConfigPattern = 'proxy.(config|local|cluster).*' def initialize(value={}) super(value) end def name=(value) @property_hash[:name] = value end # this method is only called when value isn't insync? def value=(value) @property_hash[:name] = resource[:name]

Slide 22

Slide 22 text

intermezzo

Slide 23

Slide 23 text

defined type define git::config( $value, $section = regsubst($name, '^([^\.]+)\.([^\.]+)$','\1'), $key = regsubst($name, '^([^\.]+)\.([^\.]+)$','\2'), $user = 'root', ) { exec{"git config --global ${section}.${key} '${value}'": environment => inline_template('<%= "HOME=" + ENV["HOME"] %>'), path => ['/usr/bin', '/bin', '/usr/local/bin'], user => $user, unless => "git config --global --get ${section}.${key} '${value}'", } }

Slide 24

Slide 24 text

implementation (wrong) exec{"git config --global ${section}.${key} '${value}'": environment => inline_template('<%= "HOME=" + ENV["HOME"] %>'), path => ['/usr/bin', '/bin', '/usr/local/bin'], user => $user, unless => "git config --global --get ${section}.${key} '${value}'", }

Slide 25

Slide 25 text

type Puppet::Type.newtype(:git_config) do validate do fail('it is required to pass "value"') if self[:value].nil? || self[:value].em end newparam(:name) do desc "The default namevar" end newparam(:user) do desc "The user for which the config will be set. Default value: root" defaultto "root" end newparam(:section, :namevar => true) do desc "The configuration section. Example: user." end newparam(:key, :namevar => true) do desc "The configuration key. Example: email." end

Slide 26

Slide 26 text

implementation (correct) Puppet::Type.type(:git_config).provide(:git_config) do mk_resource_methods def check_current?(value) require 'etc' user = @resource[:user] key = @resource[:key] section = @resource[:section] home = Etc.getpwnam(user)[:dir] current = Puppet::Util::Execution.execute( "git config --global --get #{section}.#{key}", :uid => user, :failonfail => false, :custom_environment => { 'HOME' => home } ) return value == current.strip end def update

Slide 27

Slide 27 text

done

Slide 28

Slide 28 text

references puppet types and providers by Dan Bode & Nan Liu shit gary larizza says, e.g.: http://garylarizza.com/blog/2013 /12/15/seriously-what-is-this-provider-doing/ <3 ADRIEN THEBO <3 Morgan Haskel <3 Ashley Penney