Portland Puppet User Group June 2014: Writing and publishing puppet modules

1,544 views

Published on

"Writing and publishing puppet modules" presented by Colleen Murphy at Portland Puppet User Group June 2014 meeting following June 2014 Triage-a-Thon.

Published in: Software
0 Comments
9 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
1,544
On SlideShare
0
From Embeds
0
Number of Embeds
7
Actions
Shares
0
Downloads
36
Comments
0
Likes
9
Embeds 0
No embeds

No notes for slide

Portland Puppet User Group June 2014: Writing and publishing puppet modules

  1. 1. Writing and Publishing Puppet Modules Colleen Murphy, Portland State University
  2. 2. Hello This is a beginner’s approach.
  3. 3. Hello PSU’s College of Engineering’s IT department, aka The Computer Action Team (TheCAT), uses puppet to manage a diverse infrastructure. github.com/pdxcat
  4. 4. 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
  5. 5. What should a module do? ● Set up a service, such as: ○ ssh ○ mysql ○ apache ○ sudo ● Extend puppet functionality. Examples: ○ puppetlabs/stdlib ○ puppetlabs/concat
  6. 6. The strategy Set up the service… without puppet. Then iterate.
  7. 7. Layout of a module yourmodule/ ➔ 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
  8. 8. Layout of a module yourmodule/ ➔ 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
  9. 9. Layout of a module yourmodule/ ➔ 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
  10. 10. Starting out $ puppet module generate cmurphy-ssh && mv cmurphy-ssh ssh Generating module at /etc/puppet/modules/cmurphy-ssh cmurphy-ssh cmurphy-ssh/manifests cmurphy-ssh/manifests/init.pp cmurphy-ssh/spec cmurphy-ssh/spec/spec_helper.rb cmurphy-ssh/tests cmurphy-ssh/tests/init.pp cmurphy-ssh/README cmurphy-ssh/Modulefile $ mkdir ssh/{files,templates}
  11. 11. 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'], } } # tests/init.pp include ssh # or # /etc/puppet/manifests/site.pp node default { include ssh }
  12. 12. 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 # ...
  13. 13. Needs more portability! No one should have to change your code or your files in order to use your module.
  14. 14. 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 # ...
  15. 15. 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'], } # ... # Applying the class class { 'ssh': permit_root_login => 'without-password', }
  16. 16. 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', } }
  17. 17. Templating strategies # templates/sshd_config.erb # Managed by Puppet <% @ports.each do |port| %> Port <%= port %> <% end %> <% @options.each do |k,v| %> <%= k %> <%= v %> <% end %>
  18. 18. Templating strategies Working with tricky configuration files ● Take advantage of Include conf/* 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'), } }
  19. 19. Beyond templates ● puppetlabs/concat concat { '/etc/motd': } concat::fragment { 'welcome': target => '/etc/motd', content => 'Welcome to Redhat', order => '01', } concat::fragment { 'legal': # … }
  20. 20. Beyond templates ● puppetlabs/inifile ini_setting { 'puppetdbserver': ensure => present, section => 'main', path => "${puppet_confdir}/puppetdb.conf", setting => 'server', value => $server, } ini_setting { 'puppetdbport': # … }
  21. 21. 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, }
  22. 22. 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, } # ...
  23. 23. The Forge
  24. 24. Publishing your module Modulefile name 'cmurphy-ssh' version '0.0.1' source 'https://github.com/cmurphy/puppet-module-ssh.git' author 'Colleen Murphy' license 'Apache License, Version 2.0' summary 'Puppet module for ssh' description 'Demonstration of parameterized ssh module' project_page 'https://github.com/cmurphy/puppet-module-ssh' ## Add dependencies, if any: # dependency 'username/name', '>= 1.2.0'
  25. 25. Publishing your module README ● docs.puppetlabs.com/puppet/3/reference/READMEtemplate.markdown license ● choosealicense.com
  26. 26. Publishing your module Changelog ## 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: ...
  27. 27. Publishing your module Use semantic versioning! semver.org Major.Minor.Patch
  28. 28. Publishing your module $ cd ssh/ $ puppet module build . $ ls pkg/ cmurphy-ssh-0.0.1 cmurphy-ssh-0.0.1.tar.gz
  29. 29. Testing Why 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
  30. 30. Testing your module ● Smoke testing # puppet apply --noop tests/init.pp
  31. 31. Testing your module ● Unit testing: rspec-puppet ○ rspec-puppet.com $ bundle exec rake spec
  32. 32. 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' )} # ...
  33. 33. Testing your module ● Acceptance testing: beaker-rspec ○ github.com/puppetlabs/beaker ○ youtu.be/jEJmUQOlaDg $ bundle exec rspec spec/acceptance
  34. 34. 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': }" # Run it twice and test for idempotency apply_manifest(pp, :catch_failures => true) apply_manifest(pp, :catch_failures => true) end describe service(servicename) do it { should be_running } end # ...
  35. 35. Testing your module ● Linting $ bundle exec rake lint
  36. 36. Maintaining your module Update your code ● fix bugs ● add features ● manage pull requests
  37. 37. Installing modules Search for modules on forge.puppetlabs.com or puppet module search Then install with puppet module install
  38. 38. Where now? Learn more at docs.puppetlabs.com/guides/module_guides/bgtm.html Get help at Ask: ask.puppetlabs.com IRC: #puppet on freenode Mailing list: groups.google.com/group/puppet-users
  39. 39. Thanks! Find me: Colleen Murphy freenode: crinkle github: cmurphy twitter: @pdx_krinkle

×