OSDC 2014: Ole Michaelis & Sönke Rümpler: Make it SOLID - Software Architecture for System...

Post on 10-May-2015

495 views 3 download

Tags:

description

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.

Transcript of OSDC 2014: Ole Michaelis & Sönke Rümpler: Make it SOLID - Software Architecture for System...

Ole Michaelis & Sönke Ruempler | Jimdo

Make it SOLIDSoftware Architecture for System Administrators

OSDC 2014

Ole Michaelis“Open Source Rockstar”

@CodeStarsgithub.com/nesQuick

codestars.eu

OSDC 2014

Sönke Ruempler

“Chief Trolling Officer”

@s0enkegithub.com/s0enke

ruempler.eu

OSDC 2014

Jimdo

OSDC 2014

because infrastructure development is neither a Jenga game!

S.O.L.I.D

OSDC 2014

OSDC 2014

S O L I D

OSDC 2014

Adev/ops

story

Oleas

Junior Admin

SönkeasDr. Software

OSDC 2014

the basics

OSDC 2014

configuration management

IdempotentDeclarativeConvergent

Abstract

OSDC 2014

software architecture

VS.36 years

>2000 years

OSDC 2014

OSDC 2014

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

OSDC 2014

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

OSDC 2014

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]

}

}

}

OSDC 2014

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!

OSDC 2014

Would you solder a lamp directly to the electrical wiring in a

wall?

Dependency Inversion

OSDC 2014

OSDC 2014

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]

}

}

}

OSDC 2014

Stuff tends to get big

Beware of god classes!

OSDC 2014

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'] } }

OSDC 2014

OSDC 2014

?

OSDC 2014

OSDC 2014

rspec-puppet

test-kitchen

OSDC 2014

OSDC 2014

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

?

OSDC 2014

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 }}

OSDC 2014

Just because you can, doesn’t mean you

should!

Single Responsibility

OSDC 2014

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

OSDC 2014

OSDC 2014

“programs […] are changed by adding new code, rather than by changing

existing code”

Open ClosePrinciple

OSDC 2014

OSDC 2014

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}

OSDC 2014

OSDC 2014

OSDC 2014

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!

OSDC 2014

>

OSDC 2014

OSDC 2014

?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]

}

}

}

OSDC 2014

Don’t call us,we call you!

Hollywood Principle

OSDC 2014

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.

OSDC 2014

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.

OSDC 2014

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.

OSDC 2014

OSDC 2014

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' }} ?

OSDC 2014

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

OSDC 2014

OSDC 2014

?

OSDC 2014

“puppet separate code and data”

I’m feeling lucky

OSDC 2014

# /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

OSDC 2014

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}

OSDC 2014

hiera

AWS/Cloudformation LDAP

DNSyour selfwritten stuff

OSDC 2014

OSDC 2014

OSDC 2014

OSDC 2014

What about I and L

in SOLID?

OSDC 2014

You want me to plug this in, where?

Interface Segregation

OSDC 2014

If it looks like a duck, quacks like a duck, but

need batteries - you probably have the wrong abstraction!

Liskov Substitution

OSDC 2014

S O L I D

OSDC 2014

OSDC 2014

Structure your code!Node

ProfileProfilesRole ProfileModules

Resources

OSDC 2014

Puppet forge

puppet module registry

OSDC 2014

Librarian Puppetr10k

Berkshelf (chef)

OSDC 2014

stdmod

https://github.com/stdmod

OSDC 2014

sandboxeddevelopment

https://github.com/mlafeldt/skeleton-cookbookhttps://github.com/Jimdo/puppet-skeleton

OSDC 2014

server spechttp://serverspec.org/

beaker(puppet)

https://github.com/puppetlabs/beaker

OSDC 2014

Thank you!

OSDC 2014

@CodeStarsole@jimdo.com

@s0enkesoenke@jimdo.com

Questions?

OSDC 2014

*I ’m just a blank slide*

OSDC 2014

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•