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

Absolute Beginners Guide to Puppet Through Types

Igor Galić
September 23, 2014

Absolute Beginners Guide to Puppet Through Types

When we teach people Puppet, we usually start from the DSL: Here's how you can create a file. This is how you add a user. You can install all kinds of packages. Then as soon as they discover `exec`, it all goes downhill for those who think it's just like bash!

Puppet's true power lies in its types. Rather than trying to shield beginners from those, we want to expose them to types as early as possible.

In this [failed] experiment, I want to do exactly that. I invite complete beginners to join us and learn more about Puppet's internals. Once we're able to answer the "why", the "how" will come naturally!

http://puppetconf2014.sched.org/event/a31d2618732af4046cbc474e71030c41

Igor Galić

September 23, 2014
Tweet

More Decks by Igor Galić

Other Decks in Technology

Transcript

  1. how i got here c ... bash ... perl linux

    ... make ... ansible puppet
  2. dijkstra "The art of programming is the art of organizing

    complexity, of mastering multitude and avoiding its bastard chaos as effectively as possible."
  3. 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."
  4. 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 ~ %
  5. 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
  6. 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], } }
  7. "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
  8. "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]
  9. 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}'", } }
  10. 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}'", }
  11. 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
  12. 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
  13. 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 </3 Hunter Haugen <3 pry <3 https://github.com/Brainsware/puppet-trafficserver https://github.com/puppetlabs/puppetlabs-git