SlideShare ist ein Scribd-Unternehmen logo
1 von 99
Downloaden Sie, um offline zu lesen
APACHE SLING & FRIENDS TECH MEETUP
BERLIN, 25-27 SEPTEMBER 2017
Taming AEM deployments
Jakub Wądołowski, Cognifide
The road to efficient AEM delivery
2https://flic.kr/p/z8g25R
▪ Starts on your computer
▪ Ends in production
▪ Includes everything in between
3
Development phase
Local environment
4https://flic.kr/p/b93YGx
▪ Everyone runs the same
▪ It contains the entire technology stack
▪ Start over any time you need it
Solution
5
What’s in the box?
6https://flic.kr/p/cMBbTu
▪ AEM Author & AEM Publish
▪ Preinstalled packages
▪ Dispatcher
▪ Solr Master & Slave
▪ knot.x
Vagrant in practice (1/3)
7
# Install prerequisites:
# * Vagrant
# * VirtualBox
# * ChefDK
$ git clone git@example.org:xyz/vagrant.git
$ cd project-vagrant
$ rake init
$ rake up
Vagrant in practice (2/3)
8
▪ http://localhost:4502 (AEM Author)
▪ http://localhost:4503 (AEM Publish)
▪ https://example.vagrant (Dispatcher)
▪ http://localhost:8983 (Solr)
▪ etc
Vagrant in practice (3/3)
9
$ rake provision:publish
...
Chef Client finished, 8/196 resources updated in 02
minutes 02 seconds
$ rake provision:httpd
...
Chef Client finished, 4/41 resources updated in 19
seconds
Vagrant talk
10
https://goo.gl/hu216e
11
Continuous integration
Continuous integration
12https://flic.kr/p/nCGank
▪ Code integration
▪ Tests
▪ Release
Git flow
13
Use case (1/4)
14
▪ 17 Chef cookbook repos
▪ 2 CI related repos
▪ 3 config repos
▪ 4 app repos
▪ 2 infrastructure repos
https://flic.kr/p/bF3Nwm
Use case (2/4)
15
▪ Each repository has its own lifecycle
▪ Simple Git flow
https://flic.kr/p/peZfvA
Use case (3/4)
16
$ tree -L 1
.
├── aem
├── domain
├── knotx-autocomplete
├── knotx-download
├── knotx-filters
├── knotx-index
├── knotx-search
├── pom.xml
└── solr
8 directories, 1 file
https://flic.kr/p/fnPQuz
Use case (3/4)
17
$ tree -L 1
.
├── aem
├── domain
├── knotx-autocomplete
├── knotx-download
├── knotx-filters
├── knotx-index
├── knotx-search
├── pom.xml
└── solr
8 directories, 1 file
https://flic.kr/p/fnPQuz
Use case (3/4)
18
$ tree -L 1
.
├── aem
├── domain
├── knotx-autocomplete
├── knotx-download
├── knotx-filters
├── knotx-index
├── knotx-search
├── pom.xml
└── solr
8 directories, 1 file
https://flic.kr/p/fnPQuz
Use case (3/4)
19
$ tree -L 1
.
├── aem
├── domain
├── knotx-autocomplete
├── knotx-download
├── knotx-filters
├── knotx-index
├── knotx-search
├── solr
└── pom.xml
8 directories, 1 file
https://flic.kr/p/fnPQuz
Use case (3/4)
20
$ tree -L 1
.
├── aem
├── domain
├── knotx-autocomplete
├── knotx-download
├── knotx-filters
├── knotx-index
├── knotx-search
├── solr
└── pom.xml
8 directories, 1 file
https://flic.kr/p/fnPQuz
Use case (4/4)
21
▪ Compatibility matrix is no longer needed
▪ End-to-end testing
▪ One release contains multiple artifacts
Pipelines
22https://flic.kr/p/qG26gA
▪ Variety of choices
▪ Jenkins
▪ GoCD
▪ Bamboo
▪ etc
▪ Pipeline as code (Jenkinsfile)
23
node('master') {
stage('Checkout') {
dir('app') {
git url: 'git://example.com/aem-project.git', branch: 'master'
}
dir('tests') {
git url: 'git://example.com/tests.git', branch: 'master'
}
}
stage('Build') {
node('aem') {
dir('app/aem') {
sh 'mvn clean install'
}
}
}
stage('Test') {
dir('tests') {
sh './gradlew clean contractTests'
}
}
}
24
node('master') {
stage('Checkout') {
dir('app') {
git url: 'git://example.com/aem-project.git', branch: 'master'
}
dir('tests') {
git url: 'git://example.com/tests.git', branch: 'master'
}
}
stage('Build') {
node('aem') {
dir('app/aem') {
sh 'mvn clean install'
}
}
}
stage('Test') {
dir('tests') {
sh './gradlew clean contractTests'
}
}
}
25
node('master') {
stage('Checkout') {
dir('app') {
git url: 'git://example.com/aem-project.git', branch: 'master'
}
dir('tests') {
git url: 'git://example.com/tests.git', branch: 'master'
}
}
stage('Build') {
node('aem') {
dir('app/aem') {
sh 'mvn clean install'
}
}
}
stage('Test') {
dir('tests') {
sh './gradlew clean contractTests'
}
}
}
26
node('master') {
stage('Checkout') {
dir('app') {
git url: 'git://example.com/aem-project.git', branch: 'master'
}
dir('tests') {
git url: 'git://example.com/tests.git', branch: 'master'
}
}
stage('Build') {
node('aem') {
dir('app/aem') {
sh 'mvn clean install'
}
}
}
stage('Test') {
dir('tests') {
sh './gradlew clean contractTests'
}
}
}
Build / Deploy / Test
27
28
Build / Deploy / Test
29
Build / Deploy / Test
30
Build / Deploy / Test
31
Build / Deploy / Test
32
Build / Deploy / Test
33
Build / Deploy / Test
34
Build / Deploy / Test
35
Build / Deploy / Test
36
Build / Deploy / Test
37
Build / Deploy / Test
38
Build / Deploy / Test
39
Pipeline improvements
40
▪ Dynamically defined stages
▪ Local & global configuration files
▪ Custom shared library
https://flic.kr/p/juzu1W
41
#!groovy
@Library('cognifide-library@master')
import com.cognifide.jenkinslib.Pipeline
def pipeline = new Pipeline(this)
node('master') {
withMaven(maven: 'Maven 3') {
stage('Quality Gate: Sonarqube') {
sonarqube pipeline.CFG.sonarqube
}
stage('Build') {
// ...
}
stage('Clear dispatcher cache') {
knifeExec query: "chef_environment:${pipeline.CFG.chef.environmentName}
AND tags:dispatcher"
}
}
}
42
#!groovy
@Library('cognifide-library@master')
import com.cognifide.jenkinslib.Pipeline
def pipeline = new Pipeline(this)
node('master') {
withMaven(maven: 'Maven 3') {
stage('Quality Gate: Sonarqube') {
sonarqube pipeline.CFG.sonarqube
}
stage('Build') {
// ...
}
stage('Clear dispatcher cache') {
knifeExec query: "chef_environment:${pipeline.CFG.chef.environmentName}
AND tags:dispatcher"
}
}
}
43
#!groovy
@Library('cognifide-library@master')
import com.cognifide.jenkinslib.Pipeline
def pipeline = new Pipeline(this)
node('master') {
withMaven(maven: 'Maven 3') {
stage('Quality Gate: Sonarqube') {
sonarqube pipeline.CFG.sonarqube
}
stage('Build') {
// ...
}
stage('Clear dispatcher cache') {
knifeExec query: "chef_environment:${pipeline.CFG.chef.environmentName}
AND tags:dispatcher"
}
}
}
44
#!groovy
@Library('cognifide-library@master')
import com.cognifide.jenkinslib.Pipeline
def pipeline = new Pipeline(this)
node('master') {
withMaven(maven: 'Maven 3') {
stage('Quality Gate: Sonarqube') {
sonarqube pipeline.CFG.sonarqube
}
stage('Build') {
// ...
}
stage('Clear dispatcher cache') {
knifeExec query: "chef_environment:${pipeline.CFG.chef.environmentName}
AND tags:dispatcher"
}
}
}
45
#!groovy
@Library('cognifide-library@master')
import com.cognifide.jenkinslib.Pipeline
def pipeline = new Pipeline(this)
node('master') {
withMaven(maven: 'Maven 3') {
stage('Quality Gate: Sonarqube') {
sonarqube pipeline.CFG.sonarqube
}
stage('Build') {
// ...
}
stage('Clear dispatcher cache') {
knifeExec query: "chef_environment:${pipeline.CFG.chef.environmentName}
AND tags:dispatcher"
}
}
}
46
#!groovy
@Library('cognifide-library@master')
import com.cognifide.jenkinslib.Pipeline
def pipeline = new Pipeline(this)
node('master') {
withMaven(maven: 'Maven 3') {
stage('Quality Gate: Sonarqube') {
sonarqube pipeline.CFG.sonarqube
}
stage('Build') {
// ...
}
stage('Clear dispatcher cache') {
knifeExec query: "chef_environment:${pipeline.CFG.chef.environmentName}
AND tags:dispatcher"
}
}
}
47
notifications:
enabled: true
recipients:
- 'dev-team@example.com'
deploy:
profiles:
aem-author: 'dev-author'
aem-publish1: 'dev-publish1'
aem-publish2: 'dev-publish2'
tests:
bobcat:
profiles:
- 'dev'
- 'grid'
mvnParams: '-Dfork.count=4'
chef:
environmentName: 'dev'
Testing
48
▪ Unit tests
▪ Bobcat
▪ github.com/Cognifide/bobcat
▪ Zalenium & Docker
▪ github.com/zalando/zalenium
▪ AET
▪ github.com/Cognifide/aet
https://flic.kr/p/juzgT9
Release
49https://flic.kr/p/EQbNYd
▪ Release != deployment
▪ Unnoticeable process
▪ Artifact store is a must
50
Infrastructure
Solution
51
Infrastructure setup
52
▪ Multiple AWS environments
▪ Terraform modules
▪ Bootstrap process
https://flic.kr/p/qCk82v
Service discovery
53
▪ Interconnectivity
▪ Hardcoded IPs are not an option
▪ Adapts to changes by itself
https://flic.kr/p/qr4XXW
Solution
54
Consul features
55
▪ DNS-based service discovery
▪ Load balancing
▪ Health checks
Consul talk
56
https://goo.gl/aZjKsR
57
Automated deployments
Solution
58
Chef
59
▪ Configuration management
▪ Each service has its own cookbook
▪ Deployment steps written in DSL
https://flic.kr/p/W25Lmv
Chef example
60
▪ Install a package
▪ Restart AEM
▪ Remove default flush agent
https://flic.kr/p/9qsZDC
61
cq_package 'Author: Core app' do
username 'admin'
password 'admin'
instance 'http://localhost:4502'
source 'https://artifacts.example.com/xyz/1.0/xyz-1.0.3-full.zip'
http_user 'basic_auth_user'
http_pass 'basic_auth_password'
action :deploy
end
62
cq_package 'Author: Core app' do
username 'admin'
password 'admin'
instance 'http://localhost:4502'
source 'https://artifacts.example.com/xyz/1.0/xyz-1.0.3-full.zip'
http_user 'basic_auth_user'
http_pass 'basic_auth_password'
action :deploy
end
63
cq_package 'Author: Core app' do
username 'admin'
password 'admin'
instance 'http://localhost:4502'
source 'https://artifacts.example.com/xyz/1.0/xyz-1.0.3-full.zip'
http_user 'basic_auth_user'
http_pass 'basic_auth_password'
action :deploy
end
64
cq_package 'Author: Core app' do
username 'admin'
password 'admin'
instance 'http://localhost:4502'
source 'https://artifacts.example.com/xyz/1.0/xyz-1.0.3-full.zip'
http_user 'basic_auth_user'
http_pass 'basic_auth_password'
action :deploy
end
65
cq_package 'Author: Core app' do
username node['cq']['author']['credentials']['login']
password node['cq']['author']['credentials']['password']
instance "http://localhost:#{node['cq']['author']['port']}"
source "https://artifacts.example.com/xyz/#{ver_dir}/"
"xyz-#{ver}-full.zip"
http_user node['xyz-webapp']['nexus']['user']
http_pass node['xyz-webapp']['nexus']['password']
action :deploy
end
66
cq_package 'Author: Core app' do
username 'admin'
password 'admin'
instance 'http://localhost:4502'
source 'https://artifacts.example.com/xyz/1.0/xyz-1.0.3-full.zip'
http_user 'basic_auth_user'
http_pass 'basic_auth_password'
action :deploy
notifies :restart, 'service[cq62-author]', :immediately
end
service 'cq62-author' do
action :nothing
end
67
cq_package 'Author: Core app' do
username 'admin'
password 'admin'
instance 'http://localhost:4502'
source 'https://artifacts.example.com/xyz/1.0/xyz-1.0.3-full.zip'
http_user 'basic_auth_user'
http_pass 'basic_auth_password'
action :deploy
notifies :restart, 'service[cq62-author]', :immediately
end
service 'cq62-author' do
action :nothing
end
68
cq_package 'Author: Core app' do
username 'admin'
password 'admin'
instance 'http://localhost:4502'
source 'https://artifacts.example.com/xyz/1.0/xyz-1.0.3-full.zip'
http_user 'basic_auth_user'
http_pass 'basic_auth_password'
action :deploy
notifies :restart, 'service[cq62-author]', :immediately
end
service 'cq62-author' do
action :nothing
end
69
cq_package 'Author: Core app' do
username 'admin'
password 'admin'
instance 'http://localhost:4502'
source 'https://artifacts.example.com/xyz/1.0/xyz-1.0.3-full.zip'
http_user 'basic_auth_user'
http_pass 'basic_auth_password'
action :deploy
notifies :restart, 'service[cq62-author]', :immediately
end
service 'cq62-author' do
action :nothing
end
70
cq_jcr 'Author: /etc/replication/agents.author/flush' do
path '/etc/replication/agents.author/flush'
username 'admin'
password 'admin'
instance 'http://localhost:4502'
action :delete
end
71
cq_jcr 'Author: /etc/replication/agents.author/flush' do
path '/etc/replication/agents.author/flush'
username 'admin'
password 'admin'
instance 'http://localhost:4502'
action :delete
end
72
cq_jcr 'Author: /etc/replication/agents.author/flush' do
path '/etc/replication/agents.author/flush'
username 'admin'
password 'admin'
instance 'http://localhost:4502'
action :delete
end
73
cq_jcr 'Author: /etc/replication/agents.author/flush' do
path '/etc/replication/agents.author/flush'
username 'admin'
password 'admin'
instance 'http://localhost:4502'
action :delete
end
74
$ chef-client
# ...
Chef Client finished, 39/652 resources updated in 09 minutes 46 seconds
$ chef-client
# ...
Chef Client finished, 0/652 resources updated in 01 minutes 58 seconds
75
$ chef-client
# ...
Chef Client finished, 39/652 resources updated in 09 minutes 46 seconds
$ chef-client
# ...
Chef Client finished, 0/652 resources updated in 01 minutes 58 seconds
76
$ grep cq_package recipes/author*.rb | wc -l
70
$ grep cq_jcr recipes/author*.rb | wc -l
20
$ grep cq_package recipes/publish*.rb | wc -l
67
$ grep cq_jcr recipes/publish*.rb | wc -l
11
What’s currently available?
77
▪ cq_package
▪ cq_osgi_config
▪ cq_osgi_bundle
▪ cq_osgi_component
▪ cq_user
▪ cq_jcr
▪ groovy_script
▪ apm_script
▪ …
https://flic.kr/p/qhRjAF
AEM cookbook
78
github.com/jwadolowski/cookbook-cq
79
Orchestration
Orchestration
80
▪ Deployment pipelines
▪ Driven by “knife ssh” command
https://flic.kr/p/eYhy4y
81
82
$ knife ssh 
'chef_environment:xyz-prod AND tags:aem AND tags:author' 
'sudo -u apache /bin/touch /path/to/maintenance/maintenance.lock'
83
$ knife ssh 
'chef_environment:xyz-prod AND tags:aem AND tags:author' 
'sudo -u apache /bin/touch /path/to/maintenance/maintenance.lock'
84
$ knife ssh 
'chef_environment:xyz-prod AND tags:aem AND tags:author' 
'sudo -u apache /bin/touch /path/to/maintenance/maintenance.lock'
85
86
$ knife ssh 
'chef_environment:xyz-prod AND tags:dispatcher AND tags:us-east-1a' 
'sudo -u apache /bin/touch /path/to/maintenance/deployment.lock'
87
$ knife ssh 
'chef_environment:xyz-prod AND tags:dispatcher AND tags:us-east-1a' 
'sudo -u apache /bin/touch /path/to/maintenance/deployment.lock'
88
$ knife ssh 
'chef_environment:xyz-prod AND tags:dispatcher AND tags:us-east-1a' 
'sudo -u apache /bin/touch /path/to/maintenance/deployment.lock'
89
90
$ knife ssh 
'chef_environment:xyz-prod AND (
(tags:dispatcher AND tags:us-east-1a) OR
(tags:aem AND tags:publish AND tags:us-east-1a)
)' 
'sudo /usr/bin/chef-client'
91
$ knife ssh 
'chef_environment:xyz-prod AND (
(tags:dispatcher AND tags:us-east-1a) OR
(tags:aem AND tags:publish AND tags:us-east-1a)
)' 
'sudo /usr/bin/chef-client'
92
$ knife ssh 
'chef_environment:xyz-prod AND (
(tags:dispatcher AND tags:us-east-1a) OR
(tags:aem AND tags:publish AND tags:us-east-1a)
)' 
'sudo /usr/bin/chef-client'
93
$ knife ssh 
'chef_environment:xyz-prod AND tags:dispatcher AND tags:us-east-1a' 
'sudo -u apache /usr/bin/rm -f /path/to/maintenance/deployment.lock'
94
95
96
97
Lessons learned
98
▪ Fail fast
▪ Enforce correct exit codes
▪ How to resume failed pipeline?
https://flic.kr/p/jzAyNF
99
Danke schön!

