4. DevOps - Pourquoi ?
○ Des cycles de déploiement plus courts
○ Une mise à disposition de nouvelles fonctionnalités plus
rapidement
○ Des applications ciblées et de qualité pour accroître la
satisfaction cliente
○ Une réduction des coûts et une affectation des ressources
à des tâches à plus haute valeur ajoutée
○ Amélioration de la gouvernance liée à l’automatisation du
tracking et du reporting
9. ○ Spécifications
○ Gestion de code
○ Tests fonctionnels
○ Métriques et gouvernance
○ Construction des livrables
○ Déploiement
○ Tests de performance
Mise en oeuvre de la démarche DevOps
10. Mise en oeuvre de la démarche DevOps
○ Spécifications
○ Gestion de code
○ Tests fonctionnels
○ Métriques et gouvernance
○ Construction des livrables
○ Déploiement
○ Tests de performance
11. DevOps - Behaviour Driven Development
○ Spécifications des User Stories décrites selon :
○ Des exigences
○ En tant que <rôle>
○ Je veux que <fonctionnalité>
○ Afin de <bénéfice>
○ Des scénarios / exemples
○ Given (Etant donné) <un contexte>
○ When (Lorsque) l'utilisateur effectue
certaines <actions>
○ Then (Alors) on doit pouvoir constater
telles <conséquences>
12. DevOps - Behaviour Driven Development - Exigence
○ En tant que client de l’application
○ Je veux pouvoir autoriser une autre application
à accéder à mes informations personnelles
○ Pour pouvoir bénéficier des services proposées
par cette dernière
14. DevOps - Behaviour Driven Development - Spock
def "given a valid client and an authenticated user, when asking for an
authorisation, a valid token should be generated and granted to the client for
the authenticated user and the user agent should be redirected back to the
client using the redirection URI provided by the client and including an
authorisation code” (){
given:
createUser()
request.method = 'POST'
request.setParameter(OAuth.OAUTH_RESPONSE_TYPE, 'code')
request.setParameter(OAuth.OAUTH_CLIENT_ID, CLIENT_ID)
request.setParameter(OAuth.OAUTH_REDIRECT_URI,
URLEncoder.encode('http://localhost/eboutique', 'UTF-8'))
request.setParameter(OAuth.OAUTH_USERNAME, USERNAME)
request.setParameter(OAuth.OAUTH_PASSWORD, PASSWORD)
when:
controller.authorize()
then:
HttpServletResponse.SC_FOUND == response.status
String redirectUrl = response.redirectedUrl
assertNotNull(redirectUrl)
Map<String, String> parameters = parametersAsMap(redirectUrl)
assertNotNull(parameters)
String code = parameters['code']
assertNotNull(code)
Token token = Token.findByClientIdAndValue(CLIENT_ID, code)
assertNotNull(token)
assertTrue(!token.hasExpired())
assertEquals(EXPIRES, token.expiresIn)
User u = User.findByLogin(USERNAME)
assertEquals(u, token.user)
assertTrue(StringUtils.isEmpty(token.scope))
assertTrue(StringUtils.isEmpty(token.state))
}
15. DevOps - Behaviour Driven Development - jbehave
# EmptyFavoritesRepository.story
Scenario: Empty Favorites Repository
Given empty Favorites Repository
When there is nothing added to the repository
Then favorite book is null
public class EmptyRepositorySteps {
private FavoritesRepository repository = new DefaultFavoritesRepository();;
@Given("empty Favorites Repository")
public void givenEmptyFavoritesRepository() {
}
@When("there is nothing added to the repository")
public void whenThereIsNothingAddedToTheRepository() {
}
@Then("favorite book is null")
public void thenFavoriteBookIsNull() {
assertThat(repository.getFavorite(Book.class)).isNull();
}
}
16. DevOps - Behaviour Driven Development - fitnesse
○ Définition sous la forme de tableaux (decision
table) des données en input et des résultats
attendus
17. DevOps - Behaviour Driven Development - fitnesse
○ Développement de fixtures pour appeler
directement le code
public class Division {
private double numerator, denominator;
public void setNumerator(double numerator) {
this.numerator = numerator;
}
public void setDenominator(double denominator) {
this.denominator = denominator;
}
public double quotient() {
return numerator/denominator;
}
}
18. Mise en oeuvre de la démarche DevOps
○ Spécifications
○ Gestion de code
○ Tests fonctionnels
○ Métriques et gouvernance
○ Construction des livrables
○ Déploiement
○ Tests de performance
19. DevOps - Gestion de code - Git flow
○ develop : branche principale des développements
○ features : nouvelles fonctionnalités
○ release : versions déployées sur un serveur de staging
○ master : code déployé en production
○ hotfix : correction de bugs constatés en production
20. ○ Spécifications
○ Gestion de code
○ Tests fonctionnels
○ Métriques et gouvernance
○ Construction des livrables
○ Déploiement
○ Tests de performance
Mise en oeuvre de la démarche DevOps
21. DevOps - Contraintes d’intégration
○ Base de données
○ Intégration avec d’autres SI
○ …
22. DevOps - Mock de base de données - liquibase
○ Définition des base de données supportées, des tables à
créer et du jeu de données à injecter
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog …>
<preConditions>
<dbms type="h2,oracle" />
</preConditions>
<include file="db.changelog-tables.xml"/>
<include file="db.changelog-data.xml"/>
</databaseChangeLog>
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog …>
<property name="now" value="sysdate" dbms=“oracle”/>
…
<changeSet id="1" author="smanciot">
<preConditions onFail="MARK_RAN">
<not><tableExists tableName="EXPORT_RECAPITULATIF_VENTE" /></not>
</preConditions>
<createTable tableName=“EXPORT_RECAPITULATIF_VENTE" …>
</changeSet>
</databaseChangeLog>
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog …>
<changeSet author="smanciot" id="1">
<insert dbms="h2"
tableName=“EXPORT_RECAPITULATIF_VENTE" …>
</changeSet>
</databaseChangeLog>
23. DevOps - Mock de base de données - liquibase
○ Ajout de liquibase dans la chaîne de build (maven)
<plugin>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-maven-plugin</artifactId>
<configuration>
<changeLogFile>db.changelog-master.xml</changeLogFile>
<url>${jdbc.url}</url>
<driver>${jdbc.driver}</driver>
<username>${jdbc.username}</username>
<password>${jdbc.password}</password>
</configuration>
<executions>
<execution>
<phase>process-test-classes</phase>
<goals>
<goal>update</goal>
</goals>
</execution>
</executions>
</plugin>
24. DevOps - Mock de base de données - liquibase
○ Tests sans création d’objets mockés
"all sales imported" should "be updated" in {
val rows: Int = retrieveNumberOfRows(MUT, s"SELECT count(*) FROM
$EXPORT_RECAPITULATIF_VENTE WHERE EXPORTED=0").getOrElse(0)
assert(rows > 0)
import akka.stream.scaladsl.Source
val i = new ImportStreaming(system)
import i._
val sourceUnderTest: Source[Int] =
loadRows(Seq(EXPORT_RECAPITULATIF_VENTE)) via importRows
val future = sourceUnderTest.runFold(0)(_ + _)
val result: Int = Await.result(future, 5*60*1000.millis)
assert(result > 0)
logger.info(s"imported successfully $result rows")
assert(retrieveNumberOfRows(MUT, s"SELECT count(*) FROM
$EXPORT_RECAPITULATIF_VENTE WHERE EXPORTED=0").getOrElse(1) == 0)
}
25. DevOps - Mock de services soap - soapui
○ Définition du service soap à mocker à partir du contrat
d’interface (wsdl)
○ Définition des réponses en fonction des inputs
26. DevOps - Mock de services soap - soapui
○ Ajout de soapui dans la chaine de build (maven)
<plugin>
<groupId>eviware</groupId>
<artifactId>maven-soapui-plugin</artifactId>
<version>4.5.1</version>
<executions>
<execution>
<id>proxySCVD</id>
<phase>process-test-classes</phase>
<goals>
<goal>mock</goal>
</goals>
<configuration>
<projectFile>${project.basedir}/src/test/resources/SCVD-soapui-
project.xml</projectFile>
<port>${soapui.port}</port>
<noBlock>true</noBlock>
</configuration>
</execution>
</executions>
<dependencies …>
</plugin>
29. DevOps - Mock de services rest - Servlet
○ Ajout de jetty dans la chaine de build (maven)
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<configuration>
<webAppSourceDirectory>${project.basedir}/src/test/resources</
webAppSourceDirectory>
<useTestScope>true</useTestScope>
<webApp>
<contextPath>${contextPath}</contextPath>
<descriptor>${project.basedir}/src/test/resources/WEB-INF/web.xml</
descriptor>
</webApp>
<stopKey>stop</stopKey>
<stopPort>${jetty.stopPort}</stopPort>
<systemProperties>
<systemProperty>
<name>jetty.port</name>
<value>${jetty.port}</value>
</systemProperty>
</systemProperties>
</configuration>
<dependencies …>
</plugin>
30. Mise en oeuvre de la démarche DevOps
○ Spécifications
○ Gestion de code
○ Tests fonctionnels
○ Métriques et gouvernance
○ Construction des livrables
○ Déploiement
○ Tests de performance
32. Mise en oeuvre de la démarche DevOps
○ Spécifications
○ Gestion de code
○ Tests fonctionnels
○ Métriques et gouvernance
○ Construction des livrables
○ Déploiement
○ Tests de performance
35. Docker - Valeurs ajoutées
○ Construction rapide, idempotent et automatique d’images
(Dockerfile) pouvant être partagées (docker-registry)
○ Séparation des rôles :
○ Développeur : à la main sur le conteneur
○ Opérationnel : à la main sur le reste
○ gestion des logs
○ gestion des accès distants
○ configuration réseau
○ monitoring
○ …
○ Portabilité
○ Provisioning rapide (Another Union File System)
○ Performance : les avantages d’une VM (isolation des processus,
interface réseau, …) sans les inconvénients (processus exécutés au
sein de l’hôte, pas d’émulation de périphérique)
○ pouvoir notamment monter des jeux de test ou de nouvelles
instances en fonction des besoins
36. Docker - Dockerfile (Exemple)
image de base
variables d’environnement
copie de fichiers
exécution de commandes
points de montage
port(s) d’écoute
commande par défaut
37. Mise en oeuvre de la démarche DevOps
○ Spécifications
○ Gestion de code
○ Tests fonctionnels
○ Métriques et gouvernance
○ Construction des livrables
○ Déploiement
○ Tests de performance
40. Ansible
○ Orchestration et automatisation des tâches
d’administration système
○ provisioning
○ déploiement d’application
41. Ansible - Valeurs ajoutées
○ Simplicité d’exécution : pas besoin de maître ni d’agent sur les
systèmes à administrer (ssh)
○ Mode Push
○ Simplicité d’apprentissage (YAML)
○ Performant : exécution des scripts en parallèle sur les machines
cible
○ Extensible : python
○ DRY : rôles
○ Idempotent : chaque tâche est exécutée en garantissant que le
système cible sur lequel elle s’applique se trouvera dans l’état
désiré post exécution
○ Sécurisé : ansible-vault permet d’encrypter les fichiers de
configuration spécifiques à chaque plate forme.
49. # vi: set ft=ruby :
# All Vagrant configuration is done below. The "2" in Vagrant.configure
# configures the configuration version (we support older styles for
# backwards compatibility). Please don't change it unless you know what
# you're doing.
Vagrant.configure(2) do |config|
config.vm.box_check_update = false
…
config.vm.define "mesos-batch3" do |datalab|
datalab.vm.box = "centos/7"
datalab.vm.hostname = "datalab-mesos-batch3.vm"
datalab.vm.network "private_network", ip:"192.168.33.83"
datalab.vm.synced_folder "./", "/vagrant", disabled:true
datalab.vm.synced_folder "./", "/home/vagrant/sync", disabled:true
datalab.vm.provider "virtualbox" do |vb|
vb.name = "datalab-mesos-batch3"
vb.cpus = 1
vb.memory = 1024
end
datalab.vm.provision :ansible do |ansible|
ansible.inventory_path = "vagrant-inventory.ini"
ansible.playbook = "datalab.yml"
ansible.extra_vars = { user:"vagrant"}
ansible.sudo = true
ansible.limit = 'all'
ansible.verbose = 'vv'
end
end
end
Ansible - Vagrant
box
vm network
provisioning
vagrant inventory
playbook
50. ○ Spécifications
○ Gestion de code
○ Tests fonctionnels
○ Métriques et gouvernance
○ Construction des livrables
○ Déploiement
○ Tests de performance
Mise en oeuvre de la démarche DevOps
51. DevOps - Tests de performance - Gatling
○ Génération des tests à partir d’une archive HTTP,
en utilisant un proxy, un fichier de logs serveur, …
○ Description du comportement des utilisateurs
(pause, rendezVous, exec, …)
○ Injection de données dans les scénarios (csv,
json, jdbc, redis, …)
○ Contrôle de l’injection des utilisateurs
(atOnceUsers, rampUsers, …)
○ Assertions (responseTime, requestsPerSec, …)
○ Vérification des réponses (check)
52. DevOps - Tests de performance - Gatling
○ Génération de métriques
54. Rappel des principaux composants
○ Docker-registry : disposer d’une référentiel privé des images
construites par la plate forme de livraison continue permettant
leur déploiement sur n’importe quel serveur - “build once deploy
anywhere”
○ SonarQube : disposer de métriques permettant de mesurer en
continu la qualité du code produit
○ artifactory / nexus : pouvoir disposer d’un référentiel de
composants permettant de contrôler, stocker et gérer les binaires
produits tout au long du cycle de vie du projet
○ Fitnesse : pouvoir mettre en oeuvre des tests d’acceptance
automatisés et ainsi s’assurer de la conformité du code produit au
regard des fonctionnalités attendues
○ Gatling : pouvoir effectuer des tests de performance
○ Ansible : pouvoir construire les images docker, sécuriser les
déploiements effectués sur chacune des plates forme (avec ou sans
docker) et ainsi pouvoir livrer en continu