45
Writing and Publishing Puppet Modules Colleen Murphy

Writing and Publishing Puppet Modules - PuppetConf 2014

Embed Size (px)

DESCRIPTION

Writing and Publishing Puppet Modules - Colleen Murphy, Puppet Labs

Citation preview

Page 1: Writing and Publishing Puppet Modules - PuppetConf 2014

Writing and Publishing Puppet Modules

Colleen Murphy

Page 2: Writing and Publishing Puppet Modules - PuppetConf 2014

HelloMe (then):

Student sysadmin at the IT department for Portland State University’s College of Engineering

aka The Computer Action Team (TheCAT)

github.com/pdxcat forge.puppetlabs.com/pdxcat

Page 3: Writing and Publishing Puppet Modules - PuppetConf 2014

HelloMe (now):Module engineer at Puppet Labs

Page 4: Writing and Publishing Puppet Modules - PuppetConf 2014

What is a puppet module?● An encapsulation of configuration for a

service● A structure containing an organized set of

puppet code and data● Analogous to a package, gem, python library● The place where your code goes

Page 5: Writing and Publishing Puppet Modules - PuppetConf 2014

What should a module do?● Set up a service, such as:

○ ssh○ mysql○ apache○ sudo

● Extend puppet functionality. Examples:○ puppetlabs/stdlib○ puppetlabs/concat

Page 6: Writing and Publishing Puppet Modules - PuppetConf 2014

The strategySet up the service… without puppet.

Then iterate.

Page 7: Writing and Publishing Puppet Modules - PuppetConf 2014

Layout of a moduleyourmodule/

➔ manifests/ # where your puppet code goes➔ files/ # flat configuration files➔ templates/ # dynamic configuration files➔ lib/ # plugins: types and providers, functions,

| facts, etc➔ tests/ # smoke tests/example usage➔ spec/ # automated tests

Page 8: Writing and Publishing Puppet Modules - PuppetConf 2014

Layout of a moduleyourmodule/

➔ manifests/ # where your puppet code goes➔ files/ # flat configuration files➔ templates/ # dynamic configuration files

Page 9: Writing and Publishing Puppet Modules - PuppetConf 2014

Layout of a moduleyourmodule/

➔ manifests/ # where your puppet code goes➔ files/ # flat configuration files➔ templates/ # dynamic configuration files

➔ tests/ # smoke tests/example usage➔ spec/ # automated tests

Page 10: Writing and Publishing Puppet Modules - PuppetConf 2014

Starting out$ puppet module generate cmurphy-ssh && mv cmurphy-ssh ssh

$ mkdir ssh/{files,templates}

Page 11: Writing and Publishing Puppet Modules - PuppetConf 2014

Writing your first module# manifests/init.pp

class ssh {

}

Page 12: Writing and Publishing Puppet Modules - PuppetConf 2014

Writing your first module# manifests/init.pp

class ssh {

package { 'openssh-server':

ensure => installed,

}

}

Page 13: Writing and Publishing Puppet Modules - PuppetConf 2014

Writing your first module# manifests/init.pp

class ssh {

package { 'openssh-server':

ensure => installed,

}

file { '/etc/ssh/sshd_config':

source => "puppet:///modules/ssh/sshd_config",

require => Package['openssh-server'],

}

}

Page 14: Writing and Publishing Puppet Modules - PuppetConf 2014

Writing your first module# ...

package { 'openssh-server':

ensure => installed,

}

file { '/etc/ssh/sshd_config':

source => "puppet:///modules/ssh/sshd_config",

require => Package['openssh-server'],

}

service { 'ssh':

ensure => running,

enable => true,

subscribe => File['/etc/ssh/sshd_config'],

}

}

Page 15: Writing and Publishing Puppet Modules - PuppetConf 2014

Drop in a configuration file# files/sshd_config

# Managed by Puppet

# What ports, IPs and protocols we listen for

Port 22

Protocol 2

# Logging

SyslogFacility AUTH

LogLevel INFO

# Authentication:

LoginGraceTime 120

PermitRootLogin no

StrictModes yes

# ...

Page 16: Writing and Publishing Puppet Modules - PuppetConf 2014

Writing your first module# manifests/init.pp