Weitere ähnliche Inhalte

Was ist angesagt?

"Wix Serverless from inside", Mykola Borozdin
"Wix Serverless from inside", Mykola Borozdin"Wix Serverless from inside", Mykola Borozdin
"Wix Serverless from inside", Mykola BorozdinFwdays
 
Learn basic ansible using docker
Learn basic ansible using dockerLearn basic ansible using docker
Learn basic ansible using dockerLarry Cai
 
Into The Box 2018 Going live with commandbox and docker
Into The Box 2018 Going live with commandbox and dockerInto The Box 2018 Going live with commandbox and docker
Into The Box 2018 Going live with commandbox and dockerOrtus Solutions, Corp
 
Vagrant introduction for Developers
Vagrant introduction for DevelopersVagrant introduction for Developers
Vagrant introduction for DevelopersAntons Kranga
 
Puppet Camp London Fall 2015 - Service Discovery and Puppet
Puppet Camp London Fall 2015 - Service Discovery and PuppetPuppet Camp London Fall 2015 - Service Discovery and Puppet
Puppet Camp London Fall 2015 - Service Discovery and PuppetMarc Cluet
 
A complete guide to Node.js
A complete guide to Node.jsA complete guide to Node.js
A complete guide to Node.jsPrabin Silwal
 
