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

PDF
Migrating data to drupal 8
PDF
Migrating to Drupal 8: How to Migrate Your Content and Minimize the Risks
ZIP
SHARE & the Semantic Web — This Time it's Personal
PDF
WCLA12 JavaScript
PDF
EWD 3 Training Course Part 38: Building a React.js application with QEWD, Part 2
PDF
EWD 3 Training Course Part 14: Using Ajax for QEWD Messages
PDF
EWD 3 Training Course Part 22: Traversing Documents using DocumentNode Objects
Migrating data to drupal 8
Migrating to Drupal 8: How to Migrate Your Content and Minimize the Risks
SHARE & the Semantic Web — This Time it's Personal
WCLA12 JavaScript
EWD 3 Training Course Part 38: Building a React.js application with QEWD, Part 2
EWD 3 Training Course Part 14: Using Ajax for QEWD Messages
EWD 3 Training Course Part 22: Traversing Documents using DocumentNode Objects

What's hot (20)

PPT
JavaScript Basics with baby steps
PPTX
PHP, The X DevAPI, and the MySQL Document Store Presented January 23rd, 20...
PDF
The Naked Bundle - Tryout
PDF
EWD 3 Training Course Part 20: The DocumentNode Object
PDF
Overview Of Lift Framework
PDF
Overview of The Scala Based Lift Web Framework
PDF
Auto-loading of Drupal CCK Nodes
PDF
Introduction to Node.js Platform
PDF
JavaScript 101
PDF
자바 웹 개발 시작하기 (1주차 : 웹 어플리케이션 체험 실습)
PPSX
RequireJS
PDF
From framework coupled code to #microservices through #DDD /by @codelytv
PPTX
Kubernetes #4 volume &amp; stateful set
PDF
Serverless Java on Kubernetes
PDF
NoSQL and JavaScript: a love story
PDF
Metarhia: Node.js Macht Frei
PPT
Managing JavaScript Dependencies With RequireJS
PPTX
OCCI Specification Walkthrough
JavaScript Basics with baby steps
PHP, The X DevAPI, and the MySQL Document Store Presented January 23rd, 20...
The Naked Bundle - Tryout
EWD 3 Training Course Part 20: The DocumentNode Object
Overview Of Lift Framework
Overview of The Scala Based Lift Web Framework
Auto-loading of Drupal CCK Nodes
Introduction to Node.js Platform
JavaScript 101
자바 웹 개발 시작하기 (1주차 : 웹 어플리케이션 체험 실습)
RequireJS
From framework coupled code to #microservices through #DDD /by @codelytv
Kubernetes #4 volume &amp; stateful set
Serverless Java on Kubernetes
NoSQL and JavaScript: a love story
Metarhia: Node.js Macht Frei
Managing JavaScript Dependencies With RequireJS
OCCI Specification Walkthrough
Ad

Similar to Solid and Infrastructure as Code (20)

PDF
Developing SOLID Code
PPTX
Implementing The Open/Closed Principle
ODP
PDF
Some OOP paradigms & SOLID
PDF
Architecture logicielle #3 : object oriented design
ODP
Introduction to Domain-Driven Design
PDF
IRJET- Lightweight MVC Framework in PHP
PDF
Workshop: Refactoring Legacy PHP: The Complete Guide
PDF
Beyond MVC: from Model to Domain
PDF
S.O.L.I.D. Principles
PPTX
PDF
Fighting legacy with hexagonal architecture and frameworkless php
PDF
Be pragmatic, be SOLID (at Boiling Frogs, Wrocław)
PDF
Object Oriented Programming for WordPress Plugin Development
PPT
PHP - Procedural To Object-Oriented
PDF
OOP in PHP
PPTX
Programming in the large
PPT
Ood and solid principles
PDF
Object Oriented Design Principles
PDF
Be pragmatic, be SOLID
Developing SOLID Code
Implementing The Open/Closed Principle
Some OOP paradigms & SOLID
Architecture logicielle #3 : object oriented design
Introduction to Domain-Driven Design
IRJET- Lightweight MVC Framework in PHP
Workshop: Refactoring Legacy PHP: The Complete Guide
Beyond MVC: from Model to Domain
S.O.L.I.D. Principles
Fighting legacy with hexagonal architecture and frameworkless php
Be pragmatic, be SOLID (at Boiling Frogs, Wrocław)
Object Oriented Programming for WordPress Plugin Development
PHP - Procedural To Object-Oriented
OOP in PHP
Programming in the large
Ood and solid principles
Object Oriented Design Principles
Be pragmatic, be SOLID
Ad

More from Bram Vogelaar (20)

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

Recently uploaded (20)

PPTX
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
PDF
The Rise and Fall of 3GPP – Time for a Sabbatical?
PDF
Diabetes mellitus diagnosis method based random forest with bat algorithm
PDF
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
PDF
Machine learning based COVID-19 study performance prediction
PPTX
Big Data Technologies - Introduction.pptx
PDF
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
PDF
Approach and Philosophy of On baking technology
PPTX
20250228 LYD VKU AI Blended-Learning.pptx
PDF
How UI/UX Design Impacts User Retention in Mobile Apps.pdf
PDF
Mobile App Security Testing_ A Comprehensive Guide.pdf
PDF
Advanced methodologies resolving dimensionality complications for autism neur...
PDF
Shreyas Phanse Resume: Experienced Backend Engineer | Java • Spring Boot • Ka...
PDF
Review of recent advances in non-invasive hemoglobin estimation
PPT
“AI and Expert System Decision Support & Business Intelligence Systems”
DOCX
The AUB Centre for AI in Media Proposal.docx
PDF
Encapsulation theory and applications.pdf
PDF
Chapter 3 Spatial Domain Image Processing.pdf
PDF
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
PDF
Empathic Computing: Creating Shared Understanding
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
The Rise and Fall of 3GPP – Time for a Sabbatical?
Diabetes mellitus diagnosis method based random forest with bat algorithm
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
Machine learning based COVID-19 study performance prediction
Big Data Technologies - Introduction.pptx
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
Approach and Philosophy of On baking technology
20250228 LYD VKU AI Blended-Learning.pptx
How UI/UX Design Impacts User Retention in Mobile Apps.pdf
Mobile App Security Testing_ A Comprehensive Guide.pdf
Advanced methodologies resolving dimensionality complications for autism neur...
Shreyas Phanse Resume: Experienced Backend Engineer | Java • Spring Boot • Ka...
Review of recent advances in non-invasive hemoglobin estimation
“AI and Expert System Decision Support & Business Intelligence Systems”
The AUB Centre for AI in Media Proposal.docx
Encapsulation theory and applications.pdf
Chapter 3 Spatial Domain Image Processing.pdf
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
Empathic Computing: Creating Shared Understanding

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