and other adventures in ChatOps
Puppet at GitHub
@wfarr
GitHub Operations
Known Aliases: King of Kebabs
The Computer Guy
Mr. RealTalk
Probably a delinquent
The State of Puppet at GitHub

 The State of Puppet at GitHub
boxen/puppet-*
 The State of Puppet at GitHub
~1 YEAR OLD
 The State of Puppet at GitHub
OPEN SOURCED 3 MONTHS AGO
 The State of Puppet at GitHub
~180 PUBLIC MODULES
 The State of Puppet at GitHub
2 EXTERNAL MAINTAINERS
@fromonesrc @JHaals
The State of Puppet at GitHub
THE STACK

The State of Puppet at GitHub
PUPPET 3.2

The State of Puppet at GitHub
MASTER-LESS

The State of Puppet at GitHub
RUBY 1.8.7

The State of Puppet at GitHub
RUN MANUALLY

 The State of Puppet at GitHub
github/puppet
 The State of Puppet at GitHub
~5 YEARS OLD
2010
2011
2012
2013
CODE COMMITS
 The State of Puppet at GitHub
CODE ADDITIONS
 The State of Puppet at GitHub
CODE DELETIONS
 The State of Puppet at GitHub
CONTRIBUTIONS (PAST YEAR)
~2k commits
~150 commits
 The State of Puppet at GitHub
CONTRIBUTIONS (PAST YEAR)
~23% of all commits
 The State of Puppet at GitHub
The State of Puppet at GitHub
AN AVERAGE WEEK
About 50 Pull Requests and 25 Issues comprising
300 commits across 24 authors

The State of Puppet at GitHub
THE STACK

The State of Puppet at GitHub
PUPPET 2.7.GITHUB

The State of Puppet at GitHub
SINGLE PUPPETMASTER

The State of Puppet at GitHub
RUBY 1.8.7

The State of Puppet at GitHub
RUN VIA CRON JOB

The State of Puppet at GitHub
PUPPETDB

The State of Puppet at GitHub
CUSTOM NODE DEFINITIONS

How GitHub writes Puppet

 How GitHub Writes Puppet
PUPPETLABS/STDLIB
 How GitHub Writes Puppet
PARAMETER VALIDATION
 How GitHub Writes Puppet