Ninja Build: Simple Guide for Beginners
Ninja Build: Simple Guide for BeginnersNinja Build: Simple Guide for Beginners
Ninja Build: Simple Guide for BeginnersChang W. Doh
 
TomcatCon: from a cluster to the cloud
TomcatCon: from a cluster to the cloudTomcatCon: from a cluster to the cloud
TomcatCon: from a cluster to the cloudJean-Frederic Clere
 
Docker remote-api
Docker remote-apiDocker remote-api
Docker remote-apiEric Ahn
 
Docker command
Docker commandDocker command
Docker commandEric Ahn
 
Docker Compose to Production with Docker Swarm
Docker Compose to Production with Docker SwarmDocker Compose to Production with Docker Swarm
Docker Compose to Production with Docker SwarmMario IC
 
Homer - Workshop at Kamailio World 2017
Homer - Workshop at Kamailio World 2017Homer - Workshop at Kamailio World 2017
Homer - Workshop at Kamailio World 2017Giacomo Vacca
 
Lesson Learned from Using Docker Swarm at Pronto
Lesson Learned from Using Docker Swarm at ProntoLesson Learned from Using Docker Swarm at Pronto
Lesson Learned from Using Docker Swarm at ProntoKan Ouivirach, Ph.D.
 
Puppet in the Pipeline
Puppet in the PipelinePuppet in the Pipeline
Puppet in the PipelinePuppet
 
