+ All Categories
Home > Technology > Puppet Module Reusability - What I Learned from Shipping to the Forge

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

Date post: 10-May-2015
Category:
Upload: puppet-labs
View: 5,387 times
Download: 1 times
Share this document with a friend
Description:
A simple search for "puppet-apache" on GitHub returns 70 separate repositories. An awful lot of people are busy reinventing the same configuration wheel. Configuration management tools promise write once, run anywhere code; but writing code that can be used by anyone looks like a lot of work. This presentation aims to show anyone familiar with Puppet how to write reusable modules and importantly how to make them compatible with already shared modules released on the Forge or elsewhere. We'll look at when and why testing a declarative language is actually useful, examples of good and bad modules and how to re-factor puppet code for re-usability. We'll also talk about potential improvements to Puppet that would make reuse easier. Gareth Rushgrove Technical Architect, Government Digital Service Gareth Rushgrove is now a technical architect at the Government Digital Service, part of the UK Government. He is mainly interested in configuration management, infrastructure and platform as a service, deployment and monitoring tooling and the whole devops community. He thinks when used well together these allow you to move really fast, even in tightly controlled environments like Government. When not working, Gareth can be found blogging over on morethanseven.net or uploading code to GitHub. He also curates the Devops Weekly newsletter and occasionally organises community events.
Popular Tags:
159
Puppet Module Reusability Learning from shipping to the Forge Gareth Rushgrove
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)


Recommended