class redis::server(
$data_dir = '/var/lib/redis',
$manage_service = false,
$package = 'redis-server'
) {
validate_bool($manage_service)
validate_absolute_path($data_dir)
validate_re($package, '^redis2?-server$',
"Redis::Server[${name}]: package must be either redis-server or redis2-server: $
{package}")
}
 How GitHub Writes Puppet
DATA MUNGING
 How GitHub Writes Puppet
define ruby::version(
$env = {}
) {
$default_environment = {
'CC' => 'clang',
'CFLAGS' => '-O2'
}
$ruby_build_environment = merge($default_environment, $env)
exec { "install ruby version ${name}":
environment => join_keys_to_values($ruby_build_environment, '=')
}
}
 How GitHub Writes Puppet
RESOURCE HANDLING
 How GitHub Writes Puppet
class redis::server(
$data_dir = '/var/lib/redis'
) {
if ! defined_with_params(User[redis], { ensure => 'present' }) {
user { 'redis': ensure => 'present', group => 'redis' }
}
}
 How GitHub Writes Puppet
$latest_tcs_version = "${::ruby::root}/versions/1.9.3-p231-tcs-github-1.0.30"
$tcs_alias = "${::ruby::root}/versions/1.9.3-p231-tcs-github"
$desired_params = {
'ensure' => 'link',
'target' => $latest_tcs_version,
'force' => true
}
File <| title == $tcs_version |> {
ensure => link,
target => $latest_tcs_version,
force => true
}
ensure_resource('file', $tcs_alias, $desired_params)
 How GitHub Writes Puppet
GITHUB::ROLE::*
 How GitHub Writes Puppet
NODE CONFIGURATION
node /^github-redisd+[a-z]?-rs1-prd.iad.github.net$/ {
class { 'github::role::redis':
env => 'production',
private_ipv4 => $::ipaddress,
}
}
 How GitHub Writes Puppet
 How GitHub Writes Puppet
ROLE CONFIGURATION
class github::role::redis($env, $private_ipv4) {
validate_re($env, '^(vagrant|staging|production)$')
validate_re($private_ipv4, '^d+.d+.d+.d+$')
$monitor = $env ? { 'production' => true, default => false }
class {
'github::core':
monitor => $monitor,
private_address => $private_ipv4 ;
'redis::server':
bind_address => $private_ipv4,
monitor => $monitor ;
}
}
 How GitHub Writes Puppet

ABSTRACTION
How GitHub Writes Puppet
class github::core($monitor) {
include github::common_packages
include github::staff
class {
'github::ssh':
monitor => $monitor ;
'github::ipv6':
ensure => absent ;
}
}
 How GitHub Writes Puppet
class github::ipv6($ensure = present) {
if $::lsbdistcodename != 'squeeze' {
file { '/etc/modprobe.d/ipv6':
ensure => $ensure,
mode => '0444',
source => 'puppet:///modules/github//etc/modprobe.d/ipv6',
}
} else {
$value = $ensure ? { present => 0, default => 1 }
sysctl { 'net.ipv6.conf.all.disable_ipv6':
value => $value,
}
}
}
 How GitHub Writes Puppet

AUGEAS
How GitHub Writes Puppet
class redis::server($bind_address, $data_dir, $monitor, $port) {
redis::config {
'dir':
value => $data_dir,
require => File[$data_dir];
'bind':
value => $bind_address;
'port':
value => $port;
'daemonize':
value => 'yes';
}
}
 How GitHub Writes Puppet
define redis::config($value, $ensure = present) {
validate_re($ensure, '^(present|absent)$')
$changes = $ensure ? { present => "set ${name} ${value}", default => "rm ${name}" }
augeas { "Set Redis config '${name}' to '${value}'":
changes => $changes,
context => '/files/etc/redis/redis.conf',
lens => 'Redis.lns',
incl => '/etc/redis/redis.conf',
require => File['/etc/redis/redis.conf']
}
}
 How GitHub Writes Puppet
 How GitHub Writes Puppet
CODE SHARE

LIBRARIAN-PUPPET
How GitHub Writes Puppet

HENSON
How GitHub Writes Puppet
How GitHub deploys Puppet

KEEP IT CLEAN
 How GitHub Deploys Puppet
rodjek/puppet-lint
 How GitHub Deploys Puppet
KEEP IT GREEN
 How GitHub Deploys Puppet
rodjek/rspec-puppet
 How GitHub Deploys Puppet
tmm1/test-queue
 How GitHub Deploys Puppet
KEEP IT LEAN
 How GitHub Deploys Puppet
$ git commit -am "can't lint this"
modules/github/manifests/role/redis.pp: syntax ok
modules/github/manifests/role/redis.pp - WARNING: => is not properly aligned on line 118
1 errors found, aborting commit.
 How GitHub Deploys Puppet
 How GitHub Deploys Puppet
 How GitHub Deploys Puppet
CHATOPS
 How GitHub Deploys Puppet
/puppet env worker
#=>
worker1.rs.github.com: production
worker2.rs.github.com: production
worker3.rs.github.com: production
worker4.rs.github.com: production
worker5.rs.github.com: production
worker6.rs.github.com: production
 How GitHub Deploys Puppet
/puppet run worker2
#=> Running puppet on worker2.rs.github.com/production
 How GitHub Deploys Puppet
/puppet noop feature_branch worker2
#=> Running puppet on worker2.rs.github.com/feature_branch --noop
 How GitHub Deploys Puppet
/puppet force feature_branch worker2
#=> Running puppet on worker2.rs.github.com/feature_branch
 How GitHub Deploys Puppet
/puppet disable worker2
#=> Disabling puppet on worker2.rs.github.com
 How GitHub Deploys Puppet
/puppet enable worker2
#=> Disabling puppet on worker2.rs.github.com
 How GitHub Deploys Puppet
/puppet last_run worker2
 How GitHub Deploys Puppet
/puppet certs
#=>
"wills-macbook-pro.local" (A4:5B:AC:B9:E1:85:8B:2B:0E:8B:62:F9:03:32:C9:03)
 How GitHub Deploys Puppet
The Future of Puppet at GitHub

boxen/puppet-*
The Future of Puppet at GitHub
SHELL "REMEMBER TO RUN" SUPPORT
The Future of Puppet at GitHub
You haven't run Boxen in over a week. =(
We really recommend running Boxen regularly. It's way better that way!
Do you want to run boxen now? (y/N) y
# boxen
Updating Boxen.
...
The Future of Puppet at GitHub
OPT-OUT
The Future of Puppet at GitHub
touch $HOME/.boxen-never-prompt-for-updates
The Future of Puppet at GitHub
PUPPETMASTER SUPPORT
The Future of Puppet at GitHub
OPT-IN ONLY
The Future of Puppet at GitHub
HIERA SUPPORT
The Future of Puppet at GitHub
"uncomfortunities"
The Future of Puppet at GitHub
UBUNTU SUPPORT
The Future of Puppet at GitHub
UBUNTU PRECISE
The Future of Puppet at GitHub
github/puppet
The Future of Puppet at GitHub
The Future of Puppet at GitHub
RUBY 1.9.3

The Future of Puppet at GitHub
PUPPET 3.X

The Future of Puppet at GitHub
GPANEL: ENC

The Future of Puppet at GitHub
lol censored
The Future of Puppet at GitHub
MCOLLECTIVE

The Future of Puppet at GitHub
REPLACING PARTS OF GITHUB/SHELL

The Future of Puppet at GitHub
STRUCTURED DATA > SED/AWK

The Future of Puppet at GitHub
HIERA

THANKS
speakerdeck.com/wfarr/
puppet-at-github-
puppetcamp-raleigh-2013

Puppet at GitHub