Transcript
Page 1: Puppet Module Reusability - What I Learned from Shipping to the Forge

Puppet Module ReusabilityLearning from shipping to the Forge

Gareth Rushgrove

Page 2: Puppet Module Reusability - What I Learned from Shipping to the Forge

Who(Who is this person?)

Page 3: Puppet Module Reusability - What I Learned from Shipping to the Forge

@garethr

Page 4: Puppet Module Reusability - What I Learned from Shipping to the Forge

UK Government Digital Service

Page 5: Puppet Module Reusability - What I Learned from Shipping to the Forge
Page 6: Puppet Module Reusability - What I Learned from Shipping to the Forge
Page 7: Puppet Module Reusability - What I Learned from Shipping to the Forge
Page 8: Puppet Module Reusability - What I Learned from Shipping to the Forge

Last codeI wrote

Page 9: Puppet Module Reusability - What I Learned from Shipping to the Forge
Page 10: Puppet Module Reusability - What I Learned from Shipping to the Forge
Page 11: Puppet Module Reusability - What I Learned from Shipping to the Forge

7. Gareth Rushgrove

Page 12: Puppet Module Reusability - What I Learned from Shipping to the Forge

Last puppet module I wrote

Page 13: Puppet Module Reusability - What I Learned from Shipping to the Forge

The Problem(Sharing modules is hard)

Page 14: Puppet Module Reusability - What I Learned from Shipping to the Forge

Not invented here syndrome

1

Page 15: Puppet Module Reusability - What I Learned from Shipping to the Forge

A search for puppet-apache

Page 16: Puppet Module Reusability - What I Learned from Shipping to the Forge

145Gareth Rushgrove

Page 17: Puppet Module Reusability - What I Learned from Shipping to the Forge

145Gareth Rushgrove

Page 18: Puppet Module Reusability - What I Learned from Shipping to the Forge

Puppetlabsapache

Page 19: Puppet Module Reusability - What I Learned from Shipping to the Forge

67 contributors

Gareth Rushgrove

Page 20: Puppet Module Reusability - What I Learned from Shipping to the Forge

281forks

Gareth Rushgrove

Page 21: Puppet Module Reusability - What I Learned from Shipping to the Forge

281Gareth Rushgrove

Page 22: Puppet Module Reusability - What I Learned from Shipping to the Forge

Vendor everything pattern

2

Page 23: Puppet Module Reusability - What I Learned from Shipping to the Forge

Not publishing to the Forge

3

Page 24: Puppet Module Reusability - What I Learned from Shipping to the Forge

Puppet Forge

Page 25: Puppet Module Reusability - What I Learned from Shipping to the Forge

Undocumented modules

4

Page 26: Puppet Module Reusability - What I Learned from Shipping to the Forge

Official docs guidelines

Page 27: Puppet Module Reusability - What I Learned from Shipping to the Forge

(Too) opinionated configuration

5

Page 28: Puppet Module Reusability - What I Learned from Shipping to the Forge

Sometimes I just want to write nginx configuration

Gareth Rushgrove

Page 29: Puppet Module Reusability - What I Learned from Shipping to the Forge

Duplicate resources6

Page 30: Puppet Module Reusability - What I Learned from Shipping to the Forge

