SlideShare una empresa de Scribd logo
1 de 197
Descargar para leer sin conexión
Everything as a Code
Непривычно о привычном
@aatarasoff
@aatarasoff
@aatarasoff
Everything as a Code
Непривычно о привычном
No warranty guarantee
You think you are creator
5
6
… but matrix has you
7
Выйти за пределы...
8
...поняв, что всё есть код
9
Как вы представляете себе код?
10
@Configuration
@EnableConfigurationProperties(OneServerProperties.class)
public class OneServerConfiguration implements ApplicationContextAware {
ApplicationContext applicationContext;
@Autowired
OneServerProperties properties;
@Bean
public HttpServer httpServer() throws IOException {
HttpServer httpServer = new RelativePathHttpServer();
for (String beanName : context.getBeans(HttpController.class)) {
httpServer.addRequestHandlers(context.getBean(beanName));
}
return httpServer;
}
}
11
Наверное как-то так
>>,[>>,]<<[
[<<]>>>>[
<<[>+<<+>-]
>>[>+<<<<[->]>[<]>>-]
<<<[[-]>>[>+<-]>>[<<<+>>>-]]
>>[[<+>-]>>]<
]<<[>>+<<-]<<
]>>>>[.>>]
12
...или может быть так?
Что такое код?
● Коллекция инструкций
● Человекочитаемый формат
○ plain text
● Может быть понят и “проигран”
○ после компиляции
○ интерпретатором
13
Да я тоже пишу код!
14
Вооружи себя
15
Настройка рабочего окружения
16
Install apps Code Checkout
Configure
workspace
First Blood
17
Install apps Code Checkout
Configure
workspace
First Blood
brew install
18
Install apps Code Checkout
Configure
workspace
First Blood
brew install
pip install
19
Install apps Code Checkout
Configure
workspace
First Blood
git
20
Install apps Code Checkout
Configure
workspace
First Blood
customize
*.properties
21
Install apps Code Checkout
Configure
workspace
First Blood
customize
*.propertiestemplate
.gradle
22
Install apps Code Checkout
Configure
workspace
First Blood
customize
*.properties
install
certificates
23
Install apps Code Checkout
Configure
workspace
First Blood
first build
24
Install apps Code Checkout
Configure
workspace
First Blood
mass build
first deploy
25
ansible-playbook -i local-inv setup.yml --tags configure
26
Интерпретатор
ansible-playbook -i local-inv setup.yml --tags configure
27
Конфигурация
ansible-playbook -i local-inv setup.yml --tags configure
28
Алгоритм
# checkout repositories from git
- include: checkout.yml
# configure your local environment
- include: configure.yml
# add useful mappings to your hosts file
- include: hosts.yml
# add gradle support
- include: gradle.yml
# clean and build all projects
- include: build.yml
# delpoy all services to dev
- include: deploy.yml
29
Алгоритм
ansible-playbook -i local-inv setup.yml --tags configure
30
Входные параметры
- name: checkout services
git:
repo: "{{ git.root }}/{{ item.name }}.git"
dest: "{{ work_dir }}/{{ item.name }}"
update: yes
with_items:
- "{{ services }}"
tags:
- services
31
Массовый checkout/pull
- name: checkout services
git:
repo: "{{ git.root }}/{{ item.name }}.git"
dest: "{{ work_dir }}/{{ item.name }}"
update: yes
with_items:
- "{{ services }}"
tags:
- services
Переменные
32
- name: checkout services
git:
//
with_items:
- "{{ services }}"
services:
- { name: one-instant-messenger , sourceDir: src }
- { name: one-discussions , sourceDir: src }
- { name: one-attachment , sourceDir: src, testDir: test, local: true }
Циклы
33
services:
- { name: one-instant-messenger, sourceDir: src }
- { name: one-discussions, sourceDir: src }
- { name: one-attachment, sourceDir: src, testDir: test }
Коллекции и структуры данных
34
- name: create gradle build file
template:
src: build.gradle.j2
dest: "{{ work_dir }}/build.gradle"
mode: 0644
- name: create gradle settings file
template:
src: settings.gradle.j2
dest: "{{ work_dir }}/settings.gradle"
mode: 0644
Шаблоны
35
{% if services is not none %}{% for service in services %}
if (project.name == '{{ service.name }}') {
{% if 'sourceDir' in service %}
main.java.srcDir '{{ service.sourceDir }}'
{% endif %}{% if 'testDir' in service %}
test.java.srcDir '{{ service.testDir }}'
{% endif %}
}
Условные операторы
36
{% if services is not none %}{% for service in services %}
if (project.name == '{{ service.name }}') {
{% if 'sourceDir' in service %}
main.java.srcDir '{{ service.sourceDir }}'
{% endif %}{% if 'testDir' in service %}
test.java.srcDir '{{ service.testDir }}'
{% endif %}
}
Опять циклы
37
{% if services is not none %}{% for service in services %}
if (project.name == '{{ service.name }}') {
{% if 'sourceDir' in service %}
main.java.srcDir '{{ service.sourceDir }}'
{% endif %}{% if 'testDir' in service %}
test.java.srcDir '{{ service.testDir }}'
{% endif %}
}
Переменные
38
- stat: path={{ username }}.key
register: certkey
- name: generate private key
shell: openssl genrsa -out {{ username }}.key -aes256 4096
when: not certkey.stat.exists
Идемпотентность
39
Install apps Code Checkout
Configure
workspace
Multiplie Use
40
Петля обратной связи
git
Что получили
● Автоконфигурация рабочего
пространства
○ повторяемая
○ немутабельная
● Можно дать скрипт новичку
● Можно и нужно пользоваться этим
каждый день
41
Код есть код
42
Искусство сборки
43
Compile code Unit tests Package Publishing
44
Compile code Unit tests Package
compiler
Publishing
45
Compile code Unit tests Package
javacresource
processing
Publishing
46
Compile code Unit tests Package
javacresources
copyingdependency
resolving
Publishing
47
Compile code Unit tests Package
junit
Publishing
48
Compile code Unit tests Package
jar
Publishing
49
Compile code Unit tests Package
jar
npm, deb, ...
Publishing
50
Compile code Unit tests Package
jar
npm, so, ...
docker image
Publishing
51
Compile code Unit tests Package
ivy
Publishing
52
Compile code Unit tests Package
maven, ivy
maven
Publishing
53
Compile code Unit tests Package Publishing
maven, ivylocal or dev
deploydocker registry
54
Системы сборки
● Ant + Ivy
● Maven
● Gradle
● Docker
● npm
● ...
55
FROM golang:1.7-alpine
MAINTAINER aatarasoff@gmail.com
VOLUME /data
WORKDIR /data
RUN apk update && 
apk upgrade && 
apk add git bash
RUN go get github.com/aatarasoff/apistress && 
go install github.com/aatarasoff/apistress
CMD [ "apistress" ]
Dockerfile. Наследование
56
FROM golang:1.7-alpine
MAINTAINER aatarasoff@gmail.com
VOLUME /data
WORKDIR /data
RUN apk update && 
apk upgrade && 
apk add git bash
RUN go get github.com/aatarasoff/apistress && 
go install github.com/aatarasoff/apistress
CMD [ "apistress" ]
Dockerfile. Инструкции
57
FROM golang:1.7-alpine
MAINTAINER aatarasoff@gmail.com
ARG maindir=/data
VOLUME $maindir
WORKDIR $maindir
RUN apk update && apk upgrade && apk add git bash
RUN go get github.com/aatarasoff/apistress && 
go install github.com/aatarasoff/apistress
CMD [ "apistress" ]
Dockerfile. Переменные
58
docker build … && docker push …
59
publishing {
publications {
mavenJava(MavenPublication) {
artifactId 'spring-one-nio-autoconfigure'
from components.java
artifact sourceJar {
classifier "sources"
}
}
}
}
Gradle. DSL
60
compile(ivyDependencies(projectDir, 'runtime'))
def ivyDependencies(ivyPath, conf) {
def dep = []
def ivyModule = new XmlParser().parse(file("${ivyPath}/ivy.xml"))
ivyModule.dependencies.dependency.each
dep.add([group: (null == it.@org ? 'ru.odnoklassniki' : it.@org),
name: it.@name,
version: it.@rev,
configuration: (it.@conf =~ /->(w+)/)[0][1]])
}
return dep
}
Gradle. Код как он есть
61
<macrodef name="docker-build-image" description="Build docker image">
<attribute name=" buildcommand"
default="build -t @{repo}/@{image}:@{tag} ."/>
<sequential>
<exec executable="docker">
<arg line=" @{buildcommand} "/>
</exec>
</sequential>
</macrodef>
И даже в Ant-е есть жизнь
62
./gradlew build test ant-docker-build-image publish
63
Фреймворки
для автоматизации
● Ant + Ivy
● Maven
● Gradle
● Docker
● npm
● ...
64
Что получили
● Сборка это код
○ XML
○ DSL
○ Groovy
○ etc
● Системы сборки не только для
сборки
65
Ликвидация багов
66
Unit tests API tests Stress tests UI tests
67
Unit tests API tests Stress tests UI tests
TDD
68
goss --vars vars.yaml validate
69
port:
tcp:5601:
listening: true
ip:
- 0.0.0.0
service:
mesosd:
enabled: true
running: true
goss.yml
70
port:
tcp:5601:
listening: true
ip:
- 0.0.0.0
service:
mesosd:
enabled: true
running: true
goss.yml
71
port:
tcp:5601:
listening: true
ip:
- 0.0.0.0
service:
mesosd:
enabled: true
running: true
goss.yml
72
Unit tests API tests Stress tests UI tests
BDD Specs
73
def "Return error code 400, if User-ID header is not presented"() {
given:
def request = post("/rent")
when:
def result = this.mvc.perform(request)
then:
result.andExpect(status().isBadRequest())
.andDo(document("rent-user-id-is-absent"))
}
Дружелюбный BDD
74
def "Return error code 400, if User-ID header is not presented"() {
given:
def request = post("/rent")
when:
def result = this.mvc.perform(request)
then:
result.andExpect( status().isBadRequest())
.andDo(document("rent-user-id-is-absent"))
}
Простые проверки
75
Unit tests API tests Stress tests UI tests
JMeter, wrk,
vegeta
76
Unit tests API tests Stress tests UI tests
JMeter
production
77
> config | run command
> echo $?
{0,1}
0 - success
1 - error
78
Экспресс-тест
{
"baseUrl": "http://host:9000/rent-service",
"tests": [
{
"rps": 10,
"duration": 5,
"target": {
"method": "GET",
"path": "/rent",
"headers": [
...
]
},
"sla": {
"latency": 1000,
"successRate": 99.999
}
},
... ]
}
config.json
79
{
"baseUrl": "http://host:9000/rent-service",
"tests": [
{
"rps": 10,
"duration": 5,
"target": {
"method": "GET",
"path": "/rent",
"headers": [
...
]
},
"sla": {
"latency": 1000,
"successRate": 99.999
}
},
... ]
}
config.json
80
{
"baseUrl": "http://host:9000/rent-service",
"tests": [
{
"rps": 10,
"duration": 5,
"target": {
"method": "GET",
"path": "/rent",
"headers": [
...
]
},
"sla": {
"latency": 1000,
"successRate": 99.999
}
},
... ]
}
config.json
81
cat config.json | docker run -i apistress -config=stdin
82
Где-то мы такое видели
https://github.com/aatarasoff/apistress
Requests [total, rate] 50, 10.20
Duration [total, attack, wait] 5.022872793s, 4.899943287s, 122.929506ms
Latencies [mean, 50, 95, 99, max] 143.772484ms, ..., 290.101831ms
Bytes In [total, mean] 4842, 96.84
Bytes Out [total, mean] 950, 19.00
Success [ratio] 100.00%
Status Codes [code:count] 200:50
Error Set:
Test#1
83
Requests [total, rate] 50, 10.20
Duration [total, attack, wait] 5.022872793s, 4.899943287s, 122.929506ms
Latencies [mean, 50, 95, 99, max] 143.772484ms, ..., 290.101831ms
Bytes In [total, mean] 4842, 96.84
Bytes Out [total, mean] 950, 19.00
Success [ratio] 100.00%
Status Codes [code:count] 200:50
Error Set:
Test#1
84
attacker := vegeta.NewAttacker()
var metrics vegeta.Metrics
for res := range attacker.Attack(targeter, rate, duration) {
metrics.Add(res)
}
metrics.Close()
if metrics.Success*100 < test.SLA.SuccessRate {
os.Exit(1)
}
if metrics.Latencies.P99() > SLA.Latency*time.Millisecond.Nanoseconds() {
os.Exit(1)
}
Немного go-кода
85
attacker := vegeta.NewAttacker()
var metrics vegeta.Metrics
for res := range attacker.Attack( targeter, rate, duration) {
metrics.Add(res)
}
metrics.Close()
if metrics.Success*100 < test.SLA.SuccessRate {
os.Exit(1)
}
if metrics.Latencies.P99() > SLA.Latency*time.Millisecond.Nanoseconds() {
os.Exit(1)
}
Майним метрики
86
attacker := vegeta.NewAttacker()
var metrics vegeta.Metrics
for res := range attacker.Attack(targeter, rate, duration) {
metrics.Add(res)
}
metrics.Close()
if metrics.Success*100 < test.SLA.SuccessRate {
os.Exit(1)
}
if metrics.Latencies.P99() > SLA.Latency*time.Millisecond.Nanoseconds() {
os.Exit(1)
}
Не слишком ли много ошибок?
87
attacker := vegeta.NewAttacker()
var metrics vegeta.Metrics
for res := range attacker.Attack(targeter, rate, duration) {
metrics.Add(res)
}
metrics.Close()
if metrics.Success*100 < test.SLA.SuccessRate {
os.Exit(1)
}
if metrics.Latencies.P99() > SLA.Latency*time.Millisecond.Nanoseconds() {
os.Exit(1)
}
Уложились ли по времени?
88
> cat config.json | docker run -i apistress -config=stdin
> echo $?
0
89
Код возврата
Requests [total, rate] 200, 10.05
Duration [total, attack, wait] 23.04784s, 19.899754743s, 3.148093811s
Latencies [mean, 50, 95, 99, max] 3.023677499s, ..., 11.832287083s
Bytes In [total, mean] 6874, 34.37
Bytes Out [total, mean] 1349, 6.75
Success [ratio] 35.50%
Status Codes [code:count] 0:129 200:71
Error Set:
Get http://host:9000/rent-service/rent: EOF
Get http://host:9000/rent-service/rent: http: server closed idle connection
...
Test#2
90
> cat config.json | docker run -i apistress -config=stdin
> echo $?
1
91
Код возврата
Unit tests API tests Stress tests UI tests
Selenium,
Selenide
92
Что получили
● Все тестовые сценарии в коде
● Можно встроить в процесс сборки
или доставки ПО
● Если хотите, то можно
генерировать отчёты для разбора
полётов
93
Эксперименты
94
Code Branches
95
if / switch
Code Branches
96
if / switch
DI
Code Branches
97
if / switch
DI
API v2
ISupplier<String, Ctx> srcsetSupplier = (ctx) -> {
if (configuration. isDoubleDensityAvatarsEnabled(user.getModel())) {
String link = imageSrc.getModel();
return linkBuilder.createSourceSetLink(link);
}
return "";
};
Очень простой эксперимент
98
Code Branches
One server or
partition
99
//by partition
app.photos.doubleDensityAvatarsEnabled: 0
Step#1
Code Branches
One server or
partition
Part of servers
or partitions
100
//by partition
app.photos.doubleDensityAvatarsEnabled: 0,4,7-9
Step#1 Step#2
Code Branches
One server or
partition
Part of servers
or partitions
All servers or
partitions
101
//by partition
app.photos.doubleDensityAvatarsEnabled: ALL
Step#1 Step#2 Step#3
//step#1
app.photos.doubleDensityAvatarsEnabled: 0
//step#2
app.photos.doubleDensityAvatarsEnabled: 0,4,7-9
//step#3
app.photos.doubleDensityAvatarsEnabled: ALL
102
Очень простой эксперимент
No one
One server or
partition
Part of servers
or partitions
All servers or
partitions
103
monitor
Step#1 Step#2 Step#3Step#0
104
Что хотим?
ansible-playbook -i {dev,test,prod}-env exp.yml --tags stepN
105
Абстракция
- name: update properties
uri:
url: "http://{{ pms_host }}/api/conf/update"
method: POST
user: "{{ username }}"
password: "{{ password }}"
force_basic_auth: yes
body:
applicationName: "{{ application_name }}"
propertyName: "{{ item.value.name }}"
propertyValue: "{{ item.value.value }}"
body_format: json
status_code: 200
headers:
Content-Type: "application/json"
with_dict: "{{ properties }}"
106
Координаты
- name: update properties
uri:
url: "http://{{ pms_host }}/api/conf/update"
method: POST
user: "{{ username }}"
password: "{{ password }}"
force_basic_auth: yes
body:
applicationName: "{{ application_name }}"
propertyName: "{{ item.value.name }}"
propertyValue: "{{ item.value.value }}"
body_format: json
status_code: 200
headers:
Content-Type: "application/json"
with_dict: "{{ properties }}"
107
Вкатываем настройки
- name: update properties
uri:
url: "http://{{ pms_host }}/api/conf/update"
method: POST
user: "{{ username }}"
password: "{{ password }}"
force_basic_auth: yes
body:
applicationName: "{{ application_name }}"
propertyName: "{{ item.value.name }}"
propertyValue: "{{ item.value.value }}"
body_format: json
status_code: 200
headers:
Content-Type: "application/json"
with_dict: "{{ properties }}"
108
Проверяем корректность
- name: update properties
uri:
url: "http://{{ pms_host }}/api/conf/update"
method: POST
user: "{{ username }}"
password: "{{ password }}"
force_basic_auth: yes
body:
applicationName: "{{ application_name }}"
propertyName: "{{ item.value.name }}"
propertyValue: "{{ item.value.value }}"
body_format: json
status_code: 200
headers:
Content-Type: "application/json"
with_dict: "{{ properties }}"
109
Step#0
- hosts: local
vars:
application_name: odnoklassniki-web
props:
doubleDensityAvatarsEnabled:
name: "app.photos.doubleDensityAvatarsEnabled"
value: ""
roles:
- { name: pms, properties: "{{ props }}" }
110
Step#0
- hosts: local
vars:
application_name: odnoklassniki-web
props:
doubleDensityAvatarsEnabled:
name: "app.photos.doubleDensityAvatarsEnabled"
value: ""
roles:
- { name: pms, properties: "{{ props }}" }
111
Step#1
- hosts: local
vars:
application_name: odnoklassniki-web
props:
doubleDensityAvatarsEnabled:
name: "app.photos.doubleDensityAvatarsEnabled"
value: "0"
roles:
- { name: pms, properties: "{{ props }}" }
112
Step#2
- hosts: local
vars:
application_name: odnoklassniki-web
props:
doubleDensityAvatarsEnabled:
name: "app.photos.doubleDensityAvatarsEnabled"
value: "0,4,7-9"
roles:
- { name: pms, properties: "{{ props }}" }
113
Step#3
- hosts: local
vars:
application_name: odnoklassniki-web
props:
doubleDensityAvatarsEnabled:
name: "app.photos.doubleDensityAvatarsEnabled"
value: "ALL"
roles:
- { name: pms, properties: "{{ props }}" }
114
exp.yml
---
- include: step0.yml
tags:
- step0
- cleanup
- include: step1.yml
tags: step1
- include: step2.yml
tags: step2
- include: step3.yml
tags:
- step3
- complete
Что получили
● Эксперименты хранятся в git-
репозитории
● Можно применить любой шаг в
любой момент времени на любой
среде
● Можно встроить в пайплайн
доставки
115
Кододокументация
116
Analyst, PM Developer Tester Docs
Word, PDF...
117
Analyst, PM Developer Tester Docs
Word, PDF... Code + Tests
118
Analyst, PM Developer Tester Docs
Word, PDF... Code + Tests Test cases
119
Analyst, PM Developer Tester Docs :(
Word, PDF... Code + Tests Test cases
120
Analyst, PM Developer Tester Docs :)
Markdown/Asciidoctor
Docs :)
121
= Hippo Rent Service
This is documentation for Open API of our hippo renting service
== Methods
=== Rent
==== Request specification
===== Headers
//тут опишем http-заголовки
===== Example
//а здесь будут примеры вызова
==== Response specification
===== Response fields
//здесь описание полей ответа
===== Example
//ну и пример того, что вообще ожидать в ответе
Вот такой документ
122
./gradlew ... asciidoc publishDocs
123
Компиляция документа
def "Rent a hippo"() {
given:
def request = post("/rent").header("User-ID", "aatarasoff")
when:
def result = this.mvc.perform(request)
then:
result.andExpect(status().isOk())
.andDo(document(
"rent-hippo",
preprocessResponse(prettyPrint()),
requestHeaders(
headerWithName("User-ID").description("User unique identifier")),
responseFields(
fieldWithPath("hippoRemain").description("Hippo remain count"),
fieldWithPath("parrot_fee").description("Fee in virtual parrots"),
fieldWithPath("ins").description("Insurance number. Yeah, we sell it"),
fieldWithPath("hash").description("Blockchain block hash"))
))
}
…и снова тесты
124
def "Rent a hippo"() {
given:
def request = post("/rent").header("User-ID", "aatarasoff")
when:
def result = this.mvc.perform(request)
then:
result.andExpect(status().isOk())
.andDo(document(
"rent-hippo",
preprocessResponse(prettyPrint()),
requestHeaders(
headerWithName("User-ID").description("User unique identifier")),
responseFields(
fieldWithPath("hippoRemain").description("Hippo remain count"),
fieldWithPath("parrot_fee").description("Fee in virtual parrots"),
fieldWithPath("ins").description("Insurance number. Yeah, we sell it"),
fieldWithPath("hash").description("Blockchain block hash"))
))
}
А не документация ли это?
125
document(
"rent-hippo",
preprocessResponse(prettyPrint()),
requestHeaders(
headerWithName("User-ID").description("User unique identifier")),
responseFields(
fieldWithPath("hippoRemain").description("Hippo remain count"),
fieldWithPath("parrot_fee").description("Fee in virtual parrots"),
fieldWithPath("ins").description("Insurance number. Yeah, we sell
it"),
fieldWithPath("hash").description("Blockchain block hash"))
)
Имя сниппета
126
document(
"rent-hippo",
preprocessResponse(prettyPrint()),
requestHeaders(
headerWithName("User-ID").description("User unique identifier")),
responseFields(
fieldWithPath("hippoRemain").description("Hippo remain count"),
fieldWithPath("parrot_fee").description("Fee in virtual parrots"),
fieldWithPath("ins").description("Insurance number. Yeah, we sell
it"),
fieldWithPath("hash").description("Blockchain block hash"))
)
Тестируем заголовки
127
document(
"rent-hippo",
preprocessResponse(prettyPrint()),
requestHeaders(
headerWithName("User-ID").description("User unique identifier")),
responseFields(
fieldWithPath("hippoRemain").description("Hippo remain count"),
fieldWithPath("parrot_fee").description("Fee in virtual parrots"),
fieldWithPath("ins").description("Insurance number. Yeah, we sell it"),
fieldWithPath("hash").description("Blockchain block hash"))
)
Тестируем поля ответа
128
generated-snippets
rent-hippo
curl-request.adoc
http-request.adoc
http-response.adoc
httpie-request.adoc
request-headers.adoc
response-fields.adoc
Получаем сниппеты
129
= Hippo Rent Service
This is documentation for Open API of our hippo renting service
== Methods
=== Rent
==== Request specification
===== Headers
include::{snippets}/rent-hippo/request-headers.adoc[]
===== Example
include::{snippets}/rent-hippo/http-request.adoc[]
==== Response specification
===== Response fields
include::{snippets}/rent-hippo/response-fields.adoc[]
===== Example
include::{snippets}/rent-hippo/http-response.adoc[]
Вставляем их в документ
130
= Hippo Rent Service
This is documentation for Open API of our hippo renting
service
== Methods
=== Rent
==== Request specification
===== Headers
include::{snippets}/rent-hippo/request-headers.adoc[]
===== Example
include::{snippets}/rent-hippo/http-request.adoc[]
==== Response specification
===== Response fields
include::{snippets}/rent-hippo/response-fields.adoc[]
===== Example
include::{snippets}/rent-hippo/http-response.adoc[]
131
132
Что получили?
● Документация как код
○ лежит в репозитории с кодом
○ встроена в цикл сборки
○ рендерится в html, pdf и т.д.
○ почти всегда актуальна
● Синергия с тестами
133
Инфракод
134
Hardware
Containers
Application
PaaS
Mesos/Kubernetes/Private cloud
135
Hardware + OS System Libs PaaS Application
136
Hardware + OS System Libs PaaS Application
Ansible
137
Hardware + OS System Libs PaaS Application
Ansible
Puppet/Chef
138
Ansible. Inventory
[datacenter]
api-server-1
api-server-2
api-server-3
[datacenter:vars]
magicvar = 42
139
Ansible. Playbook
- hosts: datacenter
roles:
- role: docker
- role: rsyslog
140
ansible-playbook -i dc1 bootstrap.yml
141
Без комментариев
Hardware + OS System Libs PaaS Application
Ansible
142
Hardware + OS System Libs PaaS Application
Ansible
Puppet/Chef
143
Hardware + OS System Libs PaaS Application
Manifest
144
Docker compose
services:
zk:
image: zookeeper
network_mode: bridge
ports:
- 2181:2181
environment:
ZK_CONFIG: tickTime=2000,initLimit=10,clientPort=2181
ZK_ID: 1
145
Docker compose
services:
zk:
image: zookeeper
network_mode: bridge
ports:
- 2181:2181
environment:
ZK_CONFIG: tickTime=2000,initLimit=10,clientPort=2181
ZK_ID: 1
146
Конфигурация сервиса
services:
zk:
image: zookeeper
network_mode: bridge
ports:
- 2181:2181
environment:
ZK_CONFIG: tickTime=2000,initLimit=10,clientPort=2181
ZK_ID: 1
147
Mesos/Marathon
{
"id": "/api/rent-service",
"cpus": 1,
"mem": 1024,
"instances": 3,
"container": {
"docker": {
"image": "rent-service:0.0.1",
"portMappings": [
{
"containerPort": 8080
}
]
}
}
}
148
curl -X POST ... http://marathon/v2/apps?force=true
149
Современный деплоймент
Конфигурация приложений
https://your_repo/rent-service-config/routes.yml
routes:
payment:
path: /payment-service/**
serviceId: payment-service
150
Ещё конфигурация
● Zookeeper
● Consul
● Vault
● configo
● ...
151
configo
152
docker run 
-e CONFIGO_SOURCE_0='{"type": "http", "format": "yaml", "url":
"https://my.server.com/common.yaml"}' 
rent-service
//внутри приложения
getEnvironmentVariable("MY_ENV_VAR")
https://github.com/bsideup/configo
configo
153
docker run 
-e CONFIGO_SOURCE_0='{"type": "http", "format": "yaml", "url":
"https://my.server.com/common.yaml"}' 
-e CONFIGO_SOURCE_1='{"type" : "consul",
"address": "consul.master:8500",
"prefix" : "common"}' 
rent-service
//внутри приложения
getEnvironmentVariable("MY_ENV_VAR")
https://github.com/bsideup/configo
Что получили?
● Инфрастуктура может быть легко
описана в виде кода
● Деплоймент и конфигурация
приложений в виде конфигов и
манифестов
154
Неубиваемый CI
155
156
Install Master
Configure
Slaves
157
Install Master
Configure
Slaves
Ansible
158
Install Master
Configure
Slaves
Ansible
Jenkins Docker Cloud plugin
<——— Хост с докером
<——— Сколько контейнеров можно запустить
159
Автоконфигурация
<clouds>
{% for group in ['build', 'test', 'production'] %}
{% for node in groups[group + '-slaves'] %}
<com.github.kostyasha.yad.DockerCloud plugin="yet-another-docker-plugin@0.1.0-rc31">
<name>{{ node }}</name>
...
<templates>
<com.github.kostyasha.yad.DockerSlaveTemplate>
<id>mycloud-template</id>
<dockerContainerLifecycle>
<image>{{ group }}-jenkins-slave</image>
...
</templates>
<connector>
<serverUrl>tcp://{{ node.hostname }}:2375</serverUrl>
<apiVersion>1.20</apiVersion>
</connector>
</com.github.kostyasha.yad.DockerCloud>
{% endfor %}
{% endfor %}
</clouds>
160
Код доставки
161
//checkout and definition stage
node('build') {
// Mark the code checkout 'stage'
stage 'Checkout'
git credentialsId: 'jenkins-git',
url: "${git_url}/${repo}.git"
// Mark build 'stage'
stage 'Build'
sh ('./gradlew clean build final')
}
//next steps
//checkout and definition stage
node('build') {
// Mark the code checkout 'stage'
stage 'Checkout'
git credentialsId: 'jenkins-git',
url: "${git_url}/${repo}.git"
// Mark build 'stage'
stage 'Build'
sh ('./gradlew clean build final')
}
//next steps
//checkout and definition stage
node('build') {
// Mark the code checkout 'stage'
stage 'Checkout'
git credentialsId: 'jenkins-git',
url: "${git_url}/${repo}.git"
// Mark build 'stage'
stage 'Build'
sh ('./gradlew clean build final')
}
//next steps
//checkout and definition stage
node('build') {
// Mark the code checkout 'stage'
stage 'Checkout'
git credentialsId: 'jenkins-git',
url: "${git_url}/${repo}.git"
// Mark build 'stage'
stage 'Build'
sh ('./gradlew clean build final')
}
//next steps
//checkout and definition stage
node('build') {
// Mark the code checkout 'stage'
stage 'Checkout'
git credentialsId: 'jenkins-git',
url: "${git_url}/${repo}.git"
// Mark build 'stage'
stage 'Build'
sh ('./gradlew clean build final')
}
//next steps
//checkout and definition stage
node('build') {
// Mark the code checkout 'stage'
stage 'Checkout'
git credentialsId: 'jenkins-git',
url: "${git_url}/${repo}.git"
// Mark build 'stage'
stage 'Build'
sh ('./gradlew clean build final')
}
//next steps
//deploy artifact to test
node('test') {
sh('ansible-galaxy install -r requirements.yml')
ansiblePlaybook(
credentialsId: 'ansible',
installation: 'ansible',
playbook: 'deploy.yml',
inventory: 'test'
)
}
//deploy artifact to test
node('test') {
sh('ansible-galaxy install -r requirements.yml')
ansiblePlaybook(
credentialsId: 'ansible',
installation: 'ansible',
playbook: 'deploy.yml',
inventory: 'test'
)
}
//deploy artifact to test
node('test') {
sh('ansible-galaxy install -r requirements.yml')
ansiblePlaybook(
credentialsId: 'ansible',
installation: 'ansible',
playbook: 'deploy.yml',
inventory: 'test'
)
}
//deploy artifact to test
node('test') {
sh('ansible-galaxy install -r requirements.yml')
ansiblePlaybook(
credentialsId: 'ansible',
installation: 'ansible',
playbook: 'deploy.yml',
inventory: 'test'
)
}
//deploy artifact to test
node('test') {
sh('ansible-galaxy install -r requirements.yml')
ansiblePlaybook(
credentialsId: 'ansible',
installation: 'ansible',
playbook: 'deploy.yml',
inventory: 'test'
)
}
jiraComment (
issueKey: issue_id,
body: "Artifact has been deployed"
)
node('build') {
def repos = fetchRepos(project)
for (repo in repos) {
build(repo)
}
}
def fetchRepos(String project) {
def url = new URL("https://repo/projects/${project}/repos?limit=1000")
def conn = url.openConnection()
conn.setRequestMethod("GET")
def responseCode = conn.getResponseCode()
final slurper = new groovy.json.JsonSlurper()
def repos = slurper.parse(conn.getInputStream()).values
for (repo in repos) {
if (repo.slug.contains('one-'))
result << repo.slug
}
return result
}
node('build') {
def repos = fetchRepos(project)
for (repo in repos) {
build(repo)
}
}
def fetchRepos(String project) {
def url = new URL("https://repo/projects/${project}/repos?limit=1000")
def conn = url.openConnection()
conn.setRequestMethod("GET")
def responseCode = conn.getResponseCode()
final slurper = new groovy.json.JsonSlurper()
def repos = slurper.parse(conn.getInputStream()).values
for (repo in repos) {
if (repo.slug.contains('one-'))
result << repo.slug
}
return result
}
node('build') {
def repos = fetchRepos(project)
for (repo in repos) {
build(repo)
}
}
def fetchRepos(String project) {
def url = new URL("https://repo/projects/${project}/repos?limit=1000")
def conn = url.openConnection()
conn.setRequestMethod("GET")
def responseCode = conn.getResponseCode()
final slurper = new groovy.json.JsonSlurper()
def repos = slurper.parse(conn.getInputStream()).values
for (repo in repos) {
if (repo.slug.contains('one-'))
result << repo.slug
}
return result
}
Микросервисы
178
179
Install Master
Configure
Slaves
Create
meta job
Ansible
180
Install Master
Configure
Slaves
Create
meta job
Ansible
cURL
181
Install Master
Configure
Slaves
Create
meta job
Create
pipelines
jobs.each { job ->
pipelineJob("${basePath}/${job}") {
//define SCM
definition {
cps {
script(readFileFromWorkspace('pipeline-template.groovy'))
sandbox()
}
}
}
}
JobDSL plugin
182
jobs.each { job ->
pipelineJob("${basePath}/${job}") {
//define SCM
definition {
cps {
script(readFileFromWorkspace('pipeline-template.groovy'))
sandbox()
}
}
}
}
JobDSL plugin
183
jobs.each { job ->
pipelineJob("${basePath}/${job}") {
//define SCM
definition {
cps {
script(readFileFromWorkspace('pipeline-template.groovy'))
sandbox()
}
}
}
}
JobDSL plugin
184
185
Install Master
Configure
Slaves
Create
meta job
Create
pipelines
git
ansible-playbook -i jenkins-for-my-team jenkins.yml
186
Это последний раз
Что получили?
● Пайплайн как код
● Неубиваемый CI
○ без бэкапов
○ всё хранится как код
○ разворачивается за X минут
187
Development Testing Deployment
Post
Deployment
188
> ./gradlew build test
Development Testing Deployment
Post
Deployment
189
> ./gradlew integrationTest publishDocs
Development Testing Deployment
Post
Deployment
190
> ansible-playbook -i env deploy.yml
Development Testing Deployment
Post
Deployment
191
> ansible-playbook -i prod exp.yml
Development Testing Deployment
Post
Deployment
192
Delivery Pipeline
193
Позитивные выводы
● Почти любой процесс можно
формализовать, представить в
виде кода и автоматизировать
● Мы все пишем код, хотя можем
думать, что это не так
● Рано или поздно всё превращается
в код
194
Trade-offs
● Необходимы как разовые
“капиталовложения”, так и
постоянные затраты ресурсов
● Могут потребоваться изменения в
архитектуре
● Требует дисциплины и более
высокой квалификации
специалистов
195
Спасибо, что выбрали красную
@aatarasoff
@aatarasoff
@aatarasoff
QA

Más contenido relacionado

La actualidad más candente

Java EE 6 CDI Integrates with Spring & JSF
Java EE 6 CDI Integrates with Spring & JSFJava EE 6 CDI Integrates with Spring & JSF
Java EE 6 CDI Integrates with Spring & JSFJiayun Zhou
 
OrientDB - The 2nd generation of (multi-model) NoSQL
OrientDB - The 2nd generation of  (multi-model) NoSQLOrientDB - The 2nd generation of  (multi-model) NoSQL
OrientDB - The 2nd generation of (multi-model) NoSQLRoberto Franchini
 
Spring & Hibernate
Spring & HibernateSpring & Hibernate
Spring & HibernateJiayun Zhou
 
How and Why Prometheus' New Storage Engine Pushes the Limits of Time Series D...
How and Why Prometheus' New Storage Engine Pushes the Limits of Time Series D...How and Why Prometheus' New Storage Engine Pushes the Limits of Time Series D...
How and Why Prometheus' New Storage Engine Pushes the Limits of Time Series D...Docker, Inc.
 
Javascript TDD with Jasmine, Karma, and Gulp
Javascript TDD with Jasmine, Karma, and GulpJavascript TDD with Jasmine, Karma, and Gulp
Javascript TDD with Jasmine, Karma, and GulpAll Things Open
 
Taking Jenkins Pipeline to the Extreme
Taking Jenkins Pipeline to the ExtremeTaking Jenkins Pipeline to the Extreme
Taking Jenkins Pipeline to the Extremeyinonavraham
 
Inria Tech Talk : Comment améliorer la qualité de vos logiciels avec STAMP
Inria Tech Talk : Comment améliorer la qualité de vos logiciels avec STAMPInria Tech Talk : Comment améliorer la qualité de vos logiciels avec STAMP
Inria Tech Talk : Comment améliorer la qualité de vos logiciels avec STAMPStéphanie Roger
 
Composable and streamable Play apps
Composable and streamable Play appsComposable and streamable Play apps
Composable and streamable Play appsYevgeniy Brikman
 
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é
 
Cool JVM Tools to Help You Test
Cool JVM Tools to Help You TestCool JVM Tools to Help You Test
Cool JVM Tools to Help You TestSchalk Cronjé
 
Testcontainers - Geekout EE 2017 presentation
Testcontainers - Geekout EE 2017 presentationTestcontainers - Geekout EE 2017 presentation
Testcontainers - Geekout EE 2017 presentationRichard North
 
Gradle in 45min - JBCN2-16 version
Gradle in 45min - JBCN2-16 versionGradle in 45min - JBCN2-16 version
Gradle in 45min - JBCN2-16 versionSchalk Cronjé
 
10 Cool Facts about Gradle
10 Cool Facts about Gradle10 Cool Facts about Gradle
10 Cool Facts about GradleEvgeny Goldin
 
Take Control of your Integration Testing with TestContainers
Take Control of your Integration Testing with TestContainersTake Control of your Integration Testing with TestContainers
Take Control of your Integration Testing with TestContainersNaresha K
 
Java Libraries You Can’t Afford to Miss
Java Libraries You Can’t Afford to MissJava Libraries You Can’t Afford to Miss
Java Libraries You Can’t Afford to MissAndres Almiray
 
Cool Jvm Tools to Help you Test - Aylesbury Testers Version
Cool Jvm Tools to Help you Test - Aylesbury Testers VersionCool Jvm Tools to Help you Test - Aylesbury Testers Version
Cool Jvm Tools to Help you Test - Aylesbury Testers VersionSchalk Cronjé
 

La actualidad más candente (20)

Java EE 6 CDI Integrates with Spring & JSF
Java EE 6 CDI Integrates with Spring & JSFJava EE 6 CDI Integrates with Spring & JSF
Java EE 6 CDI Integrates with Spring & JSF
 
OrientDB - The 2nd generation of (multi-model) NoSQL
OrientDB - The 2nd generation of  (multi-model) NoSQLOrientDB - The 2nd generation of  (multi-model) NoSQL
OrientDB - The 2nd generation of (multi-model) NoSQL
 
Gradle in 45min
Gradle in 45minGradle in 45min
Gradle in 45min
 
Springを用いた社内ライブラリ開発
Springを用いた社内ライブラリ開発Springを用いた社内ライブラリ開発
Springを用いた社内ライブラリ開発
 
Spring & Hibernate
Spring & HibernateSpring & Hibernate
Spring & Hibernate
 
How and Why Prometheus' New Storage Engine Pushes the Limits of Time Series D...
How and Why Prometheus' New Storage Engine Pushes the Limits of Time Series D...How and Why Prometheus' New Storage Engine Pushes the Limits of Time Series D...
How and Why Prometheus' New Storage Engine Pushes the Limits of Time Series D...
 
Javascript TDD with Jasmine, Karma, and Gulp
Javascript TDD with Jasmine, Karma, and GulpJavascript TDD with Jasmine, Karma, and Gulp
Javascript TDD with Jasmine, Karma, and Gulp
 
GradleFX
GradleFXGradleFX
GradleFX
 
Taking Jenkins Pipeline to the Extreme
Taking Jenkins Pipeline to the ExtremeTaking Jenkins Pipeline to the Extreme
Taking Jenkins Pipeline to the Extreme
 
Inria Tech Talk : Comment améliorer la qualité de vos logiciels avec STAMP
Inria Tech Talk : Comment améliorer la qualité de vos logiciels avec STAMPInria Tech Talk : Comment améliorer la qualité de vos logiciels avec STAMP
Inria Tech Talk : Comment améliorer la qualité de vos logiciels avec STAMP
 
Composable and streamable Play apps
Composable and streamable Play appsComposable and streamable Play apps
Composable and streamable Play apps
 
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
 
Cool JVM Tools to Help You Test
Cool JVM Tools to Help You TestCool JVM Tools to Help You Test
Cool JVM Tools to Help You Test
 
Gradle Introduction
Gradle IntroductionGradle Introduction
Gradle Introduction
 
Testcontainers - Geekout EE 2017 presentation
Testcontainers - Geekout EE 2017 presentationTestcontainers - Geekout EE 2017 presentation
Testcontainers - Geekout EE 2017 presentation
 
Gradle in 45min - JBCN2-16 version
Gradle in 45min - JBCN2-16 versionGradle in 45min - JBCN2-16 version
Gradle in 45min - JBCN2-16 version
 
10 Cool Facts about Gradle
10 Cool Facts about Gradle10 Cool Facts about Gradle
10 Cool Facts about Gradle
 
Take Control of your Integration Testing with TestContainers
Take Control of your Integration Testing with TestContainersTake Control of your Integration Testing with TestContainers
Take Control of your Integration Testing with TestContainers
 
Java Libraries You Can’t Afford to Miss
Java Libraries You Can’t Afford to MissJava Libraries You Can’t Afford to Miss
Java Libraries You Can’t Afford to Miss
 
Cool Jvm Tools to Help you Test - Aylesbury Testers Version
Cool Jvm Tools to Help you Test - Aylesbury Testers VersionCool Jvm Tools to Help you Test - Aylesbury Testers Version
Cool Jvm Tools to Help you Test - Aylesbury Testers Version
 

Destacado

Think Like a 50s Ad Exec & Execute Like a Geek #BeWizard
Think Like a 50s Ad Exec & Execute Like a Geek #BeWizardThink Like a 50s Ad Exec & Execute Like a Geek #BeWizard
Think Like a 50s Ad Exec & Execute Like a Geek #BeWizardLisa Myers
 
Artificial Intelligence or the Brainization of the Economy
Artificial Intelligence or the Brainization of the EconomyArtificial Intelligence or the Brainization of the Economy
Artificial Intelligence or the Brainization of the EconomyWilly Braun
 
Humantalents soft skills training-brochure
Humantalents soft skills training-brochureHumantalents soft skills training-brochure
Humantalents soft skills training-brochureJayadeva de Silva
 
Frameworks We Live By: Design by day-to-day framework development: Multi-para...
Frameworks We Live By: Design by day-to-day framework development: Multi-para...Frameworks We Live By: Design by day-to-day framework development: Multi-para...
Frameworks We Live By: Design by day-to-day framework development: Multi-para...Atsuhiro Kubo
 
Splunk Überblick
Splunk ÜberblickSplunk Überblick
Splunk ÜberblickSplunk
 
Bilmök 2017 - Microsoft Yeni Yesil Yazilim Geliştirme Teknolojileri
Bilmök 2017 - Microsoft Yeni Yesil Yazilim Geliştirme TeknolojileriBilmök 2017 - Microsoft Yeni Yesil Yazilim Geliştirme Teknolojileri
Bilmök 2017 - Microsoft Yeni Yesil Yazilim Geliştirme Teknolojileriİbrahim KIVANÇ
 
A Survey of IT Jobs in the Kingdom of Saudi Arabia 2017
A Survey of IT Jobs in the Kingdom of Saudi Arabia 2017A Survey of IT Jobs in the Kingdom of Saudi Arabia 2017
A Survey of IT Jobs in the Kingdom of Saudi Arabia 2017Hend Al-Khalifa
 
Mr. Ludo Diels IEWP @ 2nd India-EU Water Forum @ World Sustainable Developmen...
Mr. Ludo Diels IEWP @ 2nd India-EU Water Forum @ World Sustainable Developmen...Mr. Ludo Diels IEWP @ 2nd India-EU Water Forum @ World Sustainable Developmen...
Mr. Ludo Diels IEWP @ 2nd India-EU Water Forum @ World Sustainable Developmen...India-EU Water Partnership
 
MongoDB and DigitalOcean Automation with Cloud Manager
MongoDB and DigitalOcean Automation with Cloud ManagerMongoDB and DigitalOcean Automation with Cloud Manager
MongoDB and DigitalOcean Automation with Cloud ManagerJay Gordon
 
Final seminar on its
Final seminar on itsFinal seminar on its
Final seminar on itsMital Damani
 
Dealing with Performance in SharePoint Server
Dealing with Performance in SharePoint ServerDealing with Performance in SharePoint Server
Dealing with Performance in SharePoint ServerJason Warren
 
Schematic diagrams of GPUs' architecture and Time evolution of theoretical FL...
Schematic diagrams of GPUs' architecture and Time evolution of theoretical FL...Schematic diagrams of GPUs' architecture and Time evolution of theoretical FL...
Schematic diagrams of GPUs' architecture and Time evolution of theoretical FL...智啓 出川
 
NV Wim Delvoye blijft winstmachine
NV Wim Delvoye blijft winstmachineNV Wim Delvoye blijft winstmachine
NV Wim Delvoye blijft winstmachineThierry Debels
 
Investeringsprogramma koninklijk paleis in hoogste versnelling
Investeringsprogramma koninklijk paleis in hoogste versnellingInvesteringsprogramma koninklijk paleis in hoogste versnelling
Investeringsprogramma koninklijk paleis in hoogste versnellingThierry Debels
 
ジャパリパークさいかいけーかく
ジャパリパークさいかいけーかくジャパリパークさいかいけーかく
ジャパリパークさいかいけーかくfurandon_pig
 
Delfina Gómez, la candidata desconocida
Delfina Gómez, la candidata desconocidaDelfina Gómez, la candidata desconocida
Delfina Gómez, la candidata desconocidaSusana Gallardo
 
Top 10 Digital Workplace Patterns #spscalgary
Top 10 Digital Workplace Patterns #spscalgaryTop 10 Digital Workplace Patterns #spscalgary
Top 10 Digital Workplace Patterns #spscalgaryKanwal Khipple
 
マイクロソフトが創る未来 医療編 20170401
マイクロソフトが創る未来 医療編 20170401マイクロソフトが創る未来 医療編 20170401
マイクロソフトが創る未来 医療編 20170401Aya Tokura
 
10 Ways to Validate Your Startup Ideas!
10 Ways to Validate Your Startup Ideas!10 Ways to Validate Your Startup Ideas!
10 Ways to Validate Your Startup Ideas!Modern Technolab
 

Destacado (20)

Think Like a 50s Ad Exec & Execute Like a Geek #BeWizard
Think Like a 50s Ad Exec & Execute Like a Geek #BeWizardThink Like a 50s Ad Exec & Execute Like a Geek #BeWizard
Think Like a 50s Ad Exec & Execute Like a Geek #BeWizard
 
Artificial Intelligence or the Brainization of the Economy
Artificial Intelligence or the Brainization of the EconomyArtificial Intelligence or the Brainization of the Economy
Artificial Intelligence or the Brainization of the Economy
 
Head injury
Head injury Head injury
Head injury
 
Humantalents soft skills training-brochure
Humantalents soft skills training-brochureHumantalents soft skills training-brochure
Humantalents soft skills training-brochure
 
Frameworks We Live By: Design by day-to-day framework development: Multi-para...
Frameworks We Live By: Design by day-to-day framework development: Multi-para...Frameworks We Live By: Design by day-to-day framework development: Multi-para...
Frameworks We Live By: Design by day-to-day framework development: Multi-para...
 
Splunk Überblick
Splunk ÜberblickSplunk Überblick
Splunk Überblick
 
Bilmök 2017 - Microsoft Yeni Yesil Yazilim Geliştirme Teknolojileri
Bilmök 2017 - Microsoft Yeni Yesil Yazilim Geliştirme TeknolojileriBilmök 2017 - Microsoft Yeni Yesil Yazilim Geliştirme Teknolojileri
Bilmök 2017 - Microsoft Yeni Yesil Yazilim Geliştirme Teknolojileri
 
A Survey of IT Jobs in the Kingdom of Saudi Arabia 2017
A Survey of IT Jobs in the Kingdom of Saudi Arabia 2017A Survey of IT Jobs in the Kingdom of Saudi Arabia 2017
A Survey of IT Jobs in the Kingdom of Saudi Arabia 2017
 
Mr. Ludo Diels IEWP @ 2nd India-EU Water Forum @ World Sustainable Developmen...
Mr. Ludo Diels IEWP @ 2nd India-EU Water Forum @ World Sustainable Developmen...Mr. Ludo Diels IEWP @ 2nd India-EU Water Forum @ World Sustainable Developmen...
Mr. Ludo Diels IEWP @ 2nd India-EU Water Forum @ World Sustainable Developmen...
 
MongoDB and DigitalOcean Automation with Cloud Manager
MongoDB and DigitalOcean Automation with Cloud ManagerMongoDB and DigitalOcean Automation with Cloud Manager
MongoDB and DigitalOcean Automation with Cloud Manager
 
Final seminar on its
Final seminar on itsFinal seminar on its
Final seminar on its
 
Dealing with Performance in SharePoint Server
Dealing with Performance in SharePoint ServerDealing with Performance in SharePoint Server
Dealing with Performance in SharePoint Server
 
Schematic diagrams of GPUs' architecture and Time evolution of theoretical FL...
Schematic diagrams of GPUs' architecture and Time evolution of theoretical FL...Schematic diagrams of GPUs' architecture and Time evolution of theoretical FL...
Schematic diagrams of GPUs' architecture and Time evolution of theoretical FL...
 
NV Wim Delvoye blijft winstmachine
NV Wim Delvoye blijft winstmachineNV Wim Delvoye blijft winstmachine
NV Wim Delvoye blijft winstmachine
 
Investeringsprogramma koninklijk paleis in hoogste versnelling
Investeringsprogramma koninklijk paleis in hoogste versnellingInvesteringsprogramma koninklijk paleis in hoogste versnelling
Investeringsprogramma koninklijk paleis in hoogste versnelling
 
ジャパリパークさいかいけーかく
ジャパリパークさいかいけーかくジャパリパークさいかいけーかく
ジャパリパークさいかいけーかく
 
Delfina Gómez, la candidata desconocida
Delfina Gómez, la candidata desconocidaDelfina Gómez, la candidata desconocida
Delfina Gómez, la candidata desconocida
 
Top 10 Digital Workplace Patterns #spscalgary
Top 10 Digital Workplace Patterns #spscalgaryTop 10 Digital Workplace Patterns #spscalgary
Top 10 Digital Workplace Patterns #spscalgary
 
マイクロソフトが創る未来 医療編 20170401
マイクロソフトが創る未来 医療編 20170401マイクロソフトが創る未来 医療編 20170401
マイクロソフトが創る未来 医療編 20170401
 
10 Ways to Validate Your Startup Ideas!
10 Ways to Validate Your Startup Ideas!10 Ways to Validate Your Startup Ideas!
10 Ways to Validate Your Startup Ideas!
 

Similar a Everything as a code

Guide to Node.js: Basic to Advanced
Guide to Node.js: Basic to AdvancedGuide to Node.js: Basic to Advanced
Guide to Node.js: Basic to AdvancedEspeo Software
 
OWASP ZAP Workshop for QA Testers
OWASP ZAP Workshop for QA TestersOWASP ZAP Workshop for QA Testers
OWASP ZAP Workshop for QA TestersJavan Rasokat
 
Madrid JAM limitaciones - dificultades
Madrid JAM limitaciones - dificultadesMadrid JAM limitaciones - dificultades
Madrid JAM limitaciones - dificultadesJavier Delgado Garrido
 
Construire une application JavaFX 8 avec gradle
Construire une application JavaFX 8 avec gradleConstruire une application JavaFX 8 avec gradle
Construire une application JavaFX 8 avec gradleThierry Wasylczenko
 
PuppetDB: A Single Source for Storing Your Puppet Data - PUG NY
PuppetDB: A Single Source for Storing Your Puppet Data - PUG NYPuppetDB: A Single Source for Storing Your Puppet Data - PUG NY
PuppetDB: A Single Source for Storing Your Puppet Data - PUG NYPuppet
 
Our Puppet Story (GUUG FFG 2015)
Our Puppet Story (GUUG FFG 2015)Our Puppet Story (GUUG FFG 2015)
Our Puppet Story (GUUG FFG 2015)DECK36
 
GeeCON 2017 - TestContainers. Integration testing without the hassle
GeeCON 2017 - TestContainers. Integration testing without the hassleGeeCON 2017 - TestContainers. Integration testing without the hassle
GeeCON 2017 - TestContainers. Integration testing without the hassleAnton Arhipov
 
Introduction to Codeigniter
Introduction to Codeigniter Introduction to Codeigniter
Introduction to Codeigniter Zero Huang
 
DevOps Workflow: A Tutorial on Linux Containers
DevOps Workflow: A Tutorial on Linux ContainersDevOps Workflow: A Tutorial on Linux Containers
DevOps Workflow: A Tutorial on Linux Containersinside-BigData.com
 
What to expect from Java 9
What to expect from Java 9What to expect from Java 9
What to expect from Java 9Ivan Krylov
 
[CB20] Vulnerabilities of Machine Learning Infrastructure by Sergey Gordeychik
[CB20] Vulnerabilities of Machine Learning Infrastructure by Sergey Gordeychik[CB20] Vulnerabilities of Machine Learning Infrastructure by Sergey Gordeychik
[CB20] Vulnerabilities of Machine Learning Infrastructure by Sergey GordeychikCODE BLUE
 
.gradle 파일 정독해보기
.gradle 파일 정독해보기.gradle 파일 정독해보기
.gradle 파일 정독해보기경주 전
 
Building Web Apps Sanely - EclipseCon 2010
Building Web Apps Sanely - EclipseCon 2010Building Web Apps Sanely - EclipseCon 2010
Building Web Apps Sanely - EclipseCon 2010Chris Ramsdale
 
Scripting Oracle Develop 2007
Scripting Oracle Develop 2007Scripting Oracle Develop 2007
Scripting Oracle Develop 2007Tugdual Grall
 
Burn your grass with react native
Burn your grass with react nativeBurn your grass with react native
Burn your grass with react nativeEugene Zharkov
 

Similar a Everything as a code (20)

Gradle
GradleGradle
Gradle
 
Guide to Node.js: Basic to Advanced
Guide to Node.js: Basic to AdvancedGuide to Node.js: Basic to Advanced
Guide to Node.js: Basic to Advanced
 
Excelian hyperledger walkthrough-feb17
Excelian hyperledger walkthrough-feb17Excelian hyperledger walkthrough-feb17
Excelian hyperledger walkthrough-feb17
 
OWASP ZAP Workshop for QA Testers
OWASP ZAP Workshop for QA TestersOWASP ZAP Workshop for QA Testers
OWASP ZAP Workshop for QA Testers
 
Madrid JAM limitaciones - dificultades
Madrid JAM limitaciones - dificultadesMadrid JAM limitaciones - dificultades
Madrid JAM limitaciones - dificultades
 
Construire une application JavaFX 8 avec gradle
Construire une application JavaFX 8 avec gradleConstruire une application JavaFX 8 avec gradle
Construire une application JavaFX 8 avec gradle
 
PuppetDB: A Single Source for Storing Your Puppet Data - PUG NY
PuppetDB: A Single Source for Storing Your Puppet Data - PUG NYPuppetDB: A Single Source for Storing Your Puppet Data - PUG NY
PuppetDB: A Single Source for Storing Your Puppet Data - PUG NY
 
Our Puppet Story (GUUG FFG 2015)
Our Puppet Story (GUUG FFG 2015)Our Puppet Story (GUUG FFG 2015)
Our Puppet Story (GUUG FFG 2015)
 
GeeCON 2017 - TestContainers. Integration testing without the hassle
GeeCON 2017 - TestContainers. Integration testing without the hassleGeeCON 2017 - TestContainers. Integration testing without the hassle
GeeCON 2017 - TestContainers. Integration testing without the hassle
 
Introduction to Codeigniter
Introduction to Codeigniter Introduction to Codeigniter
Introduction to Codeigniter
 
DevOps Workflow: A Tutorial on Linux Containers
DevOps Workflow: A Tutorial on Linux ContainersDevOps Workflow: A Tutorial on Linux Containers
DevOps Workflow: A Tutorial on Linux Containers
 
Living with garbage
Living with garbageLiving with garbage
Living with garbage
 
Living With Garbage
Living With GarbageLiving With Garbage
Living With Garbage
 
What to expect from Java 9
What to expect from Java 9What to expect from Java 9
What to expect from Java 9
 
[CB20] Vulnerabilities of Machine Learning Infrastructure by Sergey Gordeychik
[CB20] Vulnerabilities of Machine Learning Infrastructure by Sergey Gordeychik[CB20] Vulnerabilities of Machine Learning Infrastructure by Sergey Gordeychik
[CB20] Vulnerabilities of Machine Learning Infrastructure by Sergey Gordeychik
 
.gradle 파일 정독해보기
.gradle 파일 정독해보기.gradle 파일 정독해보기
.gradle 파일 정독해보기
 
Building Web Apps Sanely - EclipseCon 2010
Building Web Apps Sanely - EclipseCon 2010Building Web Apps Sanely - EclipseCon 2010
Building Web Apps Sanely - EclipseCon 2010
 
Nashorn
NashornNashorn
Nashorn
 
Scripting Oracle Develop 2007
Scripting Oracle Develop 2007Scripting Oracle Develop 2007
Scripting Oracle Develop 2007
 
Burn your grass with react native
Burn your grass with react nativeBurn your grass with react native
Burn your grass with react native
 

Más de Aleksandr Tarasov

Cocktail of Environments. How to Mix Test and Development Environments and St...
Cocktail of Environments. How to Mix Test and Development Environments and St...Cocktail of Environments. How to Mix Test and Development Environments and St...
Cocktail of Environments. How to Mix Test and Development Environments and St...Aleksandr Tarasov
 
Service Discovery. More that it seems
Service Discovery. More that it seemsService Discovery. More that it seems
Service Discovery. More that it seemsAleksandr Tarasov
 
Continuous Delivery with Jenkins: Lessons Learned
Continuous Delivery with Jenkins: Lessons LearnedContinuous Delivery with Jenkins: Lessons Learned
Continuous Delivery with Jenkins: Lessons LearnedAleksandr Tarasov
 
WILD microSERVICES v2 (JEEConf Edition)
WILD microSERVICES v2 (JEEConf Edition)WILD microSERVICES v2 (JEEConf Edition)
WILD microSERVICES v2 (JEEConf Edition)Aleksandr Tarasov
 
Расширь границы возможного вместе с Gradle
Расширь границы возможного вместе с GradleРасширь границы возможного вместе с Gradle
Расширь границы возможного вместе с GradleAleksandr Tarasov
 
Jbreak 2016: Твой личный Spring Boot Starter
Jbreak 2016: Твой личный Spring Boot StarterJbreak 2016: Твой личный Spring Boot Starter
Jbreak 2016: Твой личный Spring Boot StarterAleksandr Tarasov
 
Хипстеры в энтерпрайзе
Хипстеры в энтерпрайзеХипстеры в энтерпрайзе
Хипстеры в энтерпрайзеAleksandr Tarasov
 
микроСЕРВИСЫ: огонь, вода и медные трубы
микроСЕРВИСЫ: огонь, вода и медные трубымикроСЕРВИСЫ: огонь, вода и медные трубы
микроСЕРВИСЫ: огонь, вода и медные трубыAleksandr Tarasov
 
Joker 2015. WILD microSERVICES
Joker 2015. WILD microSERVICESJoker 2015. WILD microSERVICES
Joker 2015. WILD microSERVICESAleksandr Tarasov
 

Más de Aleksandr Tarasov (10)

Cocktail of Environments. How to Mix Test and Development Environments and St...
Cocktail of Environments. How to Mix Test and Development Environments and St...Cocktail of Environments. How to Mix Test and Development Environments and St...
Cocktail of Environments. How to Mix Test and Development Environments and St...
 
Service Discovery. More that it seems
Service Discovery. More that it seemsService Discovery. More that it seems
Service Discovery. More that it seems
 
Continuous Delivery with Jenkins: Lessons Learned
Continuous Delivery with Jenkins: Lessons LearnedContinuous Delivery with Jenkins: Lessons Learned
Continuous Delivery with Jenkins: Lessons Learned
 
WILD microSERVICES v2 (JEEConf Edition)
WILD microSERVICES v2 (JEEConf Edition)WILD microSERVICES v2 (JEEConf Edition)
WILD microSERVICES v2 (JEEConf Edition)
 
WILD microSERVICES v2
WILD microSERVICES v2WILD microSERVICES v2
WILD microSERVICES v2
 
Расширь границы возможного вместе с Gradle
Расширь границы возможного вместе с GradleРасширь границы возможного вместе с Gradle
Расширь границы возможного вместе с Gradle
 
Jbreak 2016: Твой личный Spring Boot Starter
Jbreak 2016: Твой личный Spring Boot StarterJbreak 2016: Твой личный Spring Boot Starter
Jbreak 2016: Твой личный Spring Boot Starter
 
Хипстеры в энтерпрайзе
Хипстеры в энтерпрайзеХипстеры в энтерпрайзе
Хипстеры в энтерпрайзе
 
микроСЕРВИСЫ: огонь, вода и медные трубы
микроСЕРВИСЫ: огонь, вода и медные трубымикроСЕРВИСЫ: огонь, вода и медные трубы
микроСЕРВИСЫ: огонь, вода и медные трубы
 
Joker 2015. WILD microSERVICES
Joker 2015. WILD microSERVICESJoker 2015. WILD microSERVICES
Joker 2015. WILD microSERVICES
 

Último

Generative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfGenerative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfIngrid Airi González
 
Potential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsPotential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsRavi Sanghani
 
What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfMounikaPolabathina
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .Alan Dix
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsPixlogix Infotech
 
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...AliaaTarek5
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxLoriGlavin3
 
Decarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a realityDecarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a realityIES VE
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfLoriGlavin3
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
Assure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyesAssure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyesThousandEyes
 
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...Wes McKinney
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxLoriGlavin3
 
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentEmixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentPim van der Noll
 
Sample pptx for embedding into website for demo
Sample pptx for embedding into website for demoSample pptx for embedding into website for demo
Sample pptx for embedding into website for demoHarshalMandlekar2
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality AssuranceInflectra
 
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesHow to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesThousandEyes
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxLoriGlavin3
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc
 

Último (20)

Generative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfGenerative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdf
 
Potential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsPotential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and Insights
 
What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdf
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and Cons
 
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
 
Decarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a realityDecarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a reality
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdf
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
Assure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyesAssure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyes
 
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
 
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentEmixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
 
Sample pptx for embedding into website for demo
Sample pptx for embedding into website for demoSample pptx for embedding into website for demo
Sample pptx for embedding into website for demo
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
 
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesHow to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
 

Everything as a code