WRITING & SHARINGGREAT MODULESCody Herriges, Puppet LabsTwitter: @odyrf | Freenode: odyi
WHO IS THIS GUY?Destiny was written in the 6th grade.Professional Services @puppetlabs, ~2 yearsOperations Engineer @puppe...
THINGS I DOOld public modules (The PS era)puppetlabs-java_ks: java keystore managementpuppetlabs-corosync: build pacemaker...
LET’S TALK ABOUTMODULES
BEST PRACTICESTraditional development: 50+ years to matureModern config. mgmt: 15 years, maxBest practices are evolving
SO WHERE DO WE START?Separate your logic and configurationKnow your interfaceUse semantic versioningReuse everythingLevera...
DATA/LOGICSEPARATION
SEPARATE LOGIC FROM DATALogic != DataExample: configuring a service on different platformsShouldn’t have to update every f...
PACKAGE/FILE/SERVICEHumble beginnings for many modulesclass mysql::server {package { mysql-server:ensure => present,}file ...
PROBLEMS WITH PACKAGE/FILE/SERVICENothing inherently wrongOverly simpleVery staticGenerally requires overhaul for differen...
RUDIMENTARY DATA/LOGIC SEPARATIONclass mysql::server {include mysql::paramspackage { mysql-server:name => $mysql::params::...
HARDCODING TUNABLE VALUESWant to prevent people from reusing your modules?Hardcode everything!
BAD PARAMS USEParams class = goodWhy is this bad?Site specific defaults?INSECURE DEFAULTS‽class mysql::params {$allow_host...
GOOD PARAMS USEForce user to supply dataFail fastclass mysql::params($allow_hosts, # Force the module user to fill this ou...
DATA BINDING
DATA BINDINGNew in Puppet 3: data bindingProvides a method for configuring modules
USING DATA BINDINGDefine data in a data storefiledatabaseweb serviceAutomatically load data in the relevant manifestsIt is...
USING DATA BINDINGclass mysql::params($allow_hosts,$database_password,$database_user = root) {...}# $datadir/common.yaml--...
USING MODULES ASINTERFACES
MODULES AS INTERFACESPuppet simplifies management of servicesDefines how people interact with that servicePuppet modules d...
BE OPINIONATEDCannot make every option tunableYou’ll go insaneRequire mandatory dataAdd parameters for frequently changed ...
BUT OTHER OPINIONS ARE NICE TOOYou can’t always support every optionAllow people to directly insert their own configuration
OVERRIDE EXAMPLE: PARTIAL TEMPLATESModule provides template fragmentsUser assembles these into a full config
CREATING A PARTIAL TEMPLATE<%# nginx/templates/vhost/_listen.conf.erb %><%# Configuration fragment for listening on IPv4 a...
USING PARTIAL TEMPLATESExample: my_nginx_app/templates/nginx-vhost.conf.erbserver {<%= scope.function_template([nginx/vhos...
SEMVER
WITHOUT SEMANTIC VERSIONINGA cautionary tale of versioning gone bad1.0.0 Initial release for managing cacti1.1.1 Change se...
UPGRADING SHOULD BE BORINGAPI breakage means upgrading is dangerousNobody wants to upgrade if it means uncertaintySemantic...
WHAT IS SEMVER?Version strings should have meaningReleases match the format x.y.zValues indicate what’s changed in that ve...
MAJOR RELEASESExample: x.0.0Backwards incompatible changesChanging class namesChanging parameter namesDropping platform su...
MINOR RELEASESExample: x.y.0Backwards compatible featuresAdding support for new platformsAdding parametersAdding features
PATCH RELEASESExample: x.y.zBugfixesDocumentationTestsAnything that can’t be called a feature
SEMVER AS A CONTRACTIf you use SemVer, you’re making an agreement to avoidmaking breaking changesWhat is a breaking change...
WHAT IS PUBLIC?Publicly exposed classesClass parametersThe final behavior of your class
WHAT IS PRIVATE?The actual resources used in your classes and definesAs long as they result in the same functionalityClass...
SAFETY IN SEMVERSemVer takes the risk out of upgradingYou can understand the implications of upgrading rightawayHow Puppet...
MAKE OTHER PEOPLE DOYOUR WORK
AKA
REUSE MODULES
REUSE MODULESWriting good code is hard.Make other people do your work.Being upstream is hard.
DISCOVERY VIA THE FORGEPuppet Forge has close to 1200 modulesProvides a single point to discover and install modulesEasy a...
GET DEPENDENCIES FROM THE FORGEroot@example:~# puppet module install puppetlabs/mysqlNotice: Preparing to install into /et...
COLLABORATE ON EXISTING MODULESLots of good modules are out thereEncourage people to publish on the ForgeHelp improve exis...
SMALL CONTRIBUTIONS HELPDocumentationBug fixesIssue reports
ESTABLISH ACOMMUNITY
SURVIVING SUCCESSYour module is a hit!Prepare for a deluge of bug reports and feature requests
POPULARITY = MORE WORKThings users are good at:Finding bugsFiling feature requestsRequesting things like “documentation”Fi...
BUILD YOUR COMMUNITYBug reports = people careShow people how to helpAsk for pull requestsGuide people through the contribu...
ENDQUESTIONS?
Upcoming SlideShare
Loading in …5
×

Writing & Sharing Great Modules - Puppet Camp Boston

1,509 views

Published on

"Writing & sharing great modules" by Cody Herriges at Puppet Camp Boston 2013.

0 Comments
4 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
1,509
On SlideShare
0
From Embeds
0
Number of Embeds
12
Actions
Shares
0
Downloads
0
Comments
0
Likes
4
Embeds 0
No embeds

No notes for slide

Writing & Sharing Great Modules - Puppet Camp Boston

  1. 1. WRITING & SHARINGGREAT MODULESCody Herriges, Puppet LabsTwitter: @odyrf | Freenode: odyi
  2. 2. WHO IS THIS GUY?Destiny was written in the 6th grade.Professional Services @puppetlabs, ~2 yearsOperations Engineer @puppetlabs, ~1 yearIntegration Engineer @puppetlabs, ~1 month
  3. 3. THINGS I DOOld public modules (The PS era)puppetlabs-java_ks: java keystore managementpuppetlabs-corosync: build pacemaker clustersLess old public modules (The Operations era)puppetlabs-apacheds: stands up Apache DirectoryServerpuppetlabs-ldap_entry: manipulates an ldap serverpuppetlabs-stunnel: set up SSL tunnelsLatelypuppet-openstack: build your openstack
  4. 4. LET’S TALK ABOUTMODULES
  5. 5. BEST PRACTICESTraditional development: 50+ years to matureModern config. mgmt: 15 years, maxBest practices are evolving
  6. 6. SO WHERE DO WE START?Separate your logic and configurationKnow your interfaceUse semantic versioningReuse everythingLeverage the community
  7. 7. DATA/LOGICSEPARATION
  8. 8. SEPARATE LOGIC FROM DATALogic != DataExample: configuring a service on different platformsShouldn’t have to update every file in a module
  9. 9. PACKAGE/FILE/SERVICEHumble beginnings for many modulesclass mysql::server {package { mysql-server:ensure => present,}file { /etc/mysql/my.cnf:ensure => present,content => template(mysql/server/my.cnf.erb),require => Package[mysql-server],}service { mysqld:ensure => running,enable => true,subscribe => File[/etc/mysql/my.conf],}}
  10. 10. PROBLEMS WITH PACKAGE/FILE/SERVICENothing inherently wrongOverly simpleVery staticGenerally requires overhaul for different platforms
  11. 11. RUDIMENTARY DATA/LOGIC SEPARATIONclass mysql::server {include mysql::paramspackage { mysql-server:name => $mysql::params::server_package,ensure => present,}file { my.cnf:path => $mysql::params::server_config,ensure => present,source => puppet:///modules/mysql/my.cnf,require => Package[mysql-server],}service { mysql-server:name => $mysql::params::server_service,ensure => running,
  12. 12. HARDCODING TUNABLE VALUESWant to prevent people from reusing your modules?Hardcode everything!
  13. 13. BAD PARAMS USEParams class = goodWhy is this bad?Site specific defaults?INSECURE DEFAULTS‽class mysql::params {$allow_hosts = 172.16.0.1/24$root_password = changeme$root_user = root}
  14. 14. GOOD PARAMS USEForce user to supply dataFail fastclass mysql::params($allow_hosts, # Force the module user to fill this out$root_password, # Fail fast rather than potentially use bad data$root_user = root # Sane default) {...}
  15. 15. DATA BINDING
  16. 16. DATA BINDINGNew in Puppet 3: data bindingProvides a method for configuring modules
  17. 17. USING DATA BINDINGDefine data in a data storefiledatabaseweb serviceAutomatically load data in the relevant manifestsIt is hierarchical
  18. 18. USING DATA BINDINGclass mysql::params($allow_hosts,$database_password,$database_user = root) {...}# $datadir/common.yaml---mysql::params::allow_hosts: 10.126.8.0/24# $datadir/qa.mysite.local.yaml---mysql::params::allow_hosts: 10.134.8.0/24
  19. 19. USING MODULES ASINTERFACES
  20. 20. MODULES AS INTERFACESPuppet simplifies management of servicesDefines how people interact with that servicePuppet modules define an interface for that serviceCreates two challengesWhat options are supported?What options should users configure?
  21. 21. BE OPINIONATEDCannot make every option tunableYou’ll go insaneRequire mandatory dataAdd parameters for frequently changed dataOffer an ‘override’ option
  22. 22. BUT OTHER OPINIONS ARE NICE TOOYou can’t always support every optionAllow people to directly insert their own configuration
  23. 23. OVERRIDE EXAMPLE: PARTIAL TEMPLATESModule provides template fragmentsUser assembles these into a full config
  24. 24. CREATING A PARTIAL TEMPLATE<%# nginx/templates/vhost/_listen.conf.erb %><%# Configuration fragment for listening on IPv4 and IPv6 with SSL %><% unless @sslonly -%>listen <%= port %>;<% if scope.lookupvar(::ipaddress6) -%>listen [::]:<%= port %>;<% end -%><% end -%><% if ssl -%>listen <%= ssl_port %> ssl;<% if scope.lookupvar(::ipaddress6) -%>listen [::]:<%= ssl_port %> ssl;<% end -%><% end -%>
  25. 25. USING PARTIAL TEMPLATESExample: my_nginx_app/templates/nginx-vhost.conf.erbserver {<%= scope.function_template([nginx/vhost/_listen.conf.erb]) %>root /usr/share/empty;location / {proxy_pass <%= @proto %>://workers;proxy_redirect off;proxy_next_upstream error timeout invalid_header http_500 http_503;proxy_connect_timeout 5;}}
  26. 26. SEMVER
  27. 27. WITHOUT SEMANTIC VERSIONINGA cautionary tale of versioning gone bad1.0.0 Initial release for managing cacti1.1.1 Change serverparam to servername1.1.2 Move params from cacti::data to cacti::params1.2.0 Updated README1.2.1 Drops support for CentOS 51.3.0 This module now manages munin2.0.0 I can update versions whenever I want?10.51.100 THIS IS AWESOME!-4.number.999999999999 I’VE CREATED A MONSTER
  28. 28. UPGRADING SHOULD BE BORINGAPI breakage means upgrading is dangerousNobody wants to upgrade if it means uncertaintySemantic versioning helps mitigate this
  29. 29. WHAT IS SEMVER?Version strings should have meaningReleases match the format x.y.zValues indicate what’s changed in that version
  30. 30. MAJOR RELEASESExample: x.0.0Backwards incompatible changesChanging class namesChanging parameter namesDropping platform support
  31. 31. MINOR RELEASESExample: x.y.0Backwards compatible featuresAdding support for new platformsAdding parametersAdding features
  32. 32. PATCH RELEASESExample: x.y.zBugfixesDocumentationTestsAnything that can’t be called a feature
  33. 33. SEMVER AS A CONTRACTIf you use SemVer, you’re making an agreement to avoidmaking breaking changesWhat is a breaking change?What’s public?What’s private?
  34. 34. WHAT IS PUBLIC?Publicly exposed classesClass parametersThe final behavior of your class
  35. 35. WHAT IS PRIVATE?The actual resources used in your classes and definesAs long as they result in the same functionalityClasses that are documented as privateIf you document that a class is private, people shouldn’tuse it
  36. 36. SAFETY IN SEMVERSemVer takes the risk out of upgradingYou can understand the implications of upgrading rightawayHow Puppet is doing it3.1.0: Better support for Ruby code loading3.1.1: Security fixes3.2.0: External CA support, types & providers forOpenWRT4.0.0: Tachyon based transport layer
  37. 37. MAKE OTHER PEOPLE DOYOUR WORK
  38. 38. AKA
  39. 39. REUSE MODULES
  40. 40. REUSE MODULESWriting good code is hard.Make other people do your work.Being upstream is hard.
  41. 41. DISCOVERY VIA THE FORGEPuppet Forge has close to 1200 modulesProvides a single point to discover and install modulesEasy access to documentationREADMERelease notesAuto generated Type & provider documentation
  42. 42. GET DEPENDENCIES FROM THE FORGEroot@example:~# puppet module install puppetlabs/mysqlNotice: Preparing to install into /etc/puppet/modules ...Notice: Downloading from https://forge.puppetlabs.com ...Notice: Installing -- do not interrupt .../etc/puppet/modules└─┬ puppetlabs-mysql (v0.6.1)└── puppetlabs-stdlib (v4.1.0)
  43. 43. COLLABORATE ON EXISTING MODULESLots of good modules are out thereEncourage people to publish on the ForgeHelp improve existing modulesOnly you can prevent ecosystem fragmentation
  44. 44. SMALL CONTRIBUTIONS HELPDocumentationBug fixesIssue reports
  45. 45. ESTABLISH ACOMMUNITY
  46. 46. SURVIVING SUCCESSYour module is a hit!Prepare for a deluge of bug reports and feature requests
  47. 47. POPULARITY = MORE WORKThings users are good at:Finding bugsFiling feature requestsRequesting things like “documentation”Finding more bugs
  48. 48. BUILD YOUR COMMUNITYBug reports = people careShow people how to helpAsk for pull requestsGuide people through the contribution processFind people to give commit rights to
  49. 49. ENDQUESTIONS?

×