Toolbox of a Ruby Team
Toolbox of a Ruby TeamToolbox of a Ruby Team
Toolbox of a Ruby TeamArto Artnik
 
How to create your own hack environment
How to create your own hack environmentHow to create your own hack environment
How to create your own hack environmentSumedt Jitpukdebodin
 
Live deployment, ci, drupal
Live deployment, ci, drupalLive deployment, ci, drupal
Live deployment, ci, drupalAndrii Podanenko
 

Was ist angesagt? (20)

"Wix Serverless from inside", Mykola Borozdin
"Wix Serverless from inside", Mykola Borozdin"Wix Serverless from inside", Mykola Borozdin
"Wix Serverless from inside", Mykola Borozdin
 
Everything as a code
Everything as a codeEverything as a code
Everything as a code
 
Learn basic ansible using docker
Learn basic ansible using dockerLearn basic ansible using docker
Learn basic ansible using docker
 
Into The Box 2018 Going live with commandbox and docker
Into The Box 2018 Going live with commandbox and dockerInto The Box 2018 Going live with commandbox and docker
Into The Box 2018 Going live with commandbox and docker
 
Vagrant introduction for Developers
Vagrant introduction for DevelopersVagrant introduction for Developers
Vagrant introduction for Developers
 
Puppet Camp London Fall 2015 - Service Discovery and Puppet
Puppet Camp London Fall 2015 - Service Discovery and PuppetPuppet Camp London Fall 2015 - Service Discovery and Puppet
Puppet Camp London Fall 2015 - Service Discovery and Puppet
 
A complete guide to Node.js
A complete guide to Node.jsA complete guide to Node.js
A complete guide to Node.js
 
Ninja Build: Simple Guide for Beginners
Ninja Build: Simple Guide for BeginnersNinja Build: Simple Guide for Beginners
Ninja Build: Simple Guide for Beginners
 
Beyond Puppet
Beyond PuppetBeyond Puppet
Beyond Puppet
 
TomcatCon: from a cluster to the cloud
TomcatCon: from a cluster to the cloudTomcatCon: from a cluster to the cloud
TomcatCon: from a cluster to the cloud
 
Docker remote-api
Docker remote-apiDocker remote-api
Docker remote-api
 
Docker command
Docker commandDocker command
Docker command
 
Docker Compose to Production with Docker Swarm
Docker Compose to Production with Docker SwarmDocker Compose to Production with Docker Swarm
Docker Compose to Production with Docker Swarm
 
About Node.js
About Node.jsAbout Node.js
About Node.js
 
Homer - Workshop at Kamailio World 2017
Homer - Workshop at Kamailio World 2017Homer - Workshop at Kamailio World 2017
Homer - Workshop at Kamailio World 2017
 
Lesson Learned from Using Docker Swarm at Pronto
Lesson Learned from Using Docker Swarm at ProntoLesson Learned from Using Docker Swarm at Pronto
Lesson Learned from Using Docker Swarm at Pronto
 
Puppet in the Pipeline
Puppet in the PipelinePuppet in the Pipeline
Puppet in the Pipeline
 
Toolbox of a Ruby Team
Toolbox of a Ruby TeamToolbox of a Ruby Team
Toolbox of a Ruby Team
 
How to create your own hack environment
How to create your own hack environmentHow to create your own hack environment
How to create your own hack environment
 
Live deployment, ci, drupal
Live deployment, ci, drupalLive deployment, ci, drupal
Live deployment, ci, drupal
 

Ähnlich wie Taming AEM deployments

(Declarative) Jenkins Pipelines
(Declarative) Jenkins Pipelines(Declarative) Jenkins Pipelines
(Declarative) Jenkins PipelinesSteffen Gebert
 
Moving from Jenkins 1 to 2 declarative pipeline adventures
Moving from Jenkins 1 to 2 declarative pipeline adventuresMoving from Jenkins 1 to 2 declarative pipeline adventures
Moving from Jenkins 1 to 2 declarative pipeline adventuresFrits Van Der Holst
 
Railsconf2011 deployment tips_for_slideshare
Railsconf2011 deployment tips_for_slideshareRailsconf2011 deployment tips_for_slideshare
Railsconf2011 deployment tips_for_slidesharetomcopeland
 
DPDK in Containers Hands-on Lab
DPDK in Containers Hands-on LabDPDK in Containers Hands-on Lab
DPDK in Containers Hands-on LabMichelle Holley
 
PuppetConf 2016: The Challenges with Container Configuration – David Lutterko...
PuppetConf 2016: The Challenges with Container Configuration – David Lutterko...PuppetConf 2016: The Challenges with Container Configuration – David Lutterko...
PuppetConf 2016: The Challenges with Container Configuration – David Lutterko...Puppet
 
Challenges of container configuration
Challenges of container configurationChallenges of container configuration
Challenges of container configurationlutter
 
Scaling Development Environments with Docker
Scaling Development Environments with DockerScaling Development Environments with Docker
Scaling Development Environments with DockerDocker, Inc.
 
Server(less) Swift at SwiftCloudWorkshop 3
Server(less) Swift at SwiftCloudWorkshop 3Server(less) Swift at SwiftCloudWorkshop 3
Server(less) Swift at SwiftCloudWorkshop 3kognate
 
Check the version with fixes. Link in description
Check the version with fixes. Link in descriptionCheck the version with fixes. Link in description
Check the version with fixes. Link in descriptionPrzemyslaw Koltermann
 
Using the Groovy Ecosystem for Rapid JVM Development
Using the Groovy Ecosystem for Rapid JVM DevelopmentUsing the Groovy Ecosystem for Rapid JVM Development
Using the Groovy Ecosystem for Rapid JVM DevelopmentSchalk Cronjé
 
Erik Skytthe - Monitoring Mesos, Docker, Containers with Zabbix | ZabConf2016
Erik Skytthe - Monitoring Mesos, Docker, Containers with Zabbix | ZabConf2016Erik Skytthe - Monitoring Mesos, Docker, Containers with Zabbix | ZabConf2016
Erik Skytthe - Monitoring Mesos, Docker, Containers with Zabbix | ZabConf2016Zabbix
 
Package a PyApp as a Flatpak Package: An HTTP Server for Example @ PyCon APAC...
Package a PyApp as a Flatpak Package: An HTTP Server for Example @ PyCon APAC...Package a PyApp as a Flatpak Package: An HTTP Server for Example @ PyCon APAC...
Package a PyApp as a Flatpak Package: An HTTP Server for Example @ PyCon APAC...Jian-Hong Pan
 