Package { 'build-essential’: ensure => installed,}

Gareth Rushgrove

Page 31: Puppet Module Reusability - What I Learned from Shipping to the Forge

Stdlib(Start here)

Page 32: Puppet Module Reusability - What I Learned from Shipping to the Forge

Standard Library from Puppetlabs

Page 33: Puppet Module Reusability - What I Learned from Shipping to the Forge

Fail fast

Gareth Rushgrove

Page 34: Puppet Module Reusability - What I Learned from Shipping to the Forge

Validation

Gareth Rushgrove

Page 35: Puppet Module Reusability - What I Learned from Shipping to the Forge

Useful error messages

Gareth Rushgrove

Page 36: Puppet Module Reusability - What I Learned from Shipping to the Forge

fail("${::operatingsystem} not supported")

Gareth Rushgrove

Page 37: Puppet Module Reusability - What I Learned from Shipping to the Forge

validate_string

Gareth Rushgrove

Page 38: Puppet Module Reusability - What I Learned from Shipping to the Forge

validate_string($version)

Gareth Rushgrove

Page 39: Puppet Module Reusability - What I Learned from Shipping to the Forge

<Puppet::Error: true is not a string.

Gareth Rushgrove

Page 40: Puppet Module Reusability - What I Learned from Shipping to the Forge

validate_slength

Gareth Rushgrove

Page 41: Puppet Module Reusability - What I Learned from Shipping to the Forge

validate_re

Gareth Rushgrove

Page 42: Puppet Module Reusability - What I Learned from Shipping to the Forge

validate_hash

Gareth Rushgrove

Page 43: Puppet Module Reusability - What I Learned from Shipping to the Forge

Gareth Rushgrove

validate_cmd

Page 44: Puppet Module Reusability - What I Learned from Shipping to the Forge

validate_bool

Gareth Rushgrove

Page 45: Puppet Module Reusability - What I Learned from Shipping to the Forge

Avoid duplicate resources

Gareth Rushgrove

Page 46: Puppet Module Reusability - What I Learned from Shipping to the Forge

Package { 'build-essential’: ensure => installed,}

Gareth Rushgrove

Page 47: Puppet Module Reusability - What I Learned from Shipping to the Forge

include 'gcc'

Gareth Rushgrove

Page 48: Puppet Module Reusability - What I Learned from Shipping to the Forge

package{[ 'python-pip', 'python-ldap',]: ensure => installed}

Gareth Rushgrove

Page 49: Puppet Module Reusability - What I Learned from Shipping to the Forge

ensure_packages

Gareth Rushgrove

Page 50: Puppet Module Reusability - What I Learned from Shipping to the Forge

ensure_packages([ 'python-pip', 'python-ldap',])

Gareth Rushgrove

Page 51: Puppet Module Reusability - What I Learned from Shipping to the Forge

ensure_resource

Gareth Rushgrove

Page 52: Puppet Module Reusability - What I Learned from Shipping to the Forge

Nicer interfaces

Gareth Rushgrove

Page 53: Puppet Module Reusability - What I Learned from Shipping to the Forge

str2bool

Gareth Rushgrove

Page 54: Puppet Module Reusability - What I Learned from Shipping to the Forge

any2array

Gareth Rushgrove

Page 55: Puppet Module Reusability - What I Learned from Shipping to the Forge

And much more

Gareth Rushgrove

Page 56: Puppet Module Reusability - What I Learned from Shipping to the Forge

Dependency management is

everywhere(Else)

Page 57: Puppet Module Reusability - What I Learned from Shipping to the Forge

NPM, Bundler, Pip, Mix, Leiningen

Gareth Rushgrove

Page 58: Puppet Module Reusability - What I Learned from Shipping to the Forge

Librarian Puppet

Page 59: Puppet Module Reusability - What I Learned from Shipping to the Forge

r10k

Page 60: Puppet Module Reusability - What I Learned from Shipping to the Forge

echo 'modules' >> .gitignore

Gareth Rushgrove

Page 61: Puppet Module Reusability - What I Learned from Shipping to the Forge

dependency 'puppetlabs/stdlib'dependency 'garethr/erlang'dependency 'maestrodev/wget'

Gareth Rushgrove

Page 62: Puppet Module Reusability - What I Learned from Shipping to the Forge

forge "http://forge.puppetlabs.com"

mod 'puppetlabs/ruby'mod 'puppetlabs/ntp'mod 'puppetlabs/git'mod 'puppetlabs/vcsrepo'mod 'puppetlabs/apt'mod 'puppetlabs/gcc'

Gareth Rushgrove

Page 63: Puppet Module Reusability - What I Learned from Shipping to the Forge

librarian-puppet install

Gareth Rushgrove

Page 64: Puppet Module Reusability - What I Learned from Shipping to the Forge

A Nice Module Pattern(Structuring modules for reuse)

Page 65: Puppet Module Reusability - What I Learned from Shipping to the Forge

R.I.Pienaar

Page 66: Puppet Module Reusability - What I Learned from Shipping to the Forge

install, config, service, params

Gareth Rushgrove

Page 67: Puppet Module Reusability - What I Learned from Shipping to the Forge

manifests!"" config.pp!"" init.pp!"" install.pp!"" params.pp#"" service.pp

Gareth Rushgrove

Page 68: Puppet Module Reusability - What I Learned from Shipping to the Forge

class sample () inherits sample::params {

class { 'sample::install': } -> class { 'sample::config': } ~> class { 'sample::service': } -> Class['sample']}

Gareth Rushgrove

Page 69: Puppet Module Reusability - What I Learned from Shipping to the Forge

anchor { 'sample::begin': } ->class { 'sample::install': } ->class { 'sample::config': }class { 'sample::service': } ->anchor { 'sample::end': }

Gareth Rushgrove

Page 70: Puppet Module Reusability - What I Learned from Shipping to the Forge

Anchor['sample::begin'] ~> Class['sample::service']

Class['sample::install'] ~> Class['sample::service']

Class['sample::config'] ~> Class['sample::service']

Gareth Rushgrove

Page 71: Puppet Module Reusability - What I Learned from Shipping to the Forge

Puppet module tool

Gareth Rushgrove

Page 72: Puppet Module Reusability - What I Learned from Shipping to the Forge

puppet module generate name

Gareth Rushgrove

Page 73: Puppet Module Reusability - What I Learned from Shipping to the Forge

Default module skeleton

Gareth Rushgrove

Page 74: Puppet Module Reusability - What I Learned from Shipping to the Forge

In puppet source code

Page 75: Puppet Module Reusability - What I Learned from Shipping to the Forge

!"" manifests!"" spec!"" tests!"" Modulefile!"" .gitignore#"" README

Gareth Rushgrove

Page 76: Puppet Module Reusability - What I Learned from Shipping to the Forge

Creating your own module skeleton

Gareth Rushgrove

Page 77: Puppet Module Reusability - What I Learned from Shipping to the Forge

~/.puppet/var/puppet-module/skeleton

Gareth Rushgrove

Page 78: Puppet Module Reusability - What I Learned from Shipping to the Forge

puppet module skeleton

Page 79: Puppet Module Reusability - What I Learned from Shipping to the Forge

!"" manifests!"" spec!"" tests!"" templates!"" files!"" lib!"" Gemfile

Gareth Rushgrove

Page 80: Puppet Module Reusability - What I Learned from Shipping to the Forge

!"" Rakefile!"" .nodeset.yml!"" .fixtures.yml!"" .travis.yml!"" Modulefile!"" .gitignore#"" README.md

Gareth Rushgrove

Page 81: Puppet Module Reusability - What I Learned from Shipping to the Forge

Creates install, config, service, params classes

Gareth Rushgrove

Page 82: Puppet Module Reusability - What I Learned from Shipping to the Forge

Dependency management with Bundler

Gareth Rushgrove

Page 83: Puppet Module Reusability - What I Learned from Shipping to the Forge

Better unit testing setup using rspec-puppet-helper

Gareth Rushgrove

Page 84: Puppet Module Reusability - What I Learned from Shipping to the Forge

Adds syntax and lint checking

Gareth Rushgrove

Page 85: Puppet Module Reusability - What I Learned from Shipping to the Forge

Adds Travis CI configuration

Gareth Rushgrove

Page 86: Puppet Module Reusability - What I Learned from Shipping to the Forge

Adds integration tests with rspec-system

Gareth Rushgrove

Page 87: Puppet Module Reusability - What I Learned from Shipping to the Forge

Adds module management with maestrodev blacksmith

Gareth Rushgrove

Page 88: Puppet Module Reusability - What I Learned from Shipping to the Forge

Focus on the interface

Gareth Rushgrove

Page 89: Puppet Module Reusability - What I Learned from Shipping to the Forge

Minimize number of entry points

Gareth Rushgrove

Page 90: Puppet Module Reusability - What I Learned from Shipping to the Forge

Allow overriding provided templates

Gareth Rushgrove

Page 91: Puppet Module Reusability - What I Learned from Shipping to the Forge

Multi-OS Support(Where to abstract the differences)

Page 92: Puppet Module Reusability - What I Learned from Shipping to the Forge

Vary default parameters

Gareth Rushgrove

Page 93: Puppet Module Reusability - What I Learned from Shipping to the Forge

Keep logic in one place

Gareth Rushgrove

Page 94: Puppet Module Reusability - What I Learned from Shipping to the Forge

case $::osfamily { 'Debian': {  }  'RedHat', 'Amazon': { } default: { fail("${::operatingsystem} not su}

Gareth Rushgrove

Page 95: Puppet Module Reusability - What I Learned from Shipping to the Forge

ARM-9 Data in Modules

Page 96: Puppet Module Reusability - What I Learned from Shipping to the Forge

garethr-erlang

Page 97: Puppet Module Reusability - What I Learned from Shipping to the Forge

0.0.x supported Ubuntu only

Gareth Rushgrove

Page 98: Puppet Module Reusability - What I Learned from Shipping to the Forge

0.1.x supports Ubuntu, Debian, Redhat, Suse

Gareth Rushgrove

Page 99: Puppet Module Reusability - What I Learned from Shipping to the Forge

Gareth Rushgrove

Page 100: Puppet Module Reusability - What I Learned from Shipping to the Forge

Pull requests to the rescue

Page 101: Puppet Module Reusability - What I Learned from Shipping to the Forge
Page 102: Puppet Module Reusability - What I Learned from Shipping to the Forge

Insist on tests with open source contributions

Gareth Rushgrove

Page 103: Puppet Module Reusability - What I Learned from Shipping to the Forge

Module Testing(Code should have tests)

Page 104: Puppet Module Reusability - What I Learned from Shipping to the Forge

Why test a declarative language?

Gareth Rushgrove

Page 105: Puppet Module Reusability - What I Learned from Shipping to the Forge

Modules increasingly contain logic

Gareth Rushgrove

Page 106: Puppet Module Reusability - What I Learned from Shipping to the Forge

Modules increasingly take arguments

Gareth Rushgrove

Page 107: Puppet Module Reusability - What I Learned from Shipping to the Forge

Modules increasingly have interfaces with other modules

Gareth Rushgrove

Page 108: Puppet Module Reusability - What I Learned from Shipping to the Forge

Modules increasingly used in many Ruby and Puppet version combinations

Gareth Rushgrove

Page 109: Puppet Module Reusability - What I Learned from Shipping to the Forge

Good news. The tools got better

Gareth Rushgrove

Page 110: Puppet Module Reusability - What I Learned from Shipping to the Forge

puppet-lint

Gareth Rushgrove

Page 111: Puppet Module Reusability - What I Learned from Shipping to the Forge

Puppetstyle guide

Page 112: Puppet Module Reusability - What I Learned from Shipping to the Forge

Availableas a gem

Page 113: Puppet Module Reusability - What I Learned from Shipping to the Forge

puppet-lint --with-filename /etc/puppet/modulesfoo/manifests/bar.pp: trailing whitespace found on line 1apache/manifests/server.pp: variable not enclosed in {} on line 56

Gareth Rushgrove

Page 114: Puppet Module Reusability - What I Learned from Shipping to the Forge

puppet-syntax

Gareth Rushgrove

Page 115: Puppet Module Reusability - What I Learned from Shipping to the Forge

Validate Puppet and ERB syntax

Page 116: Puppet Module Reusability - What I Learned from Shipping to the Forge

require 'puppet-syntax/tasks/puppet-syntax'

Gareth Rushgrove

Page 117: Puppet Module Reusability - What I Learned from Shipping to the Forge

bundle exec rake syntax---> syntax:manifests---> syntax:templates

Gareth Rushgrove

Page 118: Puppet Module Reusability - What I Learned from Shipping to the Forge

rspec-puppet

Gareth Rushgrove

Page 119: Puppet Module Reusability - What I Learned from Shipping to the Forge

Unit testing for Puppet

Page 120: Puppet Module Reusability - What I Learned from Shipping to the Forge

context "epel enabled" do let(:params) {{ :epel_enable => true }} it { should contain_class('epel') }end

Gareth Rushgrove

Page 121: Puppet Module Reusability - What I Learned from Shipping to the Forge

context "epel disabled" do let(:params) {{ :epel_enable => false }} it { should_not contain_class('epel') }end

Gareth Rushgrove

Page 122: Puppet Module Reusability - What I Learned from Shipping to the Forge

Fixtures, matchers

Page 123: Puppet Module Reusability - What I Learned from Shipping to the Forge

Test the interface not the implementation

Gareth Rushgrove

Page 124: Puppet Module Reusability - What I Learned from Shipping to the Forge

All of the above

Gareth Rushgrove

Page 125: Puppet Module Reusability - What I Learned from Shipping to the Forge

task :test => [ :syntax, :lint, :spec,]

Gareth Rushgrove

Page 126: Puppet Module Reusability - What I Learned from Shipping to the Forge

bundle exec rake test

Gareth Rushgrove

Page 127: Puppet Module Reusability - What I Learned from Shipping to the Forge

Gareth Rushgrove

Page 128: Puppet Module Reusability - What I Learned from Shipping to the Forge

Nice continuous integration

Page 129: Puppet Module Reusability - What I Learned from Shipping to the Forge
Page 130: Puppet Module Reusability - What I Learned from Shipping to the Forge

Test pull request branches too

Page 131: Puppet Module Reusability - What I Learned from Shipping to the Forge

---language: rubybefore_install: rm Gemfile.lock || truervm: - 1.8.7 - 1.9.3script: bundle exec rake testenv: matrix: - PUPPET_VERSION="~> 2.7.0" - PUPPET_VERSION="~> 3.1.0" - PUPPET_VERSION="~> 3.2.0"

Gareth Rushgrove

Page 132: Puppet Module Reusability - What I Learned from Shipping to the Forge

A matrix of possibilities

Gareth Rushgrove

Page 133: Puppet Module Reusability - What I Learned from Shipping to the Forge

rspec-system

Gareth Rushgrove

Page 134: Puppet Module Reusability - What I Learned from Shipping to the Forge

Integration test against real systems

Page 135: Puppet Module Reusability - What I Learned from Shipping to the Forge

Puppet helpers for rspec-system

Page 136: Puppet Module Reusability - What I Learned from Shipping to the Forge

Vagrant driver

Page 137: Puppet Module Reusability - What I Learned from Shipping to the Forge

VSphere provider

Page 138: Puppet Module Reusability - What I Learned from Shipping to the Forge

Test that Puppet runs without errors

Gareth Rushgrove

Page 139: Puppet Module Reusability - What I Learned from Shipping to the Forge

it 'should run without errors' do pp = "class { 'sample': }"

puppet_apply(pp) do |r| r.exit_code.should == 2 endend

Gareth Rushgrove

Page 140: Puppet Module Reusability - What I Learned from Shipping to the Forge

Test runs are idempotent

Gareth Rushgrove

Page 141: Puppet Module Reusability - What I Learned from Shipping to the Forge

it 'should run without errors' do pp = "class { 'sample': }"

puppet_apply(pp) do |r| r.exit_code.should == 2 r.refresh r.exit_code.should be_zero endend

Gareth Rushgrove

Page 142: Puppet Module Reusability - What I Learned from Shipping to the Forge

Test that the module installs relevant binaries

Gareth Rushgrove

Page 143: Puppet Module Reusability - What I Learned from Shipping to the Forge

it 'should install the erl binary' do shell 'which erl' do |r| r.stdout.should =~ /\/usr\/bin\/e r.stderr.should be_empty r.exit_code.should be_zero endend

Gareth Rushgrove

Page 144: Puppet Module Reusability - What I Learned from Shipping to the Forge

Test against different operating systems

Gareth Rushgrove

Page 145: Puppet Module Reusability - What I Learned from Shipping to the Forge

default_set: 'centos-64-x64'sets: 'centos-64-x64': nodes: "main.foo.vm": prefab: 'centos-64-x64' 'fedora-18-x64': nodes: "main.foo.vm": prefab: 'fedora-18-x64' 'debian-607-x64': nodes: "main.foo.vm":

Gareth Rushgrove

Page 146: Puppet Module Reusability - What I Learned from Shipping to the Forge

Room for improvements

(Making reuse easier in Puppet)

Page 147: Puppet Module Reusability - What I Learned from Shipping to the Forge

Run your own Forge1

Page 148: Puppet Module Reusability - What I Learned from Shipping to the Forge

A more secure Forge2

Page 149: Puppet Module Reusability - What I Learned from Shipping to the Forge

Bless a dependency management tool

3

Page 150: Puppet Module Reusability - What I Learned from Shipping to the Forge

Optional dependencies

4

Page 151: Puppet Module Reusability - What I Learned from Shipping to the Forge

dependency 'puppetlabs/stdlib'

optional_dependency 'puppetlabs/apache'

Gareth Rushgrove

Page 152: Puppet Module Reusability - What I Learned from Shipping to the Forge

Private classes5

Page 153: Puppet Module Reusability - What I Learned from Shipping to the Forge

private class elixir::install {

Gareth Rushgrove

Page 154: Puppet Module Reusability - What I Learned from Shipping to the Forge

Parameter naming conventions

6

Page 155: Puppet Module Reusability - What I Learned from Shipping to the Forge

example42Proposal

Page 156: Puppet Module Reusability - What I Learned from Shipping to the Forge

Interfaces in Puppet7

Page 157: Puppet Module Reusability - What I Learned from Shipping to the Forge

interface packageandservice { $version $enable $package_name $template}

Gareth Rushgrove

Page 158: Puppet Module Reusability - What I Learned from Shipping to the Forge

class diamond ( $version,

$enable, $package_name, $template,) { implements packageandservice

Gareth Rushgrove

Page 159: Puppet Module Reusability - What I Learned from Shipping to the Forge

Questions?(And thanks for listening)


Top Related