Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Make it SOLID Software Architecture for System Administrators

Make it SOLID Software Architecture for System Administrators

Gave this talk at the International PHP Conference on October 30th, 2013
Follow me on Twitter: @CodeStars

Starting with Chef or Puppet as a System Administrator will lead you to a problem where you are not sure what’s the best solution of a problem in terms of software architecture.
We will give you a brief overview of general well known and battle tested software patterns, which also applies to infrastructure management code. In addition, we’ll also show Antipatterns, and best practices.

Ole Michaelis

October 30, 2013
Tweet

More Decks by Ole Michaelis

Other Decks in Technology

Transcript

  1. Ole Michaelis & Sönke Ruempler | Jimdo
    Make it SOLID
    Software Architecture for System Administrators

    View full-size slide

  2. Ole Michaelis
    “Open Source Rockstar”
    @CodeStars
    github.com/nesQuick
    codestars.eu

    View full-size slide

  3. Sönke
    Ruempler
    “Chief Trolling Officer”
    @s0enke
    github.com/s0enke
    ruempler.eu

    View full-size slide

  4. because infrastructure development is
    neither a Jenga game!
    S.O.L.I.D

    View full-size slide

  5. a little poll!
    http://images.fineartamerica.com/images-medium-large/live-long-mr-spock-tobias-woelki.jpg

    View full-size slide

  6. A
    dev/ops
    story
    Ole
    as
    Junior Admin
    Sönke
    as
    Dr. Software

    View full-size slide

  7. software architecture
    VS.
    36 years
    >2000 years

    View full-size slide

  8. configuration management
    Idempotent
    Declarative
    Convergent
    Abstract

    View full-size slide

  9. node web-1 {
    $role = 'web-app-a'
    $has_apache = true;
    include php5
    }
    node web-2 {
    $role = 'web-app-b'
    $has_fcgi=true
    include php5
    }
    # has both enabled, but needs a special config
    node web-3 {
    $role = 'web-app-c'
    $has_fcgi=true
    $has_apache=true
    include php5
    }
    Web
    App 1
    Web
    App 2
    Web
    App 3

    View full-size slide

  10. class php5 {
    if ($::has_fcgi)
    package { 'php5-cli' : ensure => installed }
    }
    if ($::has_apache) {
    package { 'php5-apache' : ensure => installed }
    }
    if ($::role == 'web-app-c')
    package { 'php5-web-app-c-special-module' }
    file { '/etc/php5/php.ini' :
    source => 'puppet:///modules/php5/php.ini-web-app-c'
    }
    }
    }
    Global variable!
    Out of Context!
    No abstraction

    View full-size slide

  11. class php5(
    $has_fcgi = false,
    $has_apache = false,
    $role = undef
    ) {
    if ($has_fcgi)
    package { 'php5-cli' : ensure => installed }
    }
    if ($has_apache) {
    package { 'php5-apache' : ensure => installed }
    }
    if ($role == 'web-app-c') {
    package { 'php5-web-app-c-special-module' }
    file { '/etc/php5/php.ini' :
    source => 'puppet:///modules/php5/php.ini-web-app-c'
    ,
    require => Package[php-fcgi]
    }
    }

    View full-size slide

  12. node 'web-1' {
    $role = 'web-app-a'
    $has_apache = true
    class { 'php5' :
    has_apache => true,
    role => 'web-app-a'
    }
    }
    node 'web-2' {
    $role = 'web-app-b'
    $has_fcgi = true
    class { 'php5' :
    has_fcgi => true,
    role => 'web-app-b'
    }
    }
    Injection!
    Injection!

    View full-size slide

  13. Would you solder a
    lamp directly to the
    electrical wiring in a
    wall?
    Dependency
    Inversion

    View full-size slide

  14. class php5(
    $has_fcgi = false,
    $has_apache = false,
    $role = undef
    ) {
    if ($has_fcgi)
    package { 'php5-cli' : ensure => installed }
    }
    if ($has_apache) {
    package { 'php5-apache' : ensure => installed }
    }
    if ($role == 'web-app-c') {
    package { 'php5-web-app-c-special-module' }
    file { '/etc/php5/php.ini' :
    source => 'puppet:///modules/php5/php.ini-web-app-c'
    require => Package[php-fcgi]
    }
    }
    }

    View full-size slide

  15. Stuff tends to
    get big
    Beware of god classes!

    View full-size slide

  16. if ($lighttpd) {
    package { 'php5-cgi': }
    configdir { '/etc/php5/cgi': require => Package['php5-cgi'] }
    configdir { '/etc/php5/cgi/conf.d': require => Package['php5-cgi'] }
    if ($testserver) {
    configfile { '/etc/php5/cgi/php.ini': sourcename => 'php5/cgi/php.ini-testserver',
    require => Package['php5-cgi'] }
    } else {
    if ($cms ) {
    configfile { '/etc/php5/cgi/php.ini': sourcename => 'php5/cgi/php.ini-cms',
    require => Package['php5-cgi'] }
    } else {
    if ($mgmt ) {
    configfile { '/etc/php5/cgi/php.ini': sourcename => 'php5/cgi/php.ini-mgmt',
    require => Package['php5-cgi'] }
    } else {
    if ($lc ) {
    configfile { '/etc/php5/cgi/php.ini': sourcename => 'php5/cgi/php.ini-lc.
    jimdo.com', require => Package['php5-cgi'] }
    } else {
    configfile { '/etc/php5/cgi/php.ini': sourcename => 'php5/cgi/php.ini',
    require => Package['php5-cgi'] }
    }
    }
    }
    }
    configfile { '/etc/php5/cgi/conf.d/pdo.ini': sourcename => 'php5/cgi/conf.d/pdo.ini',
    require => Package['php5-cgi'] }
    }

    View full-size slide

  17. rspec-puppet
    test-kitchen

    View full-size slide

  18. describe :node => 'web-1' do
    it { should contain_package ('php5-fcgi') }
    end
    describe :node => 'web-2' do
    it { should contain_package ('php5-apache2' ) }
    end
    describe :node => 'web-3' do
    it { should contain_package ('php5-fcgi') }
    it { should contain_package ('php5-apache2' ) }
    end
    Test php5 class:
    Install Package
    ?

    View full-size slide

  19. describe :class => 'php5::fcgi' do
    it { should contain_package('php5-cli') }
    end
    describe :class => 'php5::apache' do
    it { should contain_package('php5-apache2') }
    end
    class php5::fgci {
    package { 'php5-cgi' : ensure => installed }
    }
    class php5::apache {
    package { 'php5-apache' : ensure => installed }
    }

    View full-size slide

  20. Just because you can,
    doesn’t mean you
    should!
    Single
    Responsibility

    View full-size slide

  21. describe :node => 'web-1' do
    it { should include_class('php5::fcgi') }
    it { should contain_package('php5-fcgi') }
    end
    describe :node => 'web-2' do
    it { should include_class('php5::apache') }
    it { should contain_package('php5-apache2') }
    end
    node web-1 {
    include php5::apache
    }
    node web-2 {
    include php5::fcgi
    }
    Tests
    Code

    View full-size slide

  22. “programs … are changed by adding new
    code, rather than by changing existing
    code”
    Open Close
    Principle

    View full-size slide

  23. new
    requirements...
    now web app 1 needs a second
    node
    node web-1 {
    $role = 'web-app-a'
    include php5::apache
    }
    node web-1a {
    $role = 'web-app-a'
    include php5::apache
    }

    View full-size slide

  24. class role::web-app-a {
    include php5::apache
    }
    node web-1 {
    include role::web-app-
    a
    }
    node web-1a {
    include role::web-app-
    a
    }
    Our new role!
    And nodes just
    include it!

    View full-size slide

  25. ?
    class php5::fcgi($role = undef) {
    if ($role == 'web-app-c') {
    package { 'php5-web-app-c-special-module' }
    file { '/etc/php5/php.ini' :
    source =>
    'puppet:///modules/php5/php.ini-web-app-c',
    require => Package[php-fcgi]
    }
    }
    }

    View full-size slide

  26. Don’t call us,
    we call you!
    Hollywood
    Principle

    View full-size slide

  27. class role::web-app-c::special-php-stuff {
    package { 'php5-web-app-c-special-module' }
    file { '/etc/php5/php.ini' :
    source => 'puppet:///modules/php5/php.ini-web-app-c'
    }
    }
    1. Split out the special case into its own class.

    View full-size slide

  28. class php5::fcgi($include_after_package_install = undef) {
    package { 'php5-fcgi' : ensure => installed }
    if ($include_after_package_install)
    include $include_after_package_install
    Package['php5-fcgi'] -> Class[$include_after_package_install]
    }
    }
    2. Make the special case pluggable and
    reusable.
    2a. And name it abstract.

    View full-size slide

  29. class role::web-app-c {
    include php5::apache
    class { 'php5::fcgi' :
    include_after_package_install => 'profile::web-app-c::special-php-stuff'
    }
    }
    3. Pass the special case as dependency in our
    web-app-c.

    View full-size slide

  30. class profile::web-app-c::special-php-stuff {
    package { 'php5-web-app-c-special-module' }
    file { '/etc/php5/php.ini' :
    source => 'puppet:///modules/php5/php.ini-web-app-c'
    }
    }
    ?

    View full-size slide

  31. define php5::specialconfig(
    $ensure = present,
    $sapi,
    $module,
    $key,
    $value,
    $section = undef,
    $path = '/etc/php5/%s/conf.d/%s.ini'
    ) {
    ini_setting { $title:
    ensure => present,
    path => sprintf($path, $sapi, $module),
    section => $section,
    setting => $key,
    value => $value,
    require => Package["php5-${sapi}"]
    }
    }

    View full-size slide

  32. “puppet separate code and data”
    I’m feeling lucky

    View full-size slide

  33. # /etc/puppet/hieradata/web1.yaml
    ---
    classes:
    - profile::web-app-a
    # /etc/puppet/hieradata/web1a.yaml
    ---
    classes:
    - profile::web-app-a
    # /etc/puppet/hieradata/web2.yaml
    ---
    classes:
    - profile::web-app-c
    # /etc/puppet/hieradata/web3.yaml
    ---
    classes:
    - profile::web-app-c
    puppet-hiera
    example in YAML

    View full-size slide

  34. node default {
    hiera_include('classes')
    }
    node web-1 {
    include role::web-app-a
    }
    node web-1a {
    include role::web-app-a
    }
    node web-2 {
    include role::web-app-b
    }
    node web-3 {
    include role::web-app-c
    }

    View full-size slide

  35. hiera
    AWS/Cloudformation LDAP
    DNS
    your selfwritten
    stuff

    View full-size slide

  36. What about
    I and L
    in SOLID?

    View full-size slide

  37. You want me to plug
    this in, where?
    Interface
    Segregation

    View full-size slide

  38. If it looks like a duck,
    quacks like a duck, but
    need batteries - you
    probably have the
    wrong abstraction!
    Liskov
    Substitution

    View full-size slide

  39. Structure your code!
    Node
    Profile
    Profiles
    Role Profile
    Modules
    Resources

    View full-size slide

  40. Puppet forge
    puppet module registry

    View full-size slide

  41. Dependency Management
    Librarian Puppet
    Berkshelf (chef)

    View full-size slide

  42. stdmod
    https://github.com/stdmod

    View full-size slide

  43. server spec
    http://serverspec.org/

    View full-size slide

  44. sandboxed
    development
    https://github.com/mlafeldt/skeleton-cookbook
    https://github.com/Jimdo/puppet-skeleton

    View full-size slide

  45. Thank you!
    Rate this talk!
    https://joind.in/9578

    View full-size slide

  46. *I ’m just a blank slide*

    View full-size slide

  47. Sources
    • http://www.slideshare.net/PuppetLabs/garethrushgrove-puppetconf
    • http://www.slideshare.net/PuppetLabs/alessandro-franceschi-new
    • https://github.com/jedi4ever/stop-the-fork
    • http://lostechies.com/derickbailey/2009/02/11/solid-development-principles-in-motivational-
    pictures/
    • https://speakerdeck.com/jfryman/refactoring-puppet
    • http://www.clker.com/cliparts/e/2/a/d/1206574733930851359Ryan_Taylor_Green_Tick.svg.med.
    png
    • http://www.craigdunn.org/2012/05/239/
    • http://cdn.slashgear.com/wp-content/uploads/2012/10/google-datacenter-tech-13.jpg
    • http://deviq.com/Media/Default/Article/Dont-Call-Us-Well-Call-You-Jun-2013.png
    • http://www.timeshighereducation.co.uk/Pictures/web/g/q/g/copy_paste_keyboard_button_450.jpg
    • http://sanremo.com.au/wp-content/uploads/2013/05/lasagna.jpg
    • http://4.bp.blogspot.
    com/_9kQQgQD35rY/SaV5p8YBGhI/AAAAAAAAAkg/HOvlhIo7yGI/s400/06_Red_Green_Refactor.
    JPG
    • http://www.thelolshop.com/wp-content/uploads/2012/11/20121126-101937.jpg

    View full-size slide