Introducing Playwright's New Test Runner
Introducing Playwright's New Test RunnerIntroducing Playwright's New Test Runner
Introducing Playwright's New Test RunnerApplitools
 
Orchestrated Functional Testing with Puppet-spec and Mspectator
Orchestrated Functional Testing with Puppet-spec and MspectatorOrchestrated Functional Testing with Puppet-spec and Mspectator
Orchestrated Functional Testing with Puppet-spec and MspectatorRaphaël PINSON
 
Orchestrated Functional Testing with Puppet-spec and Mspectator - PuppetConf ...
Orchestrated Functional Testing with Puppet-spec and Mspectator - PuppetConf ...Orchestrated Functional Testing with Puppet-spec and Mspectator - PuppetConf ...
Orchestrated Functional Testing with Puppet-spec and Mspectator - PuppetConf ...Puppet
 
Session on Launching Selenium Grid and Running tests using docker compose and...
Session on Launching Selenium Grid and Running tests using docker compose and...Session on Launching Selenium Grid and Running tests using docker compose and...
Session on Launching Selenium Grid and Running tests using docker compose and...Agile Testing Alliance
 

Ähnlich wie Taming AEM deployments (20)

(Declarative) Jenkins Pipelines
(Declarative) Jenkins Pipelines(Declarative) Jenkins Pipelines
(Declarative) Jenkins Pipelines
 
Moving from Jenkins 1 to 2 declarative pipeline adventures
Moving from Jenkins 1 to 2 declarative pipeline adventuresMoving from Jenkins 1 to 2 declarative pipeline adventures
Moving from Jenkins 1 to 2 declarative pipeline adventures
 
Jenkins Pipelines
Jenkins PipelinesJenkins Pipelines
Jenkins Pipelines
 
Railsconf2011 deployment tips_for_slideshare
Railsconf2011 deployment tips_for_slideshareRailsconf2011 deployment tips_for_slideshare
Railsconf2011 deployment tips_for_slideshare
 
DPDK in Containers Hands-on Lab
DPDK in Containers Hands-on LabDPDK in Containers Hands-on Lab
DPDK in Containers Hands-on Lab
 
PuppetConf 2016: The Challenges with Container Configuration – David Lutterko...
PuppetConf 2016: The Challenges with Container Configuration – David Lutterko...PuppetConf 2016: The Challenges with Container Configuration – David Lutterko...
PuppetConf 2016: The Challenges with Container Configuration – David Lutterko...
 
Challenges of container configuration
Challenges of container configurationChallenges of container configuration
Challenges of container configuration
 
Docker perl build
Docker perl buildDocker perl build
Docker perl build
 
Scaling Development Environments with Docker
Scaling Development Environments with DockerScaling Development Environments with Docker
Scaling Development Environments with Docker
 
Server(less) Swift at SwiftCloudWorkshop 3
Server(less) Swift at SwiftCloudWorkshop 3Server(less) Swift at SwiftCloudWorkshop 3
Server(less) Swift at SwiftCloudWorkshop 3
 
Check the version with fixes. Link in description
Check the version with fixes. Link in descriptionCheck the version with fixes. Link in description
Check the version with fixes. Link in description
 
Front-end tools
Front-end toolsFront-end tools
Front-end tools
 
Using the Groovy Ecosystem for Rapid JVM Development
Using the Groovy Ecosystem for Rapid JVM DevelopmentUsing the Groovy Ecosystem for Rapid JVM Development
Using the Groovy Ecosystem for Rapid JVM Development
 
Erik Skytthe - Monitoring Mesos, Docker, Containers with Zabbix | ZabConf2016
Erik Skytthe - Monitoring Mesos, Docker, Containers with Zabbix | ZabConf2016Erik Skytthe - Monitoring Mesos, Docker, Containers with Zabbix | ZabConf2016
Erik Skytthe - Monitoring Mesos, Docker, Containers with Zabbix | ZabConf2016
 
Package a PyApp as a Flatpak Package: An HTTP Server for Example @ PyCon APAC...
Package a PyApp as a Flatpak Package: An HTTP Server for Example @ PyCon APAC...Package a PyApp as a Flatpak Package: An HTTP Server for Example @ PyCon APAC...
Package a PyApp as a Flatpak Package: An HTTP Server for Example @ PyCon APAC...
 
Docker as an every day work tool
Docker as an every day work toolDocker as an every day work tool
Docker as an every day work tool
 
Introducing Playwright's New Test Runner
Introducing Playwright's New Test RunnerIntroducing Playwright's New Test Runner
Introducing Playwright's New Test Runner
 
Orchestrated Functional Testing with Puppet-spec and Mspectator
Orchestrated Functional Testing with Puppet-spec and MspectatorOrchestrated Functional Testing with Puppet-spec and Mspectator
Orchestrated Functional Testing with Puppet-spec and Mspectator
 
Orchestrated Functional Testing with Puppet-spec and Mspectator - PuppetConf ...
Orchestrated Functional Testing with Puppet-spec and Mspectator - PuppetConf ...Orchestrated Functional Testing with Puppet-spec and Mspectator - PuppetConf ...
Orchestrated Functional Testing with Puppet-spec and Mspectator - PuppetConf ...
 
Session on Launching Selenium Grid and Running tests using docker compose and...
Session on Launching Selenium Grid and Running tests using docker compose and...Session on Launching Selenium Grid and Running tests using docker compose and...
Session on Launching Selenium Grid and Running tests using docker compose and...
 

Mehr von Jakub Wadolowski

Don’t reduce dispatcher testing to an afterthought
Don’t reduce dispatcher testing to an afterthoughtDon’t reduce dispatcher testing to an afterthought
Don’t reduce dispatcher testing to an afterthoughtJakub Wadolowski
 
Automated CI with AEM Cloud service
Automated CI with AEM Cloud serviceAutomated CI with AEM Cloud service
Automated CI with AEM Cloud serviceJakub Wadolowski
 
The curious case of misrendered JSON
The curious case of misrendered JSONThe curious case of misrendered JSON
The curious case of misrendered JSONJakub Wadolowski
 
Image optimization at the edge
Image optimization at the edgeImage optimization at the edge
Image optimization at the edgeJakub Wadolowski
 
Taming content delivery at scale
Taming content delivery at scaleTaming content delivery at scale
Taming content delivery at scaleJakub Wadolowski
 
Into the nooks and crannies of Boden’s digital transformation
Into the nooks and crannies of Boden’s digital transformationInto the nooks and crannies of Boden’s digital transformation
Into the nooks and crannies of Boden’s digital transformationJakub Wadolowski
 
How to seamlessly incorporate CDN into your application stack
How to seamlessly incorporate CDN into your application stackHow to seamlessly incorporate CDN into your application stack
How to seamlessly incorporate CDN into your application stackJakub Wadolowski
 
The underappreciated power of content invalidation
The underappreciated power of content invalidationThe underappreciated power of content invalidation
The underappreciated power of content invalidationJakub Wadolowski
 
