class: center, middle, inverse # Puppet
Hacks ??? --- class: center, middle, inversedoubleheading # Puppet Hacks ##
you didn't know you were looking for ??? --- ## $ whoami
* Tim 'bastelfreak' Meusel * Puppet Contributor since 2012 * Merging stuff on [Vox Pupuli](https://voxpupuli.org/) (Puppet Community) since 2015 * Vox Pupuli Project Management Committee member * Senior IT Automation Consultant at [betadots](https://betadots.de/)
??? * who has seen this picture before because I reviewed/merged your pull request? --- class: center, middle, inverse # Resource Abstraction
Layer ??? --- .left-column[ ## RAL ] .right-column[ * Puppet uses RAL - Resource Abstraction Layer ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] ??? Who knows the RAL? --- .left-column[ ## RAL ] .right-column[ * Puppet uses RAL - Resource Abstraction Layer * Abstracts package manager away into Puppet resources ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] --- count: false .left-column[ ## RAL ] .right-column[ * Puppet uses RAL - Resource Abstraction Layer * Abstracts package manager away into Puppet resources * Implemented via types and providers ```puppet package { 'htop': ensure => 'installed', } ``` ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] --- count: false .left-column[ ## RAL ] .right-column[ * Puppet uses RAL - Resource Abstraction Layer * Abstracts package manager away into Puppet resources * Implemented via types and providers ```puppet package { 'htop': ensure => 'installed', } ``` * List available types on CLI * `puppet resource --types` ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] ??? * Switch to terminal and show? Works as root/normal user --- .left-column[ ## RAL ### Find Resources ] .right-column[ * RAL can be triggered on the CLI! * `puppet resource package htop` ```puppet package { 'htop': ensure => '3.4.1-1', provider => 'pacman', } ``` ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] --- count: false .left-column[ ## RAL ### Find Resources ] .right-column[ * RAL can be triggered on the CLI! * `puppet resource package htop` ```puppet package { 'htop': ensure => '3.4.1-1', provider => 'pacman', } ``` * Can output all instances of a resource type * `puppet resource package` ```puppet package { 'yamllint': ensure => '1.33.0-1', provider => 'pacman', } package { 'yard': ensure => ['0.9.26'], provider => 'gem', } ``` ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] ??? * Puppet needs to know the current state of a resource before code is applied * required to detect if changes are needed * prefetch needs to be implemented in the provider * check yard ensure, array --- .left-column[ ## RAL ### Find Resources ### Modify Resources ] .right-column[ * Can modify a resource instance * `puppet resource package htop ensure=absent` ```puppet Notice: /Package[htop]/ensure: removed package { 'htop': ensure => 'absent', provider => 'pacman', } ``` ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] ??? * You can also pass the other parameters --- count: false .left-column[ ## RAL ### Find Resources ### Modify Resources ] .right-column[ * Can modify a resource instance * `puppet resource package htop ensure=absent` ```puppet Notice: /Package[htop]/ensure: removed package { 'htop': ensure => 'absent', provider => 'pacman', } ``` * Can modify a resource instance with debug output! * `puppet resource package htop ensure=absent --debug` ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] ??? --- count: false .left-column[ ## RAL ### Find Resources ### Modify Resources ] .right-column[ * Can modify a resource instance * `puppet resource package htop ensure=absent` ```puppet Notice: /Package[htop]/ensure: removed package { 'htop': ensure => 'absent', provider => 'pacman', } ``` * Can modify a resource instance with debug output! * `puppet resource package htop ensure=absent --debug` * Can simulate a change! * `puppet resource package htop ensure=absent --debug --noop` ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] ??? * Puppet CLI args like debug and noop can be passed to every `puppet resource package` --- .left-column[ ## RAL ### Find Resources ### Modify Resources ### Purge Resources ] .right-column[ * [puppet.com/docs/puppet/8/type#resources](https://www.puppet.com/docs/puppet/8/type#resources)  ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] ??? * Who knows the resources resource type? * Who used it? * Who likes it? * I took the screenshots some time ago in case perforce fucks up their docs. well they did now --- .left-column[ ## RAL ### Find Resources ### Modify Resources ### Purge Resources ] .right-column[ ```puppet resources { 'User': purge => true, } resources { 'Package': purge => true, } ``` ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] ??? * purge all users not managed by puppet * show resources.pp * Resource title has the resource capitalized --- count: false .left-column[ ## RAL ### Find Resources ### Modify Resources ### Purge Resources ] .right-column[ ```puppet resources { 'User': purge => true, } resources { 'Package': purge => true, } resources { 'Service': purge => true, noop => false, } ``` ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] ??? * noop is nice because it will inform you about unmanaged/unexpected resources * not so useful for packages or users * but what about database users * backends in your F5? --- .left-column[ ## RAL ### Find Resources ### Modify Resources ### Purge Resources ] .right-column[ * [forge.puppet.com/crayfishx/purge](https://forge.puppet.com/modules/crayfishx/purge/readme)  ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] --- .left-column[ ## RAL ### Find Resources ### Modify Resources ### Purge Resources ] .right-column[  ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] --- .left-column[ ## RAL ### Find Resources ### Modify Resources ### Purge Resources ] .right-column[  ```puppet tidy { '/tmp': age => '1w', recurse => 1, matches => [ '[0-9]pub*.tmp', '*.temp', 'tmpfile?' ], } ``` ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] ??? * uses the RAL to collect all files * applies the different matchers * purges all matching files * sucks, because it adds one file resource for each file to the catalog --- .left-column[ ## RAL ### Find Resources ### Modify Resources ### Purge Resources ] .right-column[ * Purging files and directories * [enterprisemodules.com/blog/2022/02/cleanup-temporary-files-in-puppet](https://www.enterprisemodules.com/blog/2022/02/cleanup-temporary-files-in-puppet/)  ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] ??? * works on dirs and and files * purges the files at the end of the catalog application, without any dependencies to file resources * best solution is a systemd timer or systemd tmpfs configuration --- .left-column[ ## RAL ] .right-column[ * Further documentation * https://petersouter.xyz/the-puppet-resource-abstraction-layer-ral-explained-part-1/ * https://www.puppet.com/docs/puppet/7/man/resource ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] --- class: center, middle, inverse # Puppet
Faces ??? --- .left-column[ ## Faces ] .right-column[ * https://puppetcommunity.slack.com/archives/C0W1X7ZAL/p1705520404613479?thread_ts=1705511900.536469&cid=C0W1X7ZAL  ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] ??? * An awesome way to extend the Puppet CLI * Allows you to access puppet as a lib --- .left-column[ ## Faces ] .right-column[ * Faces were "deprecated" but won't be removed: https://www.puppet.com/docs/puppet/5.5/deprecated_api.html * Kelsey Hightower explaining faces in 2011: https://www.youtube.com/watch?v=WUlYEJ-fpfU * Faces are used heavily within Puppet: https://github.com/puppetlabs/puppet/tree/main/lib/puppet/face ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] ??? --- count: false .left-column[ ## Faces ] .right-column[ * Faces were "deprecated" but won't be removed: https://www.puppet.com/docs/puppet/5.5/deprecated_api.html * Kelsey Hightower explaining faces in 2011: https://www.youtube.com/watch?v=WUlYEJ-fpfU * Faces are used heavily within Puppet: https://github.com/puppetlabs/puppet/tree/main/lib/puppet/face * "Puppet Applications" are the successor for Faces * [github.com/puppetlabs/puppet/blob/main/lib/puppet/application.rb](https://github.com/puppetlabs/puppet/blob/49d74c94c848d4d4f4d022b58ff8135b2f46e7b0/lib/puppet/application.rb#L10) ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] ??? --- .left-column[ ## Faces ### config ] .right-column[ * `puppet config print` * `puppet config print certname` * `puppet config print certname --section` * `puppet config set 'option' 'value' --section 'section'` * Valid sections: main, user, agent, server/master ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] ??? * config face is builtin * can read and write from puppet.conf * can disable defaults from the code that aren't in puppet.conf * identifies path to puppet.conf on its own --- .left-column[ ## Faces ### config ### catalog diff ] .right-column[ * [github.com/voxpupuli/puppet-catalog_diff](https://github.com/voxpupuli/puppet-catalog_diff/tree/master?tab=readme-ov-file#overview) * The tool can automatically compile the catalogs for both your new and older servers/environments. It can ask the master to use PuppetDB to compile the catalog for the last known environment with the last known facts. It can then validate against PuppetDB that the node is still active. This filtered list should contain only machines that have not been decommissioned in PuppetDB (important as compiling their catalogs would also reactive them and their exports otherwise). ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] ??? * `catalog` face exists in core, `catalog diff` is custom, maintained by Vox Pupuli --- .left-column[ ## Faces ### config ### catalog diff ] .right-column[ * `puppet catalog diff puppet.example.com/production puppet.example.com/staging --filter_old_env` * `puppet catalog diff /foo/old/node1.example.com.json /foo/new/node1.example.com.json` * [voxpupuli.org/puppet-catalog-diff-viewer](https://voxpupuli.org/puppet-catalog-diff-viewer/) ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] ??? * diff catalogs from PuppetDB or compile new ones * diff between environments * diff between different Puppet infrastructures * Visualize reports * deserves its own talk, Raphael did some in the past, linked in the README.md --- .left-column[ ## Faces ### config ### catalog diff ] .right-column[  ]
--- .left-column[ ## Faces ### config ### catalog diff ### node exports ] .right-column[ * provide a list of exported resources in PuppetDB * `watch 'puppet node exports'` * [forge.puppet.com/zack/exports](https://forge.puppet.com/modules/zack/exports/readme#example-usage) ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] --- count: false .left-column[ ## Faces ### config ### catalog diff ### node exports ] .right-column[ * provide a list of exported resources in PuppetDB * `watch 'puppet node exports'` * [forge.puppet.com/zack/exports](https://forge.puppet.com/modules/zack/exports/readme#example-usage) * Lists all exported resources * Can be filtered for resource types (for example File) ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] --- count: false .left-column[ ## Faces ### config ### catalog diff ### node exports ] .right-column[ * provide a list of exported resources in PuppetDB * `watch 'puppet node exports'` * [forge.puppet.com/zack/exports](https://forge.puppet.com/modules/zack/exports/readme#example-usage) * Lists all exported resources * Can be filtered for resource types (for example File) * Doesn't work properly with Puppet 8 :sadface:  ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] ??? It uses a deprecated HTTP client --- class: center, middle, inverse # Puppet
CLI ??? --- .left-column[ ## CLI ] .right-column[ * `puppet agent -t` ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] --- count:false .left-column[ ## CLI ] .right-column[ * `puppet agent -t` * `puppet agent --test` ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] ??? those are equal --- count:false .left-column[ ## CLI ] .right-column[ * `puppet agent -t` * `puppet agent --test` * `puppet agent --verbose --no-daemonize --no-usecacheonfailure --detailed-exitcodes --no-splay --show_diff` ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] --- count: false .left-column[ ## CLI ] .right-column[ * `puppet agent -t` * `puppet agent --test` * `puppet agent --verbose --no-daemonize --no-usecacheonfailure --detailed-exitcodes --no-splay --show_diff` * Who knows more CLI invocations? ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] ??? --- count: false .left-column[ ## CLI ] .right-column[ * `puppet agent -t` * `puppet agent --test` * `puppet agent --verbose --no-daemonize --no-usecacheonfailure --detailed-exitcodes --no-splay --show_diff` * Who knows more CLI invocations? * Some Options are only available on the CLI: `puppet agent --help` * Every config option can be set and overwritten on CLI: https://www.puppet.com/docs/puppet/8/configuration.html * `puppet agent -t --no-noop` ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] ??? * puppet.conf can be overwritten on CLI * See --no-splay above to disable options * Add noop=true to puppet.conf * when you want to apply changes, run with --no-noop --- .left-column[ ## CLI ### trace ] .right-column[ * `--trace` is a common option in the Ruby ecosystem * available in puppet faces as well  ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] ??? * Remember our error from earlier? It had no line/file information * now it has, exports.rb line 63 --- .left-column[ ## CLI ### trace ### debug ] .right-column[ * `puppet agent -t --debug` * Prints all HTTP calls to puppetserver * Lists all resources and if they are already in the desired state ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] ??? --- count:false .left-column[ ## CLI ### trace ### debug ] .right-column[ * `puppet agent -t --debug` * Prints all HTTP calls to puppetserver * Lists all resources and if they are already in the desired state * prints all debug messages * Facter: `Facter.debug('my debug text')` * Puppet Types/Provider: `Puppet.debug('my other debug text')` ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] ??? * Now we can extend our code with many debug messages * but what if we need to dig deep --- .left-column[ ## CLI ### trace ### debug ### http_debug ] .right-column[  ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] --- .left-column[ ## CLI ### trace ### debug ### http_debug ] .right-column[ * `puppet agent -t --http_debug` * Dumps every HTTP Payload and Headers from/to Puppetserver ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] --- count: false .left-column[ ## CLI ### trace ### debug ### http_debug ] .right-column[ * `puppet agent -t --http_debug` * Dumps every HTTP Payload and Headers from/to Puppetserver * As base64 ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] --- .left-column[ ## CLI ### trace ### debug ### http_debug ] .right-column[  ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] --- .left-column[ ## CLI ### trace ### debug ### http_debug ### evaltrace ] .right-column[ * `puppet agent -t --evaltrace` * prints all resources and their evaluation time  ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] ??? * Who knows that option? * naming things is hard. evaltrace written together. http_debug uses an underscore --- .left-column[ ## CLI ### trace ### debug ### http_debug ### evaltrace ] .right-column[ * `puppet agent -t --trace --evaltrace --debug --http_debug` * All options can be combined ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] --- count: false .left-column[ ## CLI ### trace ### debug ### http_debug ### evaltrace ] .right-column[ * `puppet agent -t --trace --evaltrace --debug --http_debug` * All options can be combined * You will need a very big screen! ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] ??? * This is a lot of output --- .left-column[ ## CLI ### trace ### debug ### http_debug ### evaltrace ### timing ] .right-column[ * `puppet facts show` # show all facts ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] --- count: false .left-column[ ## CLI ### trace ### debug ### http_debug ### evaltrace ### timing ] .right-column[ * `puppet facts show` # show all facts * `puppet facts show $fact` # show a single fact named fact ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] --- count: false .left-column[ ## CLI ### trace ### debug ### http_debug ### evaltrace ### timing ] .right-column[ * `puppet facts show` # show all facts * `puppet facts show $fact` # show a single fact named fact * `puppet facts show --timing` # timing per fact resolution ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] --- .left-column[ ## CLI ### trace ### debug ### http_debug ### evaltrace ### timing ] .right-column[  ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] --- class: center, middle, inverse # Design Pattern
and Hacks ??? --- .left-column[ ## Hacks & Patterns ### LLDP ] .right-column[ * LLDP - Link Layer Distribution Protocol * IEEE-802.1AB standard * exchange information between direct layer 2 peers * Common protocol for Routers, Switches *and servers* ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] --- count: false .left-column[ ## Hacks & Patterns ### LLDP ] .right-column[ * LLDP - Link Layer Distribution Protocol * IEEE-802.1AB standard * exchange information between direct layer 2 peers * Common protocol for Routers, Switches *and servers* * Linux: [github.com/lldpd/lldpd](https://github.com/lldpd/lldpd) * Puppet Module: [forge.puppet.com/puppet/lldpd](https://forge.puppet.com/modules/puppet/lldpd/readme) ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] --- .left-column[ ## Hacks & Patterns ### LLDP ] .right-column[  ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] ??? * VMs/Hypervisor run LLDP * VM knows on which HV it is running * Hypervisor knows to wich switches it's connected * Switches know which hypervisors and routers are connected * All those information can be stored to PuppetDB * the puppet module has a fact that exports the data * you can query PuppetDB to find out which devices are connected to each other and plot them live! * I would love to throw this into a graph database at some point --- .left-column[ ## Hacks & Patterns ### LLDP ### Puppet CA ] .right-column[ * [github.com/voxpupuli/puppet-puppet_ca_utils](https://github.com/voxpupuli/puppet-puppet_ca_utils) * Can crosssign Puppet CAs ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] ??? * Helpful if you've a new and old Infra and want to migrate agents * You can configure if Agents should be able to talk to both CAs or Agent from A only to A and B but B not do A --- count: false .left-column[ ## Hacks & Patterns ### LLDP ### Puppet CA ] .right-column[ * [github.com/voxpupuli/puppet-puppet_ca_utils](https://github.com/voxpupuli/puppet-puppet_ca_utils) * Can crosssign Puppet CAs * [github.com/voxpupuli/puppet-puppet_certificate](https://github.com/voxpupuli/puppet-puppet_certificate) * Allow Agents to renew their own certificate * Update CSR/SAN attributes ```puppet file { '/etc/puppetlabs/puppet/csr_attributes.yaml': ensure => file, owner => 'root', group => 'root', mode => '0440', content => epp('example/csr_attributes.yaml.epp'), } ~> puppet_certificate { $certname: ensure => present, waitforcert => 60, onrefresh => regenerate, } ``` ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] ??? --- count: false .left-column[ ## Hacks & Patterns ### LLDP ### Puppet CA ] .right-column[ * [github.com/voxpupuli/puppet-puppet_ca_utils](https://github.com/voxpupuli/puppet-puppet_ca_utils) * Can crosssign Puppet CAs * [github.com/voxpupuli/puppet-puppet_certificate](https://github.com/voxpupuli/puppet-puppet_certificate) * Allow Agents to renew their own certificate * Update CSR/SAN attributes ```puppet file { '/etc/puppetlabs/puppet/csr_attributes.yaml': ensure => file, owner => 'root', group => 'root', mode => '0440', content => epp('example/csr_attributes.yaml.epp'), } ~> puppet_certificate { $certname: ensure => present, waitforcert => 60, onrefresh => regenerate, } ``` * Puppet 8.2 supports auto cert renewal: [puppet.com/docs/puppet/8/release_notes](https://www.puppet.com/docs/puppet/8/release_notes_puppet#release_notes_puppet_x-8-2-0) ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] ??? --- .left-column[ ## Hacks & Patterns ### LLDP ### Puppet CA ] .right-column[ * Use PuppetCA for personal certificates * Use personal certificates to authenticate to local services * `puppet ssl bootstrap --certname "$(hostname -f)-${USER}"`  ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] ??? * Nginx for example can validate client TLS certificates * admins can use that for internal sites --- .left-column[ ## Hacks & Patterns ### LLDP ### Puppet CA ] .right-column[ * [github.com/m0dular/ca_extend](https://github.com/m0dular/ca_extend?tab=readme-ov-file#ca_extend) * Extend a Open Source CA ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] ??? --- count: false .left-column[ ## Hacks & Patterns ### LLDP ### Puppet CA ] .right-column[ * [github.com/m0dular/ca_extend](https://github.com/m0dular/ca_extend?tab=readme-ov-file#ca_extend) * Extend a Open Source CA * [github.com/puppetlabs/ca_extend](https://github.com/puppetlabs/ca_extend?tab=readme-ov-file#ca_extend) * Extend a PE CA ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] ??? --- count: false .left-column[ ## Hacks & Patterns ### LLDP ### Puppet CA ] .right-column[ * [github.com/m0dular/ca_extend](https://github.com/m0dular/ca_extend?tab=readme-ov-file#ca_extend) * Extend a Open Source CA * [github.com/puppetlabs/ca_extend](https://github.com/puppetlabs/ca_extend?tab=readme-ov-file#ca_extend) * Extend a PE CA * [My Shell script to extend a CA](https://gist.github.com/bastelfreak/034fca2e7719351fe42c28e7844dace5) ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] ??? --- .left-column[ ## Hacks & Patterns ### LLDP ### Puppet CA ### Clusterfoo ] .right-column[ * Use PuppetDB to dynamically build your clusters ```puppet # Get FQDNs for all cluster peers $query = "inventory[certname] { trusted.extensions.pp_role = 'consul' and trusted.extensions.pp_region = 'eu-01' }" $nodes = puppetdb_query($query).map |$value| { $value["certname"] } ``` ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] --- count: false .left-column[ ## Hacks & Patterns ### LLDP ### Puppet CA ### Clusterfoo ] .right-column[ * Use PuppetDB to dynamically build your clusters ```puppet # Get FQDNs for all cluster peers $query = "inventory[certname] { trusted.extensions.pp_role = 'consul' and trusted.extensions.pp_region = 'eu-01' }" $nodes = puppetdb_query($query).map |$value| { $value["certname"] } ``` ```puppet @@sshkey{$trusted['certname']: host_aliases => [$facts['ipaddress6'], $facts['ipaddress']], type => "ssh-${type}", key => $facts['ssh'][$type]['key'], # defaults to /etc/ssh/ so all users can use it #target => '/root/.ssh/known_hosts', tag => $trusted['extensions']['pp_role'], } ## import host key Sshkey <<| tag == $trusted['extensions']['pp_role'] and title != $trusted['certname'] |>> ``` ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] ??? * Often systems want a list of all backend systems, consul for example * Works of course for IPs and ssh_authorized_keys and others as well --- .left-column[ ## Hacks & Patterns ### LLDP ### Puppet CA ### Clusterfoo ### Updating PuppetDB ] .right-column[ * https://www.puppet.com/docs/puppet/7/configuration#resubmit-facts * `puppet config set resubmit_facts true` * `puppet agent -t --resubmit_facts` * Evaluate all facts *after* catalog application and send them to PuppetDB ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] ??? * by default, facts are only gathered and stored before the catalot is applied --- .left-column[ ## Hacks & Patterns ### LLDP ### Puppet CA ### Clusterfoo ### Updating PuppetDB ### puppetmoduleinfo ] .right-column[ * [www.puppetmodule.info/modules](https://www.puppetmodule.info/modules) * Similar to http://rubydoc.info/, puppetmodule.info renders puppet modules and puppet-strings annotations * static site with module documentation ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] ??? --- .left-column[ ## Hacks & Patterns ### LLDP ### Puppet CA ### Clusterfoo ### Updating PuppetDB ### puppetmoduleinfo ### healthchecks ] .right-column[ * [forge.puppet.com/puppet/healthcheck](https://forge.puppet.com/modules/puppet/healthcheck) * Types that block catalog application until a TCP or HTTP(S) connection is successful ```puppet tcp_conn_validator { 'foo-machine ssh service' : host => '192.168.0.42', port => 22, } ``` ```puppet http_conn_validator { 'foo-machine home' : host => '127.0.0.1', port => 8081, use_ssl => true, } ``` ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] ??? --- .left-column[ ## Hacks & Patterns ### LLDP ### Puppet CA ### Clusterfoo ### Updating PuppetDB ### puppetmoduleinfo ### healthchecks ### features ] .right-column[ * Facts can be confined to facts, a ruby code block, or a feature ```ruby # lib/facter/cem_inetd.rb Facter.add(:cem_inetd) do confine kernel: 'Linux' ... setcode do ... end end ``` ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] ??? --- .left-column[ ## Hacks & Patterns ### LLDP ### Puppet CA ### Clusterfoo ### Updating PuppetDB ### puppetmoduleinfo ### healthchecks ### features ] .right-column[ * Facts can be confined to facts, a ruby code block, or a feature ```ruby # lib/puppet/feature/cem_inetd.rb require 'puppet/util/feature' Puppet.features.add(:cem_inetd) do inetd = `sh -c 'command -v inetd'`.strip xinetd = `sh -c 'command -v xinetd'`.strip inetd.empty? && xinetd.empty? ? false : true end ``` ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] ??? --- .left-column[ ## Hacks & Patterns ### LLDP ### Puppet CA ### Clusterfoo ### Updating PuppetDB ### puppetmoduleinfo ### healthchecks ### features ] .right-column[ * Facts can be confined to facts, a ruby code block, or a feature ```ruby # lib/puppet/feature/awesome.rb require 'puppet/util/feature' Puppet.features.add(:awesome, libs: ['sinatra']) ``` ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] ??? --- .left-column[ ## Hacks & Patterns ### LLDP ### Puppet CA ### Clusterfoo ### Updating PuppetDB ### puppetmoduleinfo ### healthchecks ### features ] .right-column[ * Facts can be confined to facts, a ruby code block, or a feature ```ruby # lib/facter/cem_inetd.rb Facter.add(:cem_inetd) do confine kernel: 'Linux' confine { Puppet.features.cem_inetd? } confine { Puppet.features.awesome? } setcode do ... end end ``` ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] ??? --- count: false .left-column[ ## Hacks & Patterns ### LLDP ### Puppet CA ### Clusterfoo ### Updating PuppetDB ### puppetmoduleinfo ### healthchecks ### features ] .right-column[ * Facts can be confined to facts, a ruby code block, or a feature ```ruby # lib/facter/cem_inetd.rb Facter.add(:cem_inetd) do confine kernel: 'Linux' confine { Puppet.features.cem_inetd? } confine { Puppet.features.awesome? } setcode do ... end end ``` * Features can be referenced in provider as well * https://dev.to/puppet/features-the-forgotten-feature-of-puppet-12p2 * [Feature in puppet/zabbix module](https://github.com/voxpupuli/puppet-zabbix/blob/master/lib/puppet/feature/zabbixapi.rb) * [Using the feature in puppet/zabbix](https://github.com/voxpupuli/puppet-zabbix/blob/master/lib/puppet/provider/zabbix_application/ruby.rb#L6) ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] ??? --- class: center, middle, inverse # Conclusion
??? --- .left-column[ ## Conclusion ] .right-column[ * Puppet is very flexible and suiteable for different usecases * There are many hidden gems and extensions available * More docs from Puppet/Perforce for edgecases & advanced users would be awesome! ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] ??? * Need help with opensourcing your puppet modules or rubygems or CI setup? Let us know --- count: false .left-column[ ## Conclusion ] .right-column[ * Puppet is very flexible and suiteable for different usecases * There are many hidden gems and extensions available * More docs from Puppet/Perforce for edgecases & advanced users would be awesome! * For feedback: `bastelfreak` on
slack.puppet.com
/Libera.Chat IRC or [tim@bastelfreak.de](mailto:tim@bastelfreak.de) * This talk and previous ones:
github.com/bastelfreak/talks
### Thanks for your attention! ]
.footnote[[bastelfreak](https://github.com/bastelfreak) for [Vox Pupuli](https://voxpupuli.org)] ???