SlideShare a Scribd company logo
Applying SOLID
Principles to
Infrastructure as Code
@attachmentgenie
~$ whoami~$ whoami
● I used to be a Molecular Biologist,I used to be a Molecular Biologist,
● Then became a Dev,Then became a Dev,
● Now an Ops.Now an Ops.
● Open Source Consultant @Open Source Consultant @inuits.euinuits.eu
classclass webserver {webserver {
include apacheinclude apache
apache::vhost {apache::vhost { 'vhost.example.com''vhost.example.com'::
port =>port => '80''80',,
docroot =>docroot => '/var/www/vhost''/var/www/vhost',,
}}
include ::phpinclude ::php
classclass {{ '::mysql::server''::mysql::server'::
root_password =>root_password => 'secret''secret',,
}}
classclass {{ '::mysql::server::account_security''::mysql::server::account_security': }: }
classclass {{ '::mysql::client''::mysql::client': }: }
mysql::db {mysql::db { 'mydb''mydb'::
user =>user => 'myuser''myuser',,
password =>password => 'mypass''mypass',,
host =>host => 'localhost''localhost',,
grant => [grant => ['SELECT''SELECT',, 'UPDATE''UPDATE']],,
}}
include ::firewallinclude ::firewall
firewall{firewall{'http''http'::
dport =>dport => '80''80',,
proto =>proto => 'tcp''tcp',,
action =>action => 'accept''accept',,
}}
Roles & ProfilesRoles & Profiles
● Component modules — Modules that manageComponent modules — Modules that manage
one particular technology, for exampleone particular technology, for example
puppetlabs/apache.puppetlabs/apache.
● Profiles — Wrapper classes that use (multiple)Profiles — Wrapper classes that use (multiple)
component modules to configure a layeredcomponent modules to configure a layered
technology stack.technology stack.
● Roles — Wrapper classes that use multipleRoles — Wrapper classes that use multiple
profiles to build a complete systemprofiles to build a complete system
configuration.configuration.
https://www.craigdunn.org/2012/05/239/https://www.craigdunn.org/2012/05/239/
Roles & Profiles - TLDRRoles & Profiles - TLDR
● Component modules — Resources definitions.Component modules — Resources definitions.
● Profiles — Your company specificProfiles — Your company specific
implementation.implementation.
● Roles — Bussiness role.Roles — Bussiness role.
Roles & ProfilesRoles & Profiles
classclass roles::webserver {roles::webserver {
include profiles::apacheinclude profiles::apache
include profiles::mysqlinclude profiles::mysql
}}
Roles & ProfilesRoles & Profiles
classclass roles::webserver {roles::webserver {
include ::profiles::apacheinclude ::profiles::apache
}}
classclass roles::database {roles::database {
include ::profiles::mysqlinclude ::profiles::mysql
}}
Roles & ProfilesRoles & Profiles
● First approach: Granular rolesFirst approach: Granular roles
● Second approach: Conditional logicSecond approach: Conditional logic
● Third approach: Nested rolesThird approach: Nested roles
● Fourth approach: Multiple roles per nodeFourth approach: Multiple roles per node
● Fifth approach: Super profilesFifth approach: Super profiles
● Sixth approach: Building roles in the nodeSixth approach: Building roles in the node
classifierclassifier
https://puppet.com/docs/pe/2017.3/managinghttps://puppet.com/docs/pe/2017.3/managing
_nodes/designing_convenient_roles.html_nodes/designing_convenient_roles.html
““loose coupling, high cohesion”loose coupling, high cohesion”
Unknown?Unknown?
Roles & ProfilesRoles & Profiles
classclass roles::allinone {roles::allinone {
include ::profiles::apacheinclude ::profiles::apache
include ::profiles::mysqlinclude ::profiles::mysql
}}
Design PatternsDesign Patterns
Model View ControllerModel View Controller
● The model is the central component of theThe model is the central component of the
pattern. It expresses the application's behaviorpattern. It expresses the application's behavior
in terms of the problem domain, independent ofin terms of the problem domain, independent of
the user interface.[6] It directly manages thethe user interface.[6] It directly manages the
data, logic and rules of the application.data, logic and rules of the application.
● The controller, accepts input and converts it toThe controller, accepts input and converts it to
commands for the model or view.commands for the model or view.
● A view can be any output representation ofA view can be any output representation of
information, such as a chart or a diagram.information, such as a chart or a diagram.
Multiple views of the same information areMultiple views of the same information are
possible, such as a bar chart for managementpossible, such as a bar chart for management
and a tabular view for accountants.and a tabular view for accountants.
MVC -TLDRMVC -TLDR
● Model: heavy lifting partModel: heavy lifting part
● Controller: Logic flow coordinatorController: Logic flow coordinator
● View: Consumable render of dataView: Consumable render of data
R&P vs MVCR&P vs MVC
● Component modules — Resources definitions.Component modules — Resources definitions.
● Profiles — Your company specificProfiles — Your company specific
implementation.implementation.
● Roles — Bussiness role.Roles — Bussiness role.
● Model: heavy lifting partModel: heavy lifting part
● Controller: Flow coordinatorController: Flow coordinator
● View: Consumable render of dataView: Consumable render of data
OO - Objective OrientedOO - Objective Oriented
● Objects and classesObjects and classes
● Dynamic dispatch/message passingDynamic dispatch/message passing
● EncapsulationEncapsulation
● Composition, inheritance, and delegationComposition, inheritance, and delegation
● PolymorphismPolymorphism
● Open recursionOpen recursion
SOLID PrincipleSOLID Principle
mnemonic acronym for five design principlesmnemonic acronym for five design principles
intended to make software designs moreintended to make software designs more
understandable, flexible and maintainableunderstandable, flexible and maintainable
Robert C. Martin, 2002Robert C. Martin, 2002
SOLID PrincipleSOLID Principle
SS — Single Responsibility Principle— Single Responsibility Principle
OO— Open-Closed Principle— Open-Closed Principle
LL — Liskov Substitution Principle— Liskov Substitution Principle
II — Interface Segregation Principle— Interface Segregation Principle
DD — Dependency Inversion Principle— Dependency Inversion Principle
Single Responsibility PrincipleSingle Responsibility Principle
““A class should have one, and only one,A class should have one, and only one,
reason to change”reason to change”
classclass webserver {webserver {
include apacheinclude apache
apache::vhost {apache::vhost { 'vhost.example.com''vhost.example.com'::
port =>port => '80''80',,
docroot =>docroot => '/var/www/vhost''/var/www/vhost',,
}}
include ::phpinclude ::php
classclass {{ '::mysql::server''::mysql::server'::
root_password =>root_password => 'secret''secret',,
}}
classclass {{ '::mysql::server::account_security''::mysql::server::account_security': }: }
classclass {{ '::mysql::client''::mysql::client': }: }
mysql::db {mysql::db { 'mydb''mydb'::
user =>user => 'myuser''myuser',,
password =>password => 'mypass''mypass',,
host =>host => 'localhost''localhost',,
grant => [grant => ['SELECT''SELECT',, 'UPDATE''UPDATE']],,
}}
include ::firewallinclude ::firewall
firewall{firewall{'http''http'::
dport =>dport => '80''80',,
proto =>proto => 'tcp''tcp',,
action =>action => 'accept''accept',,
}}
Roles & ProfilesRoles & Profiles
classclass roles::webserver {roles::webserver {
include profiles::apacheinclude profiles::apache
include profiles::mysqlinclude profiles::mysql
}}
Open-Closed PrincipleOpen-Closed Principle
““You should be able to extend a class’sYou should be able to extend a class’s
behavior, without modifying it”behavior, without modifying it”
classclass profiles::website::apache (profiles::website::apache (
BooleanBoolean $default_mods$default_mods == truetrue,,
BooleanBoolean $default_vhost$default_vhost == falsefalse,,
HashHash $modules$modules = {}= {},,
StringString $mpm_module$mpm_module == 'prefork''prefork',,
BooleanBoolean $purge_configs$purge_configs == falsefalse,,
BooleanBoolean $purge_vhost_dir$purge_vhost_dir == falsefalse,,
HashHash $vhosts$vhosts = {}= {},,
) {) {
classclass {{ '::apache''::apache'::
default_mods =>default_mods => $default_mods$default_mods,,
default_vhost =>default_vhost => $default_vhost$default_vhost,,
mpm_module =>mpm_module => $mpm_module$mpm_module,,
purge_configs =>purge_configs => $purge_configs$purge_configs,,
purge_vhost_dir =>purge_vhost_dir => $purge_vhost_dir$purge_vhost_dir,,
}}
create_resources(create_resources('apache::mod''apache::mod',, $modules$modules))
create_resources(create_resources('apache::vhost''apache::vhost',, $vhosts$vhosts))
}}
YAML programmingYAML programming
profiles::website::apache::vhosts:profiles::website::apache::vhosts:
'icinga.alerting.vagrant':'icinga.alerting.vagrant':
port:port: 8080
docroot:docroot: '/usr/share/icingaweb2/public''/usr/share/icingaweb2/public'
directories:directories:
-- 'icingaweb':'icingaweb':
path:path: '/usr/share/icingaweb2/public''/usr/share/icingaweb2/public'
directoryindex:directoryindex: 'index.php''index.php'
options:options:
-- 'SymLinksIfOwnerMatch''SymLinksIfOwnerMatch'
setenv:setenv:
-- 'ICINGAWEB_CONFIGDIR "/etc/icingaweb2"''ICINGAWEB_CONFIGDIR "/etc/icingaweb2"'
rewrites:rewrites:
-- 'icingaweb':'icingaweb':
comment:comment: 'Icingaweb2''Icingaweb2'
rewrite_base:rewrite_base: '/icingaweb2''/icingaweb2'
rewrite_cond:rewrite_cond:
-- '%%{}{REQUEST_FILENAME} -s [OR]''%%{}{REQUEST_FILENAME} -s [OR]'
-- '%%{}{REQUEST_FILENAME} -l [OR]''%%{}{REQUEST_FILENAME} -l [OR]'
-- '%%{}{REQUEST_FILENAME} -d''%%{}{REQUEST_FILENAME} -d'
rewrite_rule:rewrite_rule:
-- '^.*$ - [NC,L]''^.*$ - [NC,L]'
-- 'php':'php':
comment:comment: 'PHP''PHP'
rewrite_rule:rewrite_rule:
-- '^.*$ index.php [NC,L]''^.*$ index.php [NC,L]'
setenvif:setenvif:
-- 'Authorization "(.*)" HTTP_AUTHORIZATION=$1''Authorization "(.*)" HTTP_AUTHORIZATION=$1'
aliases:aliases:
-- '/icingaweb2':'/icingaweb2':
alias:alias: '/icingaweb2''/icingaweb2'
path:path: '/usr/share/icingaweb2/public''/usr/share/icingaweb2/public'
redirectmatch_regexp:redirectmatch_regexp: '^/$''^/$'
redirectmatch_dest:redirectmatch_dest: '/icingaweb2''/icingaweb2'
custom_fragment:custom_fragment: ||
<LocationMatch "^/icingaweb2/(.*.php)$"><LocationMatch "^/icingaweb2/(.*.php)$">
ProxyPassMatch "fcgi://127.0.0.1:9000/usr/share/icingaweb2/public/$1"ProxyPassMatch "fcgi://127.0.0.1:9000/usr/share/icingaweb2/public/$1"
</LocationMatch></LocationMatch>
Circuit BreakerCircuit Breaker
# cat default.pp# cat default.pp
lookup(lookup('circuit_breaker_key''circuit_breaker_key', Boolean, Boolean))
Exec { path => [Exec { path => [ "/bin/""/bin/",, "/sbin/""/sbin/" ,, "/usr/bin/""/usr/bin/",,
"/usr/sbin/""/usr/sbin/" ] }] }
Package {Package {
allow_virtual =>allow_virtual => truetrue,,
}}
Circuit BreakerCircuit Breaker
[root@php72 ~]# puppet agent -t[root@php72 ~]# puppet agent -t
......
Error: Could not retrieve catalog from remote server:Error: Could not retrieve catalog from remote server:
Error 500 on SERVER: Server Error: Function lookup()Error 500 on SERVER: Server Error: Function lookup()
did not find a value for the name 'circuit_breaker'did not find a value for the name 'circuit_breaker'
on node php72.website.vagranton node php72.website.vagrant
Warning: Not using cache on failed catalogWarning: Not using cache on failed catalog
Error: Could not retrieve catalog; skipping runError: Could not retrieve catalog; skipping run
Liskov Substitution PrincipleLiskov Substitution Principle
““Derived classes must be substitutableDerived classes must be substitutable
for their base classes”for their base classes”
Using TypesUsing Types
classclass nginx (nginx (
$temp_path = ‘/tmp’$temp_path = ‘/tmp’,,
$confd_only$confd_only == falsefalse,,
$daemon$daemon == undefundef,,
$severity$severity == 'error''error',,
Using TypesUsing Types
classclass nginx (nginx (
Stdlib::AbsolutepathStdlib::Absolutepath $temp_path = ‘/tmp’$temp_path = ‘/tmp’,,
BooleanBoolean $confd_only$confd_only == falsefalse,,
Optional[Enum[Optional[Enum['on''on',, 'off''off']]]] $daemon$daemon == undefundef,,
Nginx::SeverityNginx::Severity $severity$severity == 'error''error',,
Using TypesUsing Types
# cat modules/nginx/types/serverity.pp# cat modules/nginx/types/serverity.pp
type Nginx::Severity = Enum[type Nginx::Severity = Enum[
'debug''debug',,
'info''info',,
'notice''notice',,
'warn''warn',,
'error''error',,
'crit''crit',,
'alert''alert',,
'emerg' # lint:ignore:trailing_comma'emerg' # lint:ignore:trailing_comma
]]
Interface Segregation PrincipleInterface Segregation Principle
““Make fine-grained interfaces that areMake fine-grained interfaces that are
client specific”client specific”
DRY – Dont Repeat YourselfDRY – Dont Repeat Yourself
““...”...”
DRYDRY
modules grep -r "apache::vhost" . | wc -l❯
75
RelationshipsRelationships
Profiles & Defined TypesProfiles & Defined Types
create_resources(create_resources( 'apache::vhost''apache::vhost',, $vhosts$vhosts,, $vhost_defaults$vhost_defaults ))
VSVS
create_resources(create_resources( '::profile_symfony::vhost''::profile_symfony::vhost',, $instances$instances ))
create_resources(create_resources( '::profile_drupal::vhost''::profile_drupal::vhost',, $instances$instances ))
Dependency Inversion PrincipleDependency Inversion Principle
““Depend on abstractions, not onDepend on abstractions, not on
concretions”concretions”
Roles & ProfilesRoles & Profiles
classclass roles::webserver {roles::webserver {
include profiles::apacheinclude profiles::apache
include profiles::mysqlinclude profiles::mysql
include profiles::firewallinclude profiles::firewall
}}
Roles & ProfilesRoles & Profiles
classclass role::webserver {role::webserver {
include profiles::apacheinclude profiles::apache
include profiles::phpinclude profiles::php
include profiles::mysqlinclude profiles::mysql
include profiles::firewallinclude profiles::firewall
}}
Defined TypesDefined Types
definedefine profile_static_app::vhost(profile_static_app::vhost(
StringString $public_name$public_name,,
StringString $internal_name$internal_name,,
StringString $package_name$package_name,,
StringString $docroot$docroot == "/var/vhosts/"/var/vhosts/${name}${name}"",,
BooleanBoolean $force_ssl$force_ssl == truetrue,,
BooleanBoolean $letsencrypt$letsencrypt == truetrue,,
BooleanBoolean $package_ensure$package_ensure == 'installed''installed',,
Enum[Enum['apache''apache',,'haproxy''haproxy',, 'none''none']] $rproxy_type$rproxy_type == 'apache''apache',,
StringString $rproxy_basicauth$rproxy_basicauth == 'ldap''ldap',,
StringString $custom_fragment$custom_fragment == '''',,
Array[String]Array[String] $internal_aliases$internal_aliases = []= [],,
Array[String]Array[String] $public_aliases$public_aliases = []= [],,
) {) {
::profile_static_app::instance {::profile_static_app::instance {$public_name$public_name::
package_name =>package_name => $package_name$package_name,,
ensure =>ensure => $package_ensure$package_ensure,,
}}
::profile_apache::vhost{::profile_apache::vhost{ $public_name$public_name::
docroot =>docroot => $docroot$docroot,,
internal_name =>internal_name => $internal_name$internal_name,,
internal_aliases =>internal_aliases => $internal_aliases$internal_aliases,,
public_name =>public_name => $public_name$public_name,,
public_aliases =>public_aliases => $public_aliases$public_aliases,,
force_ssl =>force_ssl => $force_ssl$force_ssl,,
letsencrypt =>letsencrypt => $letsencrypt$letsencrypt,,
rproxy_type =>rproxy_type => $rproxy_type$rproxy_type,,
rproxy_basicauth =>rproxy_basicauth => $rproxy_basicauth$rproxy_basicauth,,
custom_fragment =>custom_fragment => $custom_fragment$custom_fragment,,
}}
}}
php::fpm::pool {php::fpm::pool { $name$name::
access_log =>access_log => $acces_log$acces_log,,
listen =>listen => $fpm_listen$fpm_listen,,
pm =>pm => $process_manager$process_manager,,
pm_status_path =>pm_status_path => "/"/${name}${name}_status"_status",,
}}
profile_base::logrotate::file {profile_base::logrotate::file { ""${name}${name}-pool"-pool"::
location => [location => [$acces_log$acces_log]],,
}}
ifif $create_cachetool_config$create_cachetool_config {{
::profile_php::cachetool::config {::profile_php::cachetool::config { $name$name::
fpm_listen =>fpm_listen => $fpm_listen$fpm_listen,,
location =>location => $cachetool_config_dir$cachetool_config_dir,,
}}
}}
ifif $enable_alerting$enable_alerting {{
notify {notify { 'no alerting to see here''no alerting to see here': }: }
}}
ifif $enable_ship_logs$enable_ship_logs {{
::profile_base::rsyslog::file {::profile_base::rsyslog::file { ""${name}${name}-pool"-pool"::
location =>location => $acces_log$acces_log,,
}}
}}
ifif $enable_ship_metrics$enable_ship_metrics {{
notify {notify { 'no metrics to see here''no metrics to see here': }: }
}}
ConclusionsConclusions
VV Single Responsibility PrincipleSingle Responsibility Principle
½½ Open-Closed PrincipleOpen-Closed Principle
½½ Liskov Substitution PrincipleLiskov Substitution Principle
½½ Interface Segregation PrincipleInterface Segregation Principle
¾¾ Dependency Inversion PrincipleDependency Inversion Principle
More ReadingMore Reading
ContactContact
Bram VogelaarBram Vogelaar
+31 6 46 62 60 78+31 6 46 62 60 78
bram.vogelaar@inuits.eubram.vogelaar@inuits.eu
@attachmentgenie@attachmentgenie
Inuits BEInuits BE
Essensteenweg 31Essensteenweg 31
2930 Brasschaat2930 Brasschaat
BelgiumBelgium
Inuits NLInuits NL
Maashaven Zuidzijde 2Maashaven Zuidzijde 2
3081 AE Rotterdam3081 AE Rotterdam
NetherlandsNetherlands

More Related Content

What's hot (20)

PPT
JavaScript Basics with baby steps
Muhammad khurram khan
 
PPTX
PHP, The X DevAPI, and the MySQL Document Store Presented January 23rd, 20...
Dave Stokes
 
PDF
The Naked Bundle - Tryout
Matthias Noback
 
PDF
EWD 3 Training Course Part 20: The DocumentNode Object
Rob Tweed
 
PDF
Overview Of Lift Framework
Xebia IT Architects
 
PDF
Overview of The Scala Based Lift Web Framework
IndicThreads
 
PDF
Auto-loading of Drupal CCK Nodes
nihiliad
 
PDF
Introduction to Node.js Platform
Naresh Chintalcheru
 
PDF
JavaScript 101
ygv2000
 
PDF
자바 웹 개발 시작하기 (1주차 : 웹 어플리케이션 체험 실습)
DK Lee
 
PPSX
RequireJS
Tim Doherty
 
PDF
From framework coupled code to #microservices through #DDD /by @codelytv
CodelyTV
 
PPTX
Kubernetes #4 volume &amp; stateful set
Terry Cho
 
PDF
Serverless Java on Kubernetes
Krzysztof Sobkowiak
 
PDF
NoSQL and JavaScript: a love story
Alexandre Morgaut
 
PDF
Metarhia: Node.js Macht Frei
Timur Shemsedinov
 
PPT
Managing JavaScript Dependencies With RequireJS
Den Odell
 
PPTX
OCCI Specification Walkthrough
befreax
 
JavaScript Basics with baby steps
Muhammad khurram khan
 
PHP, The X DevAPI, and the MySQL Document Store Presented January 23rd, 20...
Dave Stokes
 
The Naked Bundle - Tryout
Matthias Noback
 
EWD 3 Training Course Part 20: The DocumentNode Object
Rob Tweed
 
Overview Of Lift Framework
Xebia IT Architects
 
Overview of The Scala Based Lift Web Framework
IndicThreads
 
Auto-loading of Drupal CCK Nodes
nihiliad
 
Introduction to Node.js Platform
Naresh Chintalcheru
 
JavaScript 101
ygv2000
 
자바 웹 개발 시작하기 (1주차 : 웹 어플리케이션 체험 실습)
DK Lee
 
RequireJS
Tim Doherty
 
From framework coupled code to #microservices through #DDD /by @codelytv
CodelyTV
 
Kubernetes #4 volume &amp; stateful set
Terry Cho
 
Serverless Java on Kubernetes
Krzysztof Sobkowiak
 
NoSQL and JavaScript: a love story
Alexandre Morgaut
 
Metarhia: Node.js Macht Frei
Timur Shemsedinov
 
Managing JavaScript Dependencies With RequireJS
Den Odell
 
OCCI Specification Walkthrough
befreax
 

Similar to Solid and Infrastructure as Code (20)

ODP
feature toggles for ops
Bram Vogelaar
 
PDF
Web applications with Catalyst
svilen.ivanov
 
PPTX
Laravel development (Laravel History, Environment Setup & Laravel Installatio...
Dilouar Hossain
 
PDF
Convert Your Dev Environment to a Docker Stack - PHP Tek 2025.pdf
Dana Luther
 
PDF
Python RESTful webservices with Python: Flask and Django solutions
Solution4Future
 
PDF
AEM Sightly Deep Dive
Gabriel Walt
 
KEY
[Coscup 2012] JavascriptMVC
Alive Kuo
 
PDF
Burn down the silos! Helping dev and ops gel on high availability websites
Lindsay Holmwood
 
PDF
PuppetConf 2016: The Long, Twisty Road to Automation: Implementing Puppet at ...
Puppet
 
PPTX
Creating Reusable Puppet Profiles
Bram Vogelaar
 
PDF
Understanding OpenStack Deployments - PuppetConf 2014
Puppet
 
PDF
Laravel presentation
Toufiq Mahmud
 
ODP
Knolx session
Knoldus Inc.
 
PDF
SproutCore and the Future of Web Apps
Mike Subelsky
 
KEY
modern module development - Ken Barber 2012 Edinburgh Puppet Camp
Puppet
 
KEY
Yii Introduction
Jason Ragsdale
 
PPTX
Rails Engine | Modular application
mirrec
 
PDF
Catalyst MVC
Sheeju Alex
 
PDF
Intro to Laravel 4
Singapore PHP User Group
 
PDF
Nuxeo JavaOne 2007
Stefane Fermigier
 
feature toggles for ops
Bram Vogelaar
 
Web applications with Catalyst
svilen.ivanov
 
Laravel development (Laravel History, Environment Setup & Laravel Installatio...
Dilouar Hossain
 
Convert Your Dev Environment to a Docker Stack - PHP Tek 2025.pdf
Dana Luther
 
Python RESTful webservices with Python: Flask and Django solutions
Solution4Future
 
AEM Sightly Deep Dive
Gabriel Walt
 
[Coscup 2012] JavascriptMVC
Alive Kuo
 
Burn down the silos! Helping dev and ops gel on high availability websites
Lindsay Holmwood
 
PuppetConf 2016: The Long, Twisty Road to Automation: Implementing Puppet at ...
Puppet
 
Creating Reusable Puppet Profiles
Bram Vogelaar
 
Understanding OpenStack Deployments - PuppetConf 2014
Puppet
 
Laravel presentation
Toufiq Mahmud
 
Knolx session
Knoldus Inc.
 
SproutCore and the Future of Web Apps
Mike Subelsky
 
modern module development - Ken Barber 2012 Edinburgh Puppet Camp
Puppet
 
Yii Introduction
Jason Ragsdale
 
Rails Engine | Modular application
mirrec
 
Catalyst MVC
Sheeju Alex
 
Intro to Laravel 4
Singapore PHP User Group
 
Nuxeo JavaOne 2007
Stefane Fermigier
 
Ad

More from Bram Vogelaar (20)

PPTX
Terraforming your Platform Engineering organisation.pptx
Bram Vogelaar
 
PDF
Secure second days operations with Boundary and Vault.pdf
Bram Vogelaar
 
PDF
Cost reconciliation in a post CMDB world
Bram Vogelaar
 
PDF
Self scaling Multi cloud nomad workloads
Bram Vogelaar
 
PDF
Scraping metrics for fun and profit
Bram Vogelaar
 
PDF
10 things i learned building nomad-packs
Bram Vogelaar
 
PDF
10 things I learned building Nomad packs
Bram Vogelaar
 
PDF
Easy Cloud Native Transformation with Nomad
Bram Vogelaar
 
PDF
Uncomplicated Nomad
Bram Vogelaar
 
PDF
Observability; a gentle introduction
Bram Vogelaar
 
PDF
Running Trusted Payload with Nomad and Waypoint
Bram Vogelaar
 
PDF
Easy Cloud Native Transformation using HashiCorp Nomad
Bram Vogelaar
 
PDF
Securing Prometheus exporters using HashiCorp Vault
Bram Vogelaar
 
PDF
CICD using jenkins and Nomad
Bram Vogelaar
 
PDF
Bootstrapping multidc observability stack
Bram Vogelaar
 
PDF
Running trusted payloads with Nomad and Waypoint
Bram Vogelaar
 
PDF
Gamification of Chaos Testing
Bram Vogelaar
 
PDF
Puppet and the HashiStack
Bram Vogelaar
 
PDF
Bootstrapping multidc observability stack
Bram Vogelaar
 
PDF
Gamification of Chaos Testing
Bram Vogelaar
 
Terraforming your Platform Engineering organisation.pptx
Bram Vogelaar
 
Secure second days operations with Boundary and Vault.pdf
Bram Vogelaar
 
Cost reconciliation in a post CMDB world
Bram Vogelaar
 
Self scaling Multi cloud nomad workloads
Bram Vogelaar
 
Scraping metrics for fun and profit
Bram Vogelaar
 
10 things i learned building nomad-packs
Bram Vogelaar
 
10 things I learned building Nomad packs
Bram Vogelaar
 
Easy Cloud Native Transformation with Nomad
Bram Vogelaar
 
Uncomplicated Nomad
Bram Vogelaar
 
Observability; a gentle introduction
Bram Vogelaar
 
Running Trusted Payload with Nomad and Waypoint
Bram Vogelaar
 
Easy Cloud Native Transformation using HashiCorp Nomad
Bram Vogelaar
 
Securing Prometheus exporters using HashiCorp Vault
Bram Vogelaar
 
CICD using jenkins and Nomad
Bram Vogelaar
 
Bootstrapping multidc observability stack
Bram Vogelaar
 
Running trusted payloads with Nomad and Waypoint
Bram Vogelaar
 
Gamification of Chaos Testing
Bram Vogelaar
 
Puppet and the HashiStack
Bram Vogelaar
 
Bootstrapping multidc observability stack
Bram Vogelaar
 
Gamification of Chaos Testing
Bram Vogelaar
 
Ad

Recently uploaded (20)

PPTX
Agentic AI in Healthcare Driving the Next Wave of Digital Transformation
danielle hunter
 
PDF
Make GenAI investments go further with the Dell AI Factory
Principled Technologies
 
PDF
Economic Impact of Data Centres to the Malaysian Economy
flintglobalapac
 
PPTX
AVL ( audio, visuals or led ), technology.
Rajeshwri Panchal
 
PPTX
Farrell_Programming Logic and Design slides_10e_ch02_PowerPoint.pptx
bashnahara11
 
PDF
Brief History of Internet - Early Days of Internet
sutharharshit158
 
PPTX
OA presentation.pptx OA presentation.pptx
pateldhruv002338
 
PPTX
AI in Daily Life: How Artificial Intelligence Helps Us Every Day
vanshrpatil7
 
PPTX
Dev Dives: Automate, test, and deploy in one place—with Unified Developer Exp...
AndreeaTom
 
PPTX
Agile Chennai 18-19 July 2025 | Emerging patterns in Agentic AI by Bharani Su...
AgileNetwork
 
PPTX
The Future of AI & Machine Learning.pptx
pritsen4700
 
PPTX
Introduction to Flutter by Ayush Desai.pptx
ayushdesai204
 
PDF
Per Axbom: The spectacular lies of maps
Nexer Digital
 
PPTX
Applied-Statistics-Mastering-Data-Driven-Decisions.pptx
parmaryashparmaryash
 
PDF
Structs to JSON: How Go Powers REST APIs
Emily Achieng
 
PDF
GDG Cloud Munich - Intro - Luiz Carneiro - #BuildWithAI - July - Abdel.pdf
Luiz Carneiro
 
PDF
Data_Analytics_vs_Data_Science_vs_BI_by_CA_Suvidha_Chaplot.pdf
CA Suvidha Chaplot
 
PDF
AI Unleashed - Shaping the Future -Starting Today - AIOUG Yatra 2025 - For Co...
Sandesh Rao
 
PDF
CIFDAQ's Market Wrap : Bears Back in Control?
CIFDAQ
 
PDF
The Future of Artificial Intelligence (AI)
Mukul
 
Agentic AI in Healthcare Driving the Next Wave of Digital Transformation
danielle hunter
 
Make GenAI investments go further with the Dell AI Factory
Principled Technologies
 
Economic Impact of Data Centres to the Malaysian Economy
flintglobalapac
 
AVL ( audio, visuals or led ), technology.
Rajeshwri Panchal
 
Farrell_Programming Logic and Design slides_10e_ch02_PowerPoint.pptx
bashnahara11
 
Brief History of Internet - Early Days of Internet
sutharharshit158
 
OA presentation.pptx OA presentation.pptx
pateldhruv002338
 
AI in Daily Life: How Artificial Intelligence Helps Us Every Day
vanshrpatil7
 
Dev Dives: Automate, test, and deploy in one place—with Unified Developer Exp...
AndreeaTom
 
Agile Chennai 18-19 July 2025 | Emerging patterns in Agentic AI by Bharani Su...
AgileNetwork
 
The Future of AI & Machine Learning.pptx
pritsen4700
 
Introduction to Flutter by Ayush Desai.pptx
ayushdesai204
 
Per Axbom: The spectacular lies of maps
Nexer Digital
 
Applied-Statistics-Mastering-Data-Driven-Decisions.pptx
parmaryashparmaryash
 
Structs to JSON: How Go Powers REST APIs
Emily Achieng
 
GDG Cloud Munich - Intro - Luiz Carneiro - #BuildWithAI - July - Abdel.pdf
Luiz Carneiro
 
Data_Analytics_vs_Data_Science_vs_BI_by_CA_Suvidha_Chaplot.pdf
CA Suvidha Chaplot
 
AI Unleashed - Shaping the Future -Starting Today - AIOUG Yatra 2025 - For Co...
Sandesh Rao
 
CIFDAQ's Market Wrap : Bears Back in Control?
CIFDAQ
 
The Future of Artificial Intelligence (AI)
Mukul
 

Solid and Infrastructure as Code

  • 2. ~$ whoami~$ whoami ● I used to be a Molecular Biologist,I used to be a Molecular Biologist, ● Then became a Dev,Then became a Dev, ● Now an Ops.Now an Ops. ● Open Source Consultant @Open Source Consultant @inuits.euinuits.eu
  • 3. classclass webserver {webserver { include apacheinclude apache apache::vhost {apache::vhost { 'vhost.example.com''vhost.example.com':: port =>port => '80''80',, docroot =>docroot => '/var/www/vhost''/var/www/vhost',, }} include ::phpinclude ::php classclass {{ '::mysql::server''::mysql::server':: root_password =>root_password => 'secret''secret',, }} classclass {{ '::mysql::server::account_security''::mysql::server::account_security': }: } classclass {{ '::mysql::client''::mysql::client': }: } mysql::db {mysql::db { 'mydb''mydb':: user =>user => 'myuser''myuser',, password =>password => 'mypass''mypass',, host =>host => 'localhost''localhost',, grant => [grant => ['SELECT''SELECT',, 'UPDATE''UPDATE']],, }} include ::firewallinclude ::firewall firewall{firewall{'http''http':: dport =>dport => '80''80',, proto =>proto => 'tcp''tcp',, action =>action => 'accept''accept',, }}
  • 4. Roles & ProfilesRoles & Profiles ● Component modules — Modules that manageComponent modules — Modules that manage one particular technology, for exampleone particular technology, for example puppetlabs/apache.puppetlabs/apache. ● Profiles — Wrapper classes that use (multiple)Profiles — Wrapper classes that use (multiple) component modules to configure a layeredcomponent modules to configure a layered technology stack.technology stack. ● Roles — Wrapper classes that use multipleRoles — Wrapper classes that use multiple profiles to build a complete systemprofiles to build a complete system configuration.configuration. https://www.craigdunn.org/2012/05/239/https://www.craigdunn.org/2012/05/239/
  • 5. Roles & Profiles - TLDRRoles & Profiles - TLDR ● Component modules — Resources definitions.Component modules — Resources definitions. ● Profiles — Your company specificProfiles — Your company specific implementation.implementation. ● Roles — Bussiness role.Roles — Bussiness role.
  • 6. Roles & ProfilesRoles & Profiles classclass roles::webserver {roles::webserver { include profiles::apacheinclude profiles::apache include profiles::mysqlinclude profiles::mysql }}
  • 7. Roles & ProfilesRoles & Profiles classclass roles::webserver {roles::webserver { include ::profiles::apacheinclude ::profiles::apache }} classclass roles::database {roles::database { include ::profiles::mysqlinclude ::profiles::mysql }}
  • 8. Roles & ProfilesRoles & Profiles ● First approach: Granular rolesFirst approach: Granular roles ● Second approach: Conditional logicSecond approach: Conditional logic ● Third approach: Nested rolesThird approach: Nested roles ● Fourth approach: Multiple roles per nodeFourth approach: Multiple roles per node ● Fifth approach: Super profilesFifth approach: Super profiles ● Sixth approach: Building roles in the nodeSixth approach: Building roles in the node classifierclassifier https://puppet.com/docs/pe/2017.3/managinghttps://puppet.com/docs/pe/2017.3/managing _nodes/designing_convenient_roles.html_nodes/designing_convenient_roles.html
  • 9. ““loose coupling, high cohesion”loose coupling, high cohesion” Unknown?Unknown?
  • 10. Roles & ProfilesRoles & Profiles classclass roles::allinone {roles::allinone { include ::profiles::apacheinclude ::profiles::apache include ::profiles::mysqlinclude ::profiles::mysql }}
  • 12. Model View ControllerModel View Controller ● The model is the central component of theThe model is the central component of the pattern. It expresses the application's behaviorpattern. It expresses the application's behavior in terms of the problem domain, independent ofin terms of the problem domain, independent of the user interface.[6] It directly manages thethe user interface.[6] It directly manages the data, logic and rules of the application.data, logic and rules of the application. ● The controller, accepts input and converts it toThe controller, accepts input and converts it to commands for the model or view.commands for the model or view. ● A view can be any output representation ofA view can be any output representation of information, such as a chart or a diagram.information, such as a chart or a diagram. Multiple views of the same information areMultiple views of the same information are possible, such as a bar chart for managementpossible, such as a bar chart for management and a tabular view for accountants.and a tabular view for accountants.
  • 13. MVC -TLDRMVC -TLDR ● Model: heavy lifting partModel: heavy lifting part ● Controller: Logic flow coordinatorController: Logic flow coordinator ● View: Consumable render of dataView: Consumable render of data
  • 14. R&P vs MVCR&P vs MVC ● Component modules — Resources definitions.Component modules — Resources definitions. ● Profiles — Your company specificProfiles — Your company specific implementation.implementation. ● Roles — Bussiness role.Roles — Bussiness role. ● Model: heavy lifting partModel: heavy lifting part ● Controller: Flow coordinatorController: Flow coordinator ● View: Consumable render of dataView: Consumable render of data
  • 15. OO - Objective OrientedOO - Objective Oriented ● Objects and classesObjects and classes ● Dynamic dispatch/message passingDynamic dispatch/message passing ● EncapsulationEncapsulation ● Composition, inheritance, and delegationComposition, inheritance, and delegation ● PolymorphismPolymorphism ● Open recursionOpen recursion
  • 16. SOLID PrincipleSOLID Principle mnemonic acronym for five design principlesmnemonic acronym for five design principles intended to make software designs moreintended to make software designs more understandable, flexible and maintainableunderstandable, flexible and maintainable Robert C. Martin, 2002Robert C. Martin, 2002
  • 17. SOLID PrincipleSOLID Principle SS — Single Responsibility Principle— Single Responsibility Principle OO— Open-Closed Principle— Open-Closed Principle LL — Liskov Substitution Principle— Liskov Substitution Principle II — Interface Segregation Principle— Interface Segregation Principle DD — Dependency Inversion Principle— Dependency Inversion Principle
  • 18. Single Responsibility PrincipleSingle Responsibility Principle ““A class should have one, and only one,A class should have one, and only one, reason to change”reason to change”
  • 19. classclass webserver {webserver { include apacheinclude apache apache::vhost {apache::vhost { 'vhost.example.com''vhost.example.com':: port =>port => '80''80',, docroot =>docroot => '/var/www/vhost''/var/www/vhost',, }} include ::phpinclude ::php classclass {{ '::mysql::server''::mysql::server':: root_password =>root_password => 'secret''secret',, }} classclass {{ '::mysql::server::account_security''::mysql::server::account_security': }: } classclass {{ '::mysql::client''::mysql::client': }: } mysql::db {mysql::db { 'mydb''mydb':: user =>user => 'myuser''myuser',, password =>password => 'mypass''mypass',, host =>host => 'localhost''localhost',, grant => [grant => ['SELECT''SELECT',, 'UPDATE''UPDATE']],, }} include ::firewallinclude ::firewall firewall{firewall{'http''http':: dport =>dport => '80''80',, proto =>proto => 'tcp''tcp',, action =>action => 'accept''accept',, }}
  • 20. Roles & ProfilesRoles & Profiles classclass roles::webserver {roles::webserver { include profiles::apacheinclude profiles::apache include profiles::mysqlinclude profiles::mysql }}
  • 21. Open-Closed PrincipleOpen-Closed Principle ““You should be able to extend a class’sYou should be able to extend a class’s behavior, without modifying it”behavior, without modifying it”
  • 22. classclass profiles::website::apache (profiles::website::apache ( BooleanBoolean $default_mods$default_mods == truetrue,, BooleanBoolean $default_vhost$default_vhost == falsefalse,, HashHash $modules$modules = {}= {},, StringString $mpm_module$mpm_module == 'prefork''prefork',, BooleanBoolean $purge_configs$purge_configs == falsefalse,, BooleanBoolean $purge_vhost_dir$purge_vhost_dir == falsefalse,, HashHash $vhosts$vhosts = {}= {},, ) {) { classclass {{ '::apache''::apache':: default_mods =>default_mods => $default_mods$default_mods,, default_vhost =>default_vhost => $default_vhost$default_vhost,, mpm_module =>mpm_module => $mpm_module$mpm_module,, purge_configs =>purge_configs => $purge_configs$purge_configs,, purge_vhost_dir =>purge_vhost_dir => $purge_vhost_dir$purge_vhost_dir,, }} create_resources(create_resources('apache::mod''apache::mod',, $modules$modules)) create_resources(create_resources('apache::vhost''apache::vhost',, $vhosts$vhosts)) }}
  • 23. YAML programmingYAML programming profiles::website::apache::vhosts:profiles::website::apache::vhosts: 'icinga.alerting.vagrant':'icinga.alerting.vagrant': port:port: 8080 docroot:docroot: '/usr/share/icingaweb2/public''/usr/share/icingaweb2/public' directories:directories: -- 'icingaweb':'icingaweb': path:path: '/usr/share/icingaweb2/public''/usr/share/icingaweb2/public' directoryindex:directoryindex: 'index.php''index.php' options:options: -- 'SymLinksIfOwnerMatch''SymLinksIfOwnerMatch' setenv:setenv: -- 'ICINGAWEB_CONFIGDIR "/etc/icingaweb2"''ICINGAWEB_CONFIGDIR "/etc/icingaweb2"' rewrites:rewrites: -- 'icingaweb':'icingaweb': comment:comment: 'Icingaweb2''Icingaweb2' rewrite_base:rewrite_base: '/icingaweb2''/icingaweb2' rewrite_cond:rewrite_cond: -- '%%{}{REQUEST_FILENAME} -s [OR]''%%{}{REQUEST_FILENAME} -s [OR]' -- '%%{}{REQUEST_FILENAME} -l [OR]''%%{}{REQUEST_FILENAME} -l [OR]' -- '%%{}{REQUEST_FILENAME} -d''%%{}{REQUEST_FILENAME} -d' rewrite_rule:rewrite_rule: -- '^.*$ - [NC,L]''^.*$ - [NC,L]' -- 'php':'php': comment:comment: 'PHP''PHP' rewrite_rule:rewrite_rule: -- '^.*$ index.php [NC,L]''^.*$ index.php [NC,L]' setenvif:setenvif: -- 'Authorization "(.*)" HTTP_AUTHORIZATION=$1''Authorization "(.*)" HTTP_AUTHORIZATION=$1' aliases:aliases: -- '/icingaweb2':'/icingaweb2': alias:alias: '/icingaweb2''/icingaweb2' path:path: '/usr/share/icingaweb2/public''/usr/share/icingaweb2/public' redirectmatch_regexp:redirectmatch_regexp: '^/$''^/$' redirectmatch_dest:redirectmatch_dest: '/icingaweb2''/icingaweb2' custom_fragment:custom_fragment: || <LocationMatch "^/icingaweb2/(.*.php)$"><LocationMatch "^/icingaweb2/(.*.php)$"> ProxyPassMatch "fcgi://127.0.0.1:9000/usr/share/icingaweb2/public/$1"ProxyPassMatch "fcgi://127.0.0.1:9000/usr/share/icingaweb2/public/$1" </LocationMatch></LocationMatch>
  • 24. Circuit BreakerCircuit Breaker # cat default.pp# cat default.pp lookup(lookup('circuit_breaker_key''circuit_breaker_key', Boolean, Boolean)) Exec { path => [Exec { path => [ "/bin/""/bin/",, "/sbin/""/sbin/" ,, "/usr/bin/""/usr/bin/",, "/usr/sbin/""/usr/sbin/" ] }] } Package {Package { allow_virtual =>allow_virtual => truetrue,, }}
  • 25. Circuit BreakerCircuit Breaker [root@php72 ~]# puppet agent -t[root@php72 ~]# puppet agent -t ...... Error: Could not retrieve catalog from remote server:Error: Could not retrieve catalog from remote server: Error 500 on SERVER: Server Error: Function lookup()Error 500 on SERVER: Server Error: Function lookup() did not find a value for the name 'circuit_breaker'did not find a value for the name 'circuit_breaker' on node php72.website.vagranton node php72.website.vagrant Warning: Not using cache on failed catalogWarning: Not using cache on failed catalog Error: Could not retrieve catalog; skipping runError: Could not retrieve catalog; skipping run
  • 26. Liskov Substitution PrincipleLiskov Substitution Principle ““Derived classes must be substitutableDerived classes must be substitutable for their base classes”for their base classes”
  • 27. Using TypesUsing Types classclass nginx (nginx ( $temp_path = ‘/tmp’$temp_path = ‘/tmp’,, $confd_only$confd_only == falsefalse,, $daemon$daemon == undefundef,, $severity$severity == 'error''error',,
  • 28. Using TypesUsing Types classclass nginx (nginx ( Stdlib::AbsolutepathStdlib::Absolutepath $temp_path = ‘/tmp’$temp_path = ‘/tmp’,, BooleanBoolean $confd_only$confd_only == falsefalse,, Optional[Enum[Optional[Enum['on''on',, 'off''off']]]] $daemon$daemon == undefundef,, Nginx::SeverityNginx::Severity $severity$severity == 'error''error',,
  • 29. Using TypesUsing Types # cat modules/nginx/types/serverity.pp# cat modules/nginx/types/serverity.pp type Nginx::Severity = Enum[type Nginx::Severity = Enum[ 'debug''debug',, 'info''info',, 'notice''notice',, 'warn''warn',, 'error''error',, 'crit''crit',, 'alert''alert',, 'emerg' # lint:ignore:trailing_comma'emerg' # lint:ignore:trailing_comma ]]
  • 30. Interface Segregation PrincipleInterface Segregation Principle ““Make fine-grained interfaces that areMake fine-grained interfaces that are client specific”client specific”
  • 31. DRY – Dont Repeat YourselfDRY – Dont Repeat Yourself ““...”...”
  • 32. DRYDRY modules grep -r "apache::vhost" . | wc -l❯ 75
  • 34. Profiles & Defined TypesProfiles & Defined Types create_resources(create_resources( 'apache::vhost''apache::vhost',, $vhosts$vhosts,, $vhost_defaults$vhost_defaults )) VSVS create_resources(create_resources( '::profile_symfony::vhost''::profile_symfony::vhost',, $instances$instances )) create_resources(create_resources( '::profile_drupal::vhost''::profile_drupal::vhost',, $instances$instances ))
  • 35. Dependency Inversion PrincipleDependency Inversion Principle ““Depend on abstractions, not onDepend on abstractions, not on concretions”concretions”
  • 36. Roles & ProfilesRoles & Profiles classclass roles::webserver {roles::webserver { include profiles::apacheinclude profiles::apache include profiles::mysqlinclude profiles::mysql include profiles::firewallinclude profiles::firewall }}
  • 37. Roles & ProfilesRoles & Profiles classclass role::webserver {role::webserver { include profiles::apacheinclude profiles::apache include profiles::phpinclude profiles::php include profiles::mysqlinclude profiles::mysql include profiles::firewallinclude profiles::firewall }}
  • 38. Defined TypesDefined Types definedefine profile_static_app::vhost(profile_static_app::vhost( StringString $public_name$public_name,, StringString $internal_name$internal_name,, StringString $package_name$package_name,, StringString $docroot$docroot == "/var/vhosts/"/var/vhosts/${name}${name}"",, BooleanBoolean $force_ssl$force_ssl == truetrue,, BooleanBoolean $letsencrypt$letsencrypt == truetrue,, BooleanBoolean $package_ensure$package_ensure == 'installed''installed',, Enum[Enum['apache''apache',,'haproxy''haproxy',, 'none''none']] $rproxy_type$rproxy_type == 'apache''apache',, StringString $rproxy_basicauth$rproxy_basicauth == 'ldap''ldap',, StringString $custom_fragment$custom_fragment == '''',, Array[String]Array[String] $internal_aliases$internal_aliases = []= [],, Array[String]Array[String] $public_aliases$public_aliases = []= [],, ) {) { ::profile_static_app::instance {::profile_static_app::instance {$public_name$public_name:: package_name =>package_name => $package_name$package_name,, ensure =>ensure => $package_ensure$package_ensure,, }} ::profile_apache::vhost{::profile_apache::vhost{ $public_name$public_name:: docroot =>docroot => $docroot$docroot,, internal_name =>internal_name => $internal_name$internal_name,, internal_aliases =>internal_aliases => $internal_aliases$internal_aliases,, public_name =>public_name => $public_name$public_name,, public_aliases =>public_aliases => $public_aliases$public_aliases,, force_ssl =>force_ssl => $force_ssl$force_ssl,, letsencrypt =>letsencrypt => $letsencrypt$letsencrypt,, rproxy_type =>rproxy_type => $rproxy_type$rproxy_type,, rproxy_basicauth =>rproxy_basicauth => $rproxy_basicauth$rproxy_basicauth,, custom_fragment =>custom_fragment => $custom_fragment$custom_fragment,, }} }}
  • 39. php::fpm::pool {php::fpm::pool { $name$name:: access_log =>access_log => $acces_log$acces_log,, listen =>listen => $fpm_listen$fpm_listen,, pm =>pm => $process_manager$process_manager,, pm_status_path =>pm_status_path => "/"/${name}${name}_status"_status",, }} profile_base::logrotate::file {profile_base::logrotate::file { ""${name}${name}-pool"-pool":: location => [location => [$acces_log$acces_log]],, }} ifif $create_cachetool_config$create_cachetool_config {{ ::profile_php::cachetool::config {::profile_php::cachetool::config { $name$name:: fpm_listen =>fpm_listen => $fpm_listen$fpm_listen,, location =>location => $cachetool_config_dir$cachetool_config_dir,, }} }} ifif $enable_alerting$enable_alerting {{ notify {notify { 'no alerting to see here''no alerting to see here': }: } }} ifif $enable_ship_logs$enable_ship_logs {{ ::profile_base::rsyslog::file {::profile_base::rsyslog::file { ""${name}${name}-pool"-pool":: location =>location => $acces_log$acces_log,, }} }} ifif $enable_ship_metrics$enable_ship_metrics {{ notify {notify { 'no metrics to see here''no metrics to see here': }: } }}
  • 40. ConclusionsConclusions VV Single Responsibility PrincipleSingle Responsibility Principle ½½ Open-Closed PrincipleOpen-Closed Principle ½½ Liskov Substitution PrincipleLiskov Substitution Principle ½½ Interface Segregation PrincipleInterface Segregation Principle ¾¾ Dependency Inversion PrincipleDependency Inversion Principle
  • 42. ContactContact Bram VogelaarBram Vogelaar +31 6 46 62 60 78+31 6 46 62 60 78 [email protected]@inuits.eu @attachmentgenie@attachmentgenie Inuits BEInuits BE Essensteenweg 31Essensteenweg 31 2930 Brasschaat2930 Brasschaat BelgiumBelgium Inuits NLInuits NL Maashaven Zuidzijde 2Maashaven Zuidzijde 2 3081 AE Rotterdam3081 AE Rotterdam NetherlandsNetherlands