class ssh {

package { 'openssh-server':

ensure => installed,

}

file { '/etc/ssh/sshd_config':

source => "puppet:///modules/ssh/sshd_config",

require => Package['openssh-server'],

}

service { 'ssh':

ensure => running,

enable => true,

subscribe => File['/etc/ssh/sshd_config'],

}

}

Page 17: Writing and Publishing Puppet Modules - PuppetConf 2014

Writing your first module# tests/init.pp

include ssh

# or

# /etc/puppet/manifests/site.pp

node default {

include ssh

}

Page 18: Writing and Publishing Puppet Modules - PuppetConf 2014

Needs more portability!

No one should have to change your code or your files in order to use your module.

Page 19: Writing and Publishing Puppet Modules - PuppetConf 2014

Template your module# templates/sshd_config.erb

# Managed by Puppet

# What ports, IPs and protocols we listen for

Port <%= @port %>

Protocol 2

# Logging

SyslogFacility <%= @syslog_facility %>

LogLevel <%= @log_level %>

# Authentication:

LoginGraceTime 120

PermitRootLogin <%= @permit_root_login %>

StrictModes yes

# ...

Page 20: Writing and Publishing Puppet Modules - PuppetConf 2014

Template your module# manifests/init.pp

class ssh (

$port = 22,

$syslog_facility = 'AUTH',

$log_level = 'INFO',

$permit_root_login = 'no',

) {

# ...

file { '/etc/ssh/sshd_config':

content =>

template('ssh/sshd_config.erb'),

require => Package['openssh-server'],

} # ...

# tests/init.pp or site.pp

# ...

class { 'ssh':

permit_root_login => 'without-password',

}

Page 21: Writing and Publishing Puppet Modules - PuppetConf 2014

Templating strategies# manifests/init.pp

class ssh (

$ports = [ 22 ],

$options = {}

) {

# ...

file { '/etc/ssh/sshd_config':

content =>

template('ssh/sshd_config.erb'),

require => Package['openssh-server'],

}

# ...

# Applying the class

class { 'ssh':

ports => [ 22, 2222 ],

options => {

'PermitRootLogin' => 'no',

}

}

Page 22: Writing and Publishing Puppet Modules - PuppetConf 2014

Templating strategies# templates/sshd_config.erb

# Managed by Puppet

<% @ports.each do |port| %>

Port <%= port %>

<% end %>

<% @options.each do |k,v| %>

<%= k %> <%= v %>

<% end %>

Page 23: Writing and Publishing Puppet Modules - PuppetConf 2014

Templating strategies● Take advantage of Include conf.d/* directives

file { '/etc/collectd.conf':

ensure => present,

content => 'Include "conf.d/*.conf"\n',

}

# …

define collectd::plugins::exec {

file { "${name}.load":

path => "${conf_dir}/${name}.conf",

content => template('collectd/exec.conf.erb'),

}

}

Page 24: Writing and Publishing Puppet Modules - PuppetConf 2014

Beyond templates● puppetlabs/concat concat { '/etc/motd': }

concat::fragment { 'welcome':

target => '/etc/motd',

content => 'Welcome to Redhat',

order => '01',

}

concat::fragment { 'legal':

# …

}

Page 25: Writing and Publishing Puppet Modules - PuppetConf 2014

Beyond templates● puppetlabs/inifile

ini_setting { 'puppetdbserver':

ensure => present,

section => 'main',

path => "${puppet_confdir}/puppetdb.conf",

setting => 'server',

value => $server,

}

ini_setting { 'puppetdbport':

# …

}

Page 26: Writing and Publishing Puppet Modules - PuppetConf 2014

Beyond Templates● augeas

● domcleal/augeasproviders

augeas { 'sshd_config_permit_root_login':

context => '/files/etc/ssh/sshd_config',

changes => "set PermitRootLogin $permit_root_login",

require => File['/etc/ssh/sshd_config'],

}

sshd_config { "PermitRootLogin":

ensure => present,

value => $permit_root_login,

}

Page 27: Writing and Publishing Puppet Modules - PuppetConf 2014

Smart Parameter Defaults# manifests/params.pp

class ssh::params {

case $::osfamily {

'Debian': {

$ssh_svc = 'ssh'

}

'RedHat': {

$ssh_svc = 'sshd'

}

default: {

fail("${::osfamily} is not supported.")

}

}

}

# manifests/init.pp

class ssh (

# ...

) {

include ssh::params

service { $ssh::params::ssh_svc:

ensure => running,

enable => true,

}

# ...

Page 28: Writing and Publishing Puppet Modules - PuppetConf 2014

The Forge

Page 29: Writing and Publishing Puppet Modules - PuppetConf 2014

Publishing your modulemetadata.json● module name● version (SemVer)● author● summary● source● issues URL● operating system support● dependencies

Page 30: Writing and Publishing Puppet Modules - PuppetConf 2014

Publishing your moduleUse semantic versioning! semver.org

Major.Minor.Patch

Page 31: Writing and Publishing Puppet Modules - PuppetConf 2014

Publishing your moduleChangelog## 2013-12-05 Release 0.10.0### Summary:

This release adds FreeBSD osfamily support and various other improvements to some mods.

### Features:

- Add suPHP_UserGroup directive to directory context- Add support for ScriptAliasMatch directives...

## 2013-09-06 Release 0.9.0### Summary:

...

Page 32: Writing and Publishing Puppet Modules - PuppetConf 2014

Publishing your moduleREADME● docs.puppetlabs.com/puppet/3/reference/READMEtemplate.markdown

Page 33: Writing and Publishing Puppet Modules - PuppetConf 2014

Publishing your modulelicense● choosealicense.com

Page 34: Writing and Publishing Puppet Modules - PuppetConf 2014

Publishing your module$ cd ssh/

$ puppet module build .

$ ls pkg/

cmurphy-ssh-0.0.1 cmurphy-ssh-0.0.1.tar.gz

Page 35: Writing and Publishing Puppet Modules - PuppetConf 2014

TestingWhy we test:● Testing gives us (some) assurance that our

code won’t break production systems● Contributors can run tests without having

the same infrastructure as you

Page 36: Writing and Publishing Puppet Modules - PuppetConf 2014

Testing your module● Smoke testing

# puppet apply --noop tests/init.pp

Page 37: Writing and Publishing Puppet Modules - PuppetConf 2014

Testing your module● Unit testing: rspec-puppet

○ rspec-puppet.com

$ bundle exec rake spec

Page 38: Writing and Publishing Puppet Modules - PuppetConf 2014

Testing your module# spec/classes/init_spec.rb

require 'spec_helper'

describe 'collectd' do

let :facts do

{:osfamily => 'RedHat'}

end

it { should contain_package('collectd').with(

:ensure => 'installed'

)}

it { should contain_service('collectd').with(

:ensure => 'running'

)}

# ...

Page 39: Writing and Publishing Puppet Modules - PuppetConf 2014

Testing your module● Acceptance testing: beaker-rspec

○ github.com/puppetlabs/beaker○ youtu.be/jEJmUQOlaDg

$ bundle exec rspec spec/acceptance

Page 40: Writing and Publishing Puppet Modules - PuppetConf 2014

Testing your module# spec/acceptance/class_spec.rb

require 'spec_helper_acceptance'

case fact('osfamily')

# ...

describe 'ssh class' do

context 'default parameters' do

it 'should work with no errors' do

pp = "class { 'ssh': }"

apply_manifest(pp, :catch_failures => true)

apply_manifest(pp, :catch_changes => true)

end

describe service(servicename) do

it { should be_running }

end

# ...

Page 41: Writing and Publishing Puppet Modules - PuppetConf 2014

Testing your module● Linting

$ bundle exec rake lint

Page 42: Writing and Publishing Puppet Modules - PuppetConf 2014

Maintaining your moduleUpdate your code● fix bugs● add features● manage pull requests

Page 43: Writing and Publishing Puppet Modules - PuppetConf 2014

Installing modulesSearch for modules on forge.puppetlabs.com or puppet module search ssh

Then install with puppet module install saz/ssh

Page 44: Writing and Publishing Puppet Modules - PuppetConf 2014

Where now?Learn more at docs.puppetlabs.com/guides/module_guides/bgtm.html

Get help atAsk: ask.puppetlabs.comIRC: #puppet on freenodeMailing list: groups.google.com/group/puppet-users

Page 45: Writing and Publishing Puppet Modules - PuppetConf 2014

Thanks!Find me:

Colleen Murphyfreenode: crinklegithub: cmurphy

twitter: @pdx_krinkle