When dispatcher caching is not enough... (extended version)
When dispatcher caching is not enough... (extended version)When dispatcher caching is not enough... (extended version)
When dispatcher caching is not enough... (extended version)Jakub Wadolowski
 
When dispatcher caching is not enough...
When dispatcher caching is not enough...When dispatcher caching is not enough...
When dispatcher caching is not enough...Jakub Wadolowski
 

Mehr von Jakub Wadolowski (12)

Don’t reduce dispatcher testing to an afterthought
Don’t reduce dispatcher testing to an afterthoughtDon’t reduce dispatcher testing to an afterthought
Don’t reduce dispatcher testing to an afterthought
 
Automated CI with AEM Cloud service
Automated CI with AEM Cloud serviceAutomated CI with AEM Cloud service
Automated CI with AEM Cloud service
 
The curious case of misrendered JSON
The curious case of misrendered JSONThe curious case of misrendered JSON
The curious case of misrendered JSON
 
The shift to the edge
The shift to the edgeThe shift to the edge
The shift to the edge
 
Image optimization at the edge
Image optimization at the edgeImage optimization at the edge
Image optimization at the edge
 
The shift to the edge
The shift to the edgeThe shift to the edge
The shift to the edge
 
Taming content delivery at scale
Taming content delivery at scaleTaming content delivery at scale
Taming content delivery at scale
 
Into the nooks and crannies of Boden’s digital transformation
Into the nooks and crannies of Boden’s digital transformationInto the nooks and crannies of Boden’s digital transformation
Into the nooks and crannies of Boden’s digital transformation
 
How to seamlessly incorporate CDN into your application stack
How to seamlessly incorporate CDN into your application stackHow to seamlessly incorporate CDN into your application stack
How to seamlessly incorporate CDN into your application stack
 
The underappreciated power of content invalidation
The underappreciated power of content invalidationThe underappreciated power of content invalidation
The underappreciated power of content invalidation
 
When dispatcher caching is not enough... (extended version)
When dispatcher caching is not enough... (extended version)When dispatcher caching is not enough... (extended version)
When dispatcher caching is not enough... (extended version)
 
When dispatcher caching is not enough...
When dispatcher caching is not enough...When dispatcher caching is not enough...
When dispatcher caching is not enough...
 

Kürzlich hochgeladen

🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘RTylerCroy
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptxHampshireHUG
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?Antenna Manufacturer Coco
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxMalak Abu Hammad
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsEnterprise Knowledge
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonAnna Loughnan Colquhoun
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...Martijn de Jong
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processorsdebabhi2
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CVKhem
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...Neo4j
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024Results
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfEnterprise Knowledge
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Servicegiselly40
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsJoaquim Jorge
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)wesley chun
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 

Kürzlich hochgeladen (20)

🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 

Taming AEM deployments

  • 1. APACHE SLING & FRIENDS TECH MEETUP BERLIN, 25-27 SEPTEMBER 2017 Taming AEM deployments Jakub Wądołowski, Cognifide
  • 2. The road to efficient AEM delivery 2https://flic.kr/p/z8g25R ▪ Starts on your computer ▪ Ends in production ▪ Includes everything in between
  • 4. Local environment 4https://flic.kr/p/b93YGx ▪ Everyone runs the same ▪ It contains the entire technology stack ▪ Start over any time you need it
  • 6. What’s in the box? 6https://flic.kr/p/cMBbTu ▪ AEM Author & AEM Publish ▪ Preinstalled packages ▪ Dispatcher ▪ Solr Master & Slave ▪ knot.x
  • 7. Vagrant in practice (1/3) 7 # Install prerequisites: # * Vagrant # * VirtualBox # * ChefDK $ git clone git@example.org:xyz/vagrant.git $ cd project-vagrant $ rake init $ rake up
  • 8. Vagrant in practice (2/3) 8 ▪ http://localhost:4502 (AEM Author) ▪ http://localhost:4503 (AEM Publish) ▪ https://example.vagrant (Dispatcher) ▪ http://localhost:8983 (Solr) ▪ etc
  • 9. Vagrant in practice (3/3) 9 $ rake provision:publish ... Chef Client finished, 8/196 resources updated in 02 minutes 02 seconds $ rake provision:httpd ... Chef Client finished, 4/41 resources updated in 19 seconds
  • 14. Use case (1/4) 14 ▪ 17 Chef cookbook repos ▪ 2 CI related repos ▪ 3 config repos ▪ 4 app repos ▪ 2 infrastructure repos https://flic.kr/p/bF3Nwm
  • 15. Use case (2/4) 15 ▪ Each repository has its own lifecycle ▪ Simple Git flow https://flic.kr/p/peZfvA
  • 16. Use case (3/4) 16 $ tree -L 1 . ├── aem ├── domain ├── knotx-autocomplete ├── knotx-download ├── knotx-filters ├── knotx-index ├── knotx-search ├── pom.xml └── solr 8 directories, 1 file https://flic.kr/p/fnPQuz
  • 17. Use case (3/4) 17 $ tree -L 1 . ├── aem ├── domain ├── knotx-autocomplete ├── knotx-download ├── knotx-filters ├── knotx-index ├── knotx-search ├── pom.xml └── solr 8 directories, 1 file https://flic.kr/p/fnPQuz
  • 18. Use case (3/4) 18 $ tree -L 1 . ├── aem ├── domain ├── knotx-autocomplete ├── knotx-download ├── knotx-filters ├── knotx-index ├── knotx-search ├── pom.xml └── solr 8 directories, 1 file https://flic.kr/p/fnPQuz
  • 19. Use case (3/4) 19 $ tree -L 1 . ├── aem ├── domain ├── knotx-autocomplete ├── knotx-download ├── knotx-filters ├── knotx-index ├── knotx-search ├── solr └── pom.xml 8 directories, 1 file https://flic.kr/p/fnPQuz
  • 20. Use case (3/4) 20 $ tree -L 1 . ├── aem ├── domain ├── knotx-autocomplete ├── knotx-download ├── knotx-filters ├── knotx-index ├── knotx-search ├── solr └── pom.xml 8 directories, 1 file https://flic.kr/p/fnPQuz
  • 21. Use case (4/4) 21 ▪ Compatibility matrix is no longer needed ▪ End-to-end testing ▪ One release contains multiple artifacts
  • 22. Pipelines 22https://flic.kr/p/qG26gA ▪ Variety of choices ▪ Jenkins ▪ GoCD ▪ Bamboo ▪ etc ▪ Pipeline as code (Jenkinsfile)
  • 23. 23 node('master') { stage('Checkout') { dir('app') { git url: 'git://example.com/aem-project.git', branch: 'master' } dir('tests') { git url: 'git://example.com/tests.git', branch: 'master' } } stage('Build') { node('aem') { dir('app/aem') { sh 'mvn clean install' } } } stage('Test') { dir('tests') { sh './gradlew clean contractTests' } } }
  • 24. 24 node('master') { stage('Checkout') { dir('app') { git url: 'git://example.com/aem-project.git', branch: 'master' } dir('tests') { git url: 'git://example.com/tests.git', branch: 'master' } } stage('Build') { node('aem') { dir('app/aem') { sh 'mvn clean install' } } } stage('Test') { dir('tests') { sh './gradlew clean contractTests' } } }
  • 25. 25 node('master') { stage('Checkout') { dir('app') { git url: 'git://example.com/aem-project.git', branch: 'master' } dir('tests') { git url: 'git://example.com/tests.git', branch: 'master' } } stage('Build') { node('aem') { dir('app/aem') { sh 'mvn clean install' } } } stage('Test') { dir('tests') { sh './gradlew clean contractTests' } } }
  • 26. 26 node('master') { stage('Checkout') { dir('app') { git url: 'git://example.com/aem-project.git', branch: 'master' } dir('tests') { git url: 'git://example.com/tests.git', branch: 'master' } } stage('Build') { node('aem') { dir('app/aem') { sh 'mvn clean install' } } } stage('Test') { dir('tests') { sh './gradlew clean contractTests' } } }
  • 27. Build / Deploy / Test 27
  • 28. 28
  • 29. Build / Deploy / Test 29
  • 30. Build / Deploy / Test 30
  • 31. Build / Deploy / Test 31
  • 32. Build / Deploy / Test 32
  • 33. Build / Deploy / Test 33
  • 34. Build / Deploy / Test 34
  • 35. Build / Deploy / Test 35
  • 36. Build / Deploy / Test 36
  • 37. Build / Deploy / Test 37
  • 38. Build / Deploy / Test 38
  • 39. Build / Deploy / Test 39
  • 40. Pipeline improvements 40 ▪ Dynamically defined stages ▪ Local & global configuration files ▪ Custom shared library https://flic.kr/p/juzu1W
  • 41. 41 #!groovy @Library('cognifide-library@master') import com.cognifide.jenkinslib.Pipeline def pipeline = new Pipeline(this) node('master') { withMaven(maven: 'Maven 3') { stage('Quality Gate: Sonarqube') { sonarqube pipeline.CFG.sonarqube } stage('Build') { // ... } stage('Clear dispatcher cache') { knifeExec query: "chef_environment:${pipeline.CFG.chef.environmentName} AND tags:dispatcher" } } }
  • 42. 42 #!groovy @Library('cognifide-library@master') import com.cognifide.jenkinslib.Pipeline def pipeline = new Pipeline(this) node('master') { withMaven(maven: 'Maven 3') { stage('Quality Gate: Sonarqube') { sonarqube pipeline.CFG.sonarqube } stage('Build') { // ... } stage('Clear dispatcher cache') { knifeExec query: "chef_environment:${pipeline.CFG.chef.environmentName} AND tags:dispatcher" } } }
  • 43. 43 #!groovy @Library('cognifide-library@master') import com.cognifide.jenkinslib.Pipeline def pipeline = new Pipeline(this) node('master') { withMaven(maven: 'Maven 3') { stage('Quality Gate: Sonarqube') { sonarqube pipeline.CFG.sonarqube } stage('Build') { // ... } stage('Clear dispatcher cache') { knifeExec query: "chef_environment:${pipeline.CFG.chef.environmentName} AND tags:dispatcher" } } }
  • 44. 44 #!groovy @Library('cognifide-library@master') import com.cognifide.jenkinslib.Pipeline def pipeline = new Pipeline(this) node('master') { withMaven(maven: 'Maven 3') { stage('Quality Gate: Sonarqube') { sonarqube pipeline.CFG.sonarqube } stage('Build') { // ... } stage('Clear dispatcher cache') { knifeExec query: "chef_environment:${pipeline.CFG.chef.environmentName} AND tags:dispatcher" } } }
  • 45. 45 #!groovy @Library('cognifide-library@master') import com.cognifide.jenkinslib.Pipeline def pipeline = new Pipeline(this) node('master') { withMaven(maven: 'Maven 3') { stage('Quality Gate: Sonarqube') { sonarqube pipeline.CFG.sonarqube } stage('Build') { // ... } stage('Clear dispatcher cache') { knifeExec query: "chef_environment:${pipeline.CFG.chef.environmentName} AND tags:dispatcher" } } }
  • 46. 46 #!groovy @Library('cognifide-library@master') import com.cognifide.jenkinslib.Pipeline def pipeline = new Pipeline(this) node('master') { withMaven(maven: 'Maven 3') { stage('Quality Gate: Sonarqube') { sonarqube pipeline.CFG.sonarqube } stage('Build') { // ... } stage('Clear dispatcher cache') { knifeExec query: "chef_environment:${pipeline.CFG.chef.environmentName} AND tags:dispatcher" } } }
  • 47. 47 notifications: enabled: true recipients: - 'dev-team@example.com' deploy: profiles: aem-author: 'dev-author' aem-publish1: 'dev-publish1' aem-publish2: 'dev-publish2' tests: bobcat: profiles: - 'dev' - 'grid' mvnParams: '-Dfork.count=4' chef: environmentName: 'dev'
  • 48. Testing 48 ▪ Unit tests ▪ Bobcat ▪ github.com/Cognifide/bobcat ▪ Zalenium & Docker ▪ github.com/zalando/zalenium ▪ AET ▪ github.com/Cognifide/aet https://flic.kr/p/juzgT9
  • 49. Release 49https://flic.kr/p/EQbNYd ▪ Release != deployment ▪ Unnoticeable process ▪ Artifact store is a must
  • 52. Infrastructure setup 52 ▪ Multiple AWS environments ▪ Terraform modules ▪ Bootstrap process https://flic.kr/p/qCk82v
  • 53. Service discovery 53 ▪ Interconnectivity ▪ Hardcoded IPs are not an option ▪ Adapts to changes by itself https://flic.kr/p/qr4XXW
  • 55. Consul features 55 ▪ DNS-based service discovery ▪ Load balancing ▪ Health checks
  • 59. Chef 59 ▪ Configuration management ▪ Each service has its own cookbook ▪ Deployment steps written in DSL https://flic.kr/p/W25Lmv
  • 60. Chef example 60 ▪ Install a package ▪ Restart AEM ▪ Remove default flush agent https://flic.kr/p/9qsZDC
  • 61. 61 cq_package 'Author: Core app' do username 'admin' password 'admin' instance 'http://localhost:4502' source 'https://artifacts.example.com/xyz/1.0/xyz-1.0.3-full.zip' http_user 'basic_auth_user' http_pass 'basic_auth_password' action :deploy end
  • 62. 62 cq_package 'Author: Core app' do username 'admin' password 'admin' instance 'http://localhost:4502' source 'https://artifacts.example.com/xyz/1.0/xyz-1.0.3-full.zip' http_user 'basic_auth_user' http_pass 'basic_auth_password' action :deploy end
  • 63. 63 cq_package 'Author: Core app' do username 'admin' password 'admin' instance 'http://localhost:4502' source 'https://artifacts.example.com/xyz/1.0/xyz-1.0.3-full.zip' http_user 'basic_auth_user' http_pass 'basic_auth_password' action :deploy end
  • 64. 64 cq_package 'Author: Core app' do username 'admin' password 'admin' instance 'http://localhost:4502' source 'https://artifacts.example.com/xyz/1.0/xyz-1.0.3-full.zip' http_user 'basic_auth_user' http_pass 'basic_auth_password' action :deploy end
  • 65. 65 cq_package 'Author: Core app' do username node['cq']['author']['credentials']['login'] password node['cq']['author']['credentials']['password'] instance "http://localhost:#{node['cq']['author']['port']}" source "https://artifacts.example.com/xyz/#{ver_dir}/" "xyz-#{ver}-full.zip" http_user node['xyz-webapp']['nexus']['user'] http_pass node['xyz-webapp']['nexus']['password'] action :deploy end
  • 66. 66 cq_package 'Author: Core app' do username 'admin' password 'admin' instance 'http://localhost:4502' source 'https://artifacts.example.com/xyz/1.0/xyz-1.0.3-full.zip' http_user 'basic_auth_user' http_pass 'basic_auth_password' action :deploy notifies :restart, 'service[cq62-author]', :immediately end service 'cq62-author' do action :nothing end
  • 67. 67 cq_package 'Author: Core app' do username 'admin' password 'admin' instance 'http://localhost:4502' source 'https://artifacts.example.com/xyz/1.0/xyz-1.0.3-full.zip' http_user 'basic_auth_user' http_pass 'basic_auth_password' action :deploy notifies :restart, 'service[cq62-author]', :immediately end service 'cq62-author' do action :nothing end
  • 68. 68 cq_package 'Author: Core app' do username 'admin' password 'admin' instance 'http://localhost:4502' source 'https://artifacts.example.com/xyz/1.0/xyz-1.0.3-full.zip' http_user 'basic_auth_user' http_pass 'basic_auth_password' action :deploy notifies :restart, 'service[cq62-author]', :immediately end service 'cq62-author' do action :nothing end
  • 69. 69 cq_package 'Author: Core app' do username 'admin' password 'admin' instance 'http://localhost:4502' source 'https://artifacts.example.com/xyz/1.0/xyz-1.0.3-full.zip' http_user 'basic_auth_user' http_pass 'basic_auth_password' action :deploy notifies :restart, 'service[cq62-author]', :immediately end service 'cq62-author' do action :nothing end
  • 70. 70 cq_jcr 'Author: /etc/replication/agents.author/flush' do path '/etc/replication/agents.author/flush' username 'admin' password 'admin' instance 'http://localhost:4502' action :delete end
  • 71. 71 cq_jcr 'Author: /etc/replication/agents.author/flush' do path '/etc/replication/agents.author/flush' username 'admin' password 'admin' instance 'http://localhost:4502' action :delete end
  • 72. 72 cq_jcr 'Author: /etc/replication/agents.author/flush' do path '/etc/replication/agents.author/flush' username 'admin' password 'admin' instance 'http://localhost:4502' action :delete end
  • 73. 73 cq_jcr 'Author: /etc/replication/agents.author/flush' do path '/etc/replication/agents.author/flush' username 'admin' password 'admin' instance 'http://localhost:4502' action :delete end
  • 74. 74 $ chef-client # ... Chef Client finished, 39/652 resources updated in 09 minutes 46 seconds $ chef-client # ... Chef Client finished, 0/652 resources updated in 01 minutes 58 seconds
  • 75. 75 $ chef-client # ... Chef Client finished, 39/652 resources updated in 09 minutes 46 seconds $ chef-client # ... Chef Client finished, 0/652 resources updated in 01 minutes 58 seconds
  • 76. 76 $ grep cq_package recipes/author*.rb | wc -l 70 $ grep cq_jcr recipes/author*.rb | wc -l 20 $ grep cq_package recipes/publish*.rb | wc -l 67 $ grep cq_jcr recipes/publish*.rb | wc -l 11
  • 77. What’s currently available? 77 ▪ cq_package ▪ cq_osgi_config ▪ cq_osgi_bundle ▪ cq_osgi_component ▪ cq_user ▪ cq_jcr ▪ groovy_script ▪ apm_script ▪ … https://flic.kr/p/qhRjAF
  • 80. Orchestration 80 ▪ Deployment pipelines ▪ Driven by “knife ssh” command https://flic.kr/p/eYhy4y
  • 81. 81
  • 82. 82 $ knife ssh 'chef_environment:xyz-prod AND tags:aem AND tags:author' 'sudo -u apache /bin/touch /path/to/maintenance/maintenance.lock'
  • 83. 83 $ knife ssh 'chef_environment:xyz-prod AND tags:aem AND tags:author' 'sudo -u apache /bin/touch /path/to/maintenance/maintenance.lock'
  • 84. 84 $ knife ssh 'chef_environment:xyz-prod AND tags:aem AND tags:author' 'sudo -u apache /bin/touch /path/to/maintenance/maintenance.lock'
  • 85. 85
  • 86. 86 $ knife ssh 'chef_environment:xyz-prod AND tags:dispatcher AND tags:us-east-1a' 'sudo -u apache /bin/touch /path/to/maintenance/deployment.lock'
  • 87. 87 $ knife ssh 'chef_environment:xyz-prod AND tags:dispatcher AND tags:us-east-1a' 'sudo -u apache /bin/touch /path/to/maintenance/deployment.lock'
  • 88. 88 $ knife ssh 'chef_environment:xyz-prod AND tags:dispatcher AND tags:us-east-1a' 'sudo -u apache /bin/touch /path/to/maintenance/deployment.lock'
  • 89. 89
  • 90. 90 $ knife ssh 'chef_environment:xyz-prod AND ( (tags:dispatcher AND tags:us-east-1a) OR (tags:aem AND tags:publish AND tags:us-east-1a) )' 'sudo /usr/bin/chef-client'
  • 91. 91 $ knife ssh 'chef_environment:xyz-prod AND ( (tags:dispatcher AND tags:us-east-1a) OR (tags:aem AND tags:publish AND tags:us-east-1a) )' 'sudo /usr/bin/chef-client'
  • 92. 92 $ knife ssh 'chef_environment:xyz-prod AND ( (tags:dispatcher AND tags:us-east-1a) OR (tags:aem AND tags:publish AND tags:us-east-1a) )' 'sudo /usr/bin/chef-client'
  • 93. 93 $ knife ssh 'chef_environment:xyz-prod AND tags:dispatcher AND tags:us-east-1a' 'sudo -u apache /usr/bin/rm -f /path/to/maintenance/deployment.lock'
  • 94. 94
  • 95. 95
  • 96. 96
  • 97. 97
  • 98. Lessons learned 98 ▪ Fail fast ▪ Enforce correct exit codes ▪ How to resume failed pipeline? https://flic.kr/p/jzAyNF