03 juillet 2014

NFC, le retour

Après diverses recherches, j'approfondis la question du paiement sans contact et de la sécurisation associée.



Je me base entre autre sur cet article qui explique en détail les différentes sécurités utilisées sur une carte bancaire.

Donc la bande magnétique d'une CB comporte vos infos bancaires, plus un code de contrôle qui est le résultat d'un DES(numéro, expiration, code service, clé secrète banque).

Ce code est lu par tout les lecteurs de piste CB, et peut être rejoué tel quel - sécurité 0 contre la copie, mais aujourd'hui les paiements sur le Net ne sont plus possible sans le code de contrôle visuel.

Le "code de contrôle visuel" est issu du même principe avec un code de service différent. Il permet de vérifier que vous êtes bien en possession de la carte bleue. Il n'est pas en relief et est (sauf chez Amex) imprimé au dos, donc relativement à l'abris. Si vous êtes parano vous pouvez le gratter, comme ça pas de risque en cas de vol.

La puce NFC utilise un code généré dynamiquement (dCVV) ce qui évite de rejouer le même échange NFC comme on pourrait copier une piste magnétique. Ce code n'est donc pas identique à celui qu'on trouve sur la piste magnétique, et ne permet pas de reconstituer une fausse carte bleue sans effort.

Sauf que ... la compatibilité ascendante est nécessaire au niveau des terminaux de paiement, aussi vous pouvez utiliser les données issue d'un échange NFC pour forger une piste magnétique valide (voir cet article - le lien vers la replay demonstration est malheureusement mort). La sécurité est alors basée sur le bon comportement du terminal de paiement (y compris l'appli reliée au dongle Square) qui va rejeté la piste pour code service inattendu. Ou bien la banque qui va savoir que le commerçant X a un lecteur n'acceptant pas le NFC. Bref on voit qu'il y a de possibles failles en choisissant bien chez qui tenter l'escroquerie.

Autre sécurité, la piste magnétique ainsi créé ne pourra servir qu'une seule fois et avant que l'utilisateur de la carte n'ai fait un paiement avec en NFC. Ça doit laisser un peu de temps tout de même pour s'en servir et faire un gros achat, genre envoyer les données collectées frauduleusement à un cousin aux US qui imprime illico un bande magnétique (facile, la clé de votre hotel est faite comme ça) pour s'en servir dans l'heure qui suit ... oui je vois le mal partout :)


Bref, tout n'est pas tout noir, mais c'est tout de même loin d'être tout blanc.


02 juillet 2014

maven/docker jungle

Docker office in San Francisco looks like a Jungle. I'm not sure that's the sole reason to explain profusion of maven-docker plugins in the wild.


Just searching github (I assume nobody uses google code anymore) gives a dozen candidates, some of them being just empty repositories.

So, here is a quick exploration for available plugins. All of them let you run and stop containers for integration test phase.

Alex Collins (https://github.com/alexec/docker-maven-plugin com.alexecollins.docker). 
Let you build a set of containers as part of a maven build (overriding the docker "build" terminology to follow maven "package" one). Uses a proprietary yaml descriptor, and rely on a custom fork (sic) docker-java client library, that doesn't support unix socket (default docker daemon protocol on localhost). 

Wouter Dance (https://github.com/wouterd/docker-maven-plugin net.wouterdanes.docker)
Comparable to Alex plugin but based on it's own REST client library to talk with docker daemon. So require you to choose between local or remote docker - same issue with unix socket.

Eduardo de Vera Toquero (https://github.com/etux/docker-maven-plugin es.devera.maven.plugins)
Just a maven wrapper to Docker commands

Can create a data container with built artifacts, as define by a (mostly standard) maven assembly descriptor, and then mounted into containers. Uses a custom REST client - still no support for unix socket.

Bilgin Ibryam (https://github.com/bibryam/docker-maven-plugin com.ofbizian)
A wrapper to start and stop existing docker images as part of a maven build. No support for unix socket.

Let you add artifact built by maven to an existing base image, and set entrypoint. Typical use-case is you have a generic base image with your app-server runtime, just need to add the application WAR. Can also use a full Dockerfile. Relies on spotify docker client (not sure about unix socket support, seems not implemented).

Vojtěch Juránek is also working on some plugin, but not released yet.

Imaginate Labs (https://github.com/imaginatelabs/docker-maven-plugin) develop an alpha-stage docker/vagrant plugin. Not sure I like such a combination of a VM manager + Docker within a build.


Most of those plugin are just wrappers to run docker, could just be replaced with maven-exec plugin to run equivalent docker commands, and without restriction on docker daemon unix socket. I don't think it's "cleaner" to write such a docker execution as xml in a pom versus just get the right tool executed as-is. This just introduce expectation to get the same result, but actual differences, like lack of unix socket support and/or docker API mismatch.
So, as a resume, none of those plugins make me feel I need one to use docker within my maven project. Spotify and RHuss plugins are the sole one to hack the docker build process and provide some added value: They both try to concile an actual maven packaging workflow with a docker image build.

Make me also think jenkins way to encourage people to contribute on same github organization and contribute vs re-create existing plugin on their own is a good model. Codehaus Mojo was initially designed for this purpose but clearly isn't attractive/flexible enough to embrace developer enthusiasm.

01 juillet 2014

Carte bleue NFC

Après renouvellement de ma carte bleue j'ai découvert qu'elle était équipée d'une antenne NFC, qui permet le payement sans contact. Première surprise, ce paiement se fait sans que je valide quoi que ce soit, ce qui ne m'a pas tellement plu. Mais je suis rassuré en lisant http://www.cartes-bancaires.com/spip.php?rubrique81 :


Puis-je faire une transaction sans contact sans m’en rendre compte ?
Non, il est impossible d’effectuer un paiement sans contact sans le vouloir. En effet, c’est vous qui déclenchez le paiement en approchant votre carte à moins de 3 à 4 cm du terminal du commerçant pour valider le montant inscrit. Au-delà de cette distance votre carte sans contact ne peut-être activée. Vous restez donc maître de vos paiements sans contact. En outre, toute transaction sans contact se conclue par l’émission d’un ticket de 
caisse.
Ah ben s'il y a un ticket de caisse, alors tout va bien.

Seconde surprise, après quelques recherche : les données de ma carte sont envoyées en clair via le protocole sans fil, sans aucune forme de sécurisation. Un peu comme quand le stagiaire vous dit que le mot de passe est sécurisé par encodage Base64, mais en pire.

Donc en gros, les infos de la bande magnétique de la carte sont exposées sans contact a quiconque passe à proximité. Car si le protocole NFC est limité à quelques cm avec une antenne compacte - comme celle intégrée dans la carte bleue - un récepteur bien pensé et bien amplifié doit permettre de capter sans problème depuis le fond d'une poche ou d'un sac à main en profitant de la promiscuité d'un métro à l'heure de pointe. Vous pouvez lire ici une explication détaillée sur les limites techniques de distance en NFC.

On me répond que le débit est limité à 20€, mais là n'est pas le problème (encore que...). En laissant ainsi mes coordonnées bancaires exposées, je permet à un malveillant mais ingénieux bricoleur (avec un tonton dans la mafia) de collecter des données valides pour fabriquer de vraies-fausses cartes.

Et non, tout le monde n'utilise pas la puce de la carte bleue et la validation par code PIN. Allez faire un tour aux USA pour vous en convaincre - ils sont en avance sur pas mal de sujets, mais clairement sur le payement par carte c'est la préhistoire. En 4 jours à San Francisco pendant Google IO, j'ai effectué une dizaine de paiements par carte par seule lecture de la bande magnétique, et même un avec le "fer à repasser" que les moins de 30 ans n'ont sans doute jamais vu.

Une seule fois (sic) on a noté le code de vérification (les fameux trois derniers chiffres au dos). Par ailleurs, le succès de Square qui se base aussi sur la seule bande magnétique est révélateur.

J'ai adopté une solution un peu radicale pour "désactiver" l'antenne NFC (on peut faire plus propre), sinon il parait qu'on peut demander à sa banque un échange contre une carte sans NFC - avec des frais bien évidemment.

Mais bon rassurez-vous, votre forfait de services bancaires inclut une assurance contre utilisation frauduleuse de votre moyen de payement, bien plus utile que de mettre en place une solution techniquement fiable...





30 juin 2014

Debugging a Docker container

So you can run your (put your favorite language/framework here) application within a Docker container, that's cool. Now, how do you debug it ?

This is feedback I got from my colleague Cyrile, trying to port his Tomcat 8 runtime from RUN@Cloud to a Docker-based environment. He use to integrate the tomcat appserver with syslog and capture thread dumps at runtime with a kill -3 signal sent to the JVM.

Few days ago I'd have suggested him to instrument his Docker image with tons of additional diagnostic tools and extra ports, but I've read Jerôme's blog in the meantime.

So, application is running inside a Docker container :

➜ ~  docker run -d dgageot/helloworld
1cbe9740baa45279eb775d2e0df5a12e5807c112ec382b3bdb20695df429854e

I'll use nsenter and Jerôme docker-enter to add a new diagnostic process to my container. Please remember a container is not a classic Virtual Machine, but "just" a group of process sharing a common Linux kernel namespace. nsenter let you add another process to the group, so can be used to attach a new shell session to the running container.

As I'm running boot2docker and this one don't have nsenter pre-installed (it should imho), I'm installing it directly from Jerôme Docker image :

➜  ~ docker run --rm -v /usr/local/bin:/target jpetazzo/nsenter
Unable to find image 'jpetazzo/nsenter' locally
Pulling repository jpetazzo/nsenter
...
Installing nsenter to /target
Installing docker-enter to /target

docker-enter script makes it even easier to use nsenter in a docker context, just need to know the docker image ID. So let's ssh into boot2docker and use this script to access the running container.

➜  ~ boot2docker ssh
Warning: Permanently added '[localhost]:2022' (RSA) to the list of known hosts.
                        ##        .
                  ## ## ##       ==
               ## ## ## ##      ===
           /""""""""""""""""\___/ ===
      ~~~ {~~ ~~~~ ~~~ ~~~~ ~~ ~ /  ===- ~~~
           \______ o          __/
             \    \        __/
              \____\______/
 _                 _   ____     _            _
| |__   ___   ___ | |_|___ \ __| | ___   ___| | _____ _ __
| '_ \ / _ \ / _ \| __| __) / _` |/ _ \ / __| |/ / _ \ '__|
| |_) | (_) | (_) | |_ / __/ (_| | (_) | (__|   <  __/ |
|_.__/ \___/ \___/ \__|_____\__,_|\___/ \___|_|\_\___|_|
boot2docker: 1.0.0
             master : 16013ee - Mon Jun  9 16:33:25 UTC 2014


docker@boot2docker:~$ sudo docker-enter 1cbe9740baa45279
# ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 14:12 ?        00:00:04 java -jar target/hello.jar
root        22     0  0 14:19 ?        00:00:00 -sh
root        25    22  0 14:19 ?        00:00:00 ps -ef

I now can use my favorite diagnostic tools to check application health.
# jstack 1
2014-06-30 14:20:17
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.5-b02 mixed mode):

"Attach Listener" #15 daemon prio=9 os_prio=0 tid=0x00007fbfa0001000 nid=0x25 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

Cool, isn't it ?
As you maybe noticed, this require to be root on host, so for your production server you might consider reading Jerôme's article carefully and consider using the ssh command= option with a dedicated ssh key for production diagnostic.

I'm considering using this exact same mechanism in a Jenkins plugin so user can provide arbitrary image for build environment, without requirement for a sshd server (like docker plugin does).


13 juin 2014

Ce gars est un grand malade - et il n'est pas le seul

Quand on vous dit que les choses vont très vite dans l'écosystème Docker ...

Il y a quelques heures, David publiait son fiboid à base de docker imbriqués, il n'a pas fallu attendre bien longtemps pour voir les premiers commentaires, et en particulier celui de Solomon Hykes, fondateur de Docker...

Imbriquer des conteneurs Docker c'est possible mais évidemment on send que ce n'est pas une solution très "naturelle".

Docker étant basé sur un démon, auquel parle un client (la ligne de commande docker, ou tout autre client via une API REST), il est plus simple d'expose le démon de l'infrastructure aux containers qui ont besoin de lancer d'autres containers.

L'idée est simple : monter dans le container le socket exposé par le démon.
-v /var/run/docker.sock:/var/run/docker.sock

Du coup, quand dans un container qui a été outillé de cette façon on lance une command "docker run ..." c'est le démon de l'hôte qui va répondre, et lancer un nouveau container, non plus imbriqué, mais côte à côte. Plus besoin de bricoler pour pourvoir faire tourner un démon docker dans le container, exposer les cgroups, etc. C'est tout de même un peu moins "hack-ish" :P


Deux petits schémas pour résumer ça :

Lancer un container DANS un container - possible, mais on sent comme un truc pas net

Lancer un container DEPUIS un container - clean, et plus besoin de --priviledge





Fiboid - ce gars est un grand malade

Lors de notre session au Ch'tiJug, expliquant entre deux anecdotes que Docker peut même être lancé à l'intérieur d'un autre container Docker, on (amis, j'ai oublié ton nom) nous a suggéré de faire un calcul récursif de suite de Fibonacci via des containers Docker.

Il n'en fallait pas autant pour lancer David sur la piste d'un projet aussi inutile qu'indispensable, dont il a publié le résultat : https://github.com/dgageot/fiboid "Fibo Inside Docker". Ce gars ne dors jamais, ou bien il est vraiment cinglé, ou peut être les deux, en tout cas svp ne l'encouragez pas.

A quoi ça sert ?

Sur l'exemple de David : a rien - enfin si, à tester la capacité de Docker à fonctionner en mode "poupée russe" et voir jusqu'où il peut aller.

Dans l'absolu, je suis longtemps resté perplexe, mais j'ai depuis vu passer plusieurs usages.


1. Builder des images Docker.

eBay a adopté Mesos et Docker, et a publié un papier dessus. Depuis Jenkins, un container Docker est donc lancé sur le cluster Mesos pour héberger chaque build. Jusque là, c'est simple, sauf que ce build veut lui même construire et tester des images Docker, et va donc lancer Docker dans l'image Docker. On a donc un premier niveau d'imbrication.

2. Packager un environnement multi-noeud.

Tester rapidement un project composé de N containers, ça signifie aujourd'hui fournir N images Docker et le script de lancement qui va bien (voir aussi le format containers.yml de Google). Une autre façon de faire, c'est de définir un Dockerfile qui lance les N conteneurs Docker de l'application. A nouveau, imbrication de containers

Je suppose qu'il y a plein d'autres cas intéressant à inventer.

Là ou fiboid est intéressant, c'est qu'il montre COMMENT imbriquer les containers. Car l'approche naïve que j'ai moi aussi testée dans le TGV qui me ramenais à Rennes, coincé entre deux valises d'un wagon bondé, c'est de lancer sans plus de scrupules "docker run" dans mon Dockerfile - sauf que ça ne marche pas. Sans 3G et avec les cuisses qui cuisent, je n'ai pas insisté :'(



Il y a en effet une petite manip pas triviale, résumée dans l'exemple de David par le script startdocker

Le premier truc à savoir c'est qu'il faut que le container tourne en mode "privilégié" pour pouvoir exploiter les containers (auxquels il est lui-même soumis), à savoir les API cgroup, les restrictions AppArmor, etc (je ne détaille pas car je n'y connais rien).

Ensuite, exploiter les cgroups depuis un container nécessite un minimum de collaboration avec l'hôte qui porte le container courant. Il faut donc synchroniser les cgroups du container avec ceux de l'hôte. Le reste du script est lié a divers raffinements et contournements, pour finalement lancer un démon Docker dans le container, qui permettra de lancer la commande "docker run" comme prévu.

Le principe d'imbrication des containers a été démontré initialement (afaik) par Jerôme Petazzoni, dont David a repris la recette. Le script wrapdocker ayant 3 mois, soit une éternité dans le contexte de Docker, il est possible que certains hacks ne soient plus nécessaires. Si quelqu'un en maitrise les détails, faites lui une pull-request :)





12 juin 2014

Docker Security

A moins de vivre dans une grotte, vous n'avez pas pu rater l'annonce de Docker 1.0-FINAL production ready.

Il y a tout de même un petit bémol à prendre en considération sur ce "production ready".

Docker utilise les capacités du noyau Linux pour isoler et contrôler des groupes de process (respectivement : namespaces et cgroups). La promesse est donc que chaque container se comporte quasiment comme une VM, en beaucoup plus léger, assurant l'étanchéité et l'indépendance de chaque application par rapport à ses voisines qui sont au final co-locataires de la machine hôte.

Seulement dans la vraie vie, il reste une issue non encore résolue : pour lancer un container, il faut être root. Les process qui tournent dans le container sont root (le root du container) par défaut. On peut bien sur tourner dans le container avec un autre user, mais si on autorise à faire tourner n'importe quelle image, on doit partir du principe que l'utilisateur du container est root - ou peut le devenir en hackant son container en installant volontairement un soft dont il connait une faille de sécu, il ne suffit donc pas de forcer le USER.

Que se passe t-il si notre utilisateur dans le container, qui s'y connais bien et a des intentions indélicates, arrive à sortir du conteneur, exploitant la faille X de la version Y du noyau pas encore mis à jour sur l'infra ? Et bien notre petit malin va se retrouver root sur la machine hôte - et ça c'est pas glop. Tiens d'ailleurs, si quelqu'un connais une (vielle) version du noyau / distro qui aurait un bug de ce type ce serait sympa pour en faire une démo.



Cette contrainte, on peut vivre avec, surtout sur des environnements privés : dans votre DataCenter, le risque d'un hack de ce type est quasi nul vu que vous ne déployez que vos propres applis. Sur un environnement réellement multi-tenant comme un Cloud public par contre ...

Le noyau Linux fournit le mécanisme de user namespace, qui permet à l'utilisateur root du container (id=0) d'être en fait l'utilisateur tartempion avec des droits standard sur la machine hôte. Le jail-break, sans être complètement anodin, n'a alors plus du tout le même impact.

Docker pourrait utiliser ce namespace, qui nécessite "juste" un noyau très récent. Vous pouvez lire les commentaires sur cette issue par exemple, qui n'aborde qu'une partie d'un possible fix, pour comprendre que ce n'est pas si simple, et qu'écarter ce point pour une 1.0 avait du sens. Comme dit plus haut, cela n'interdit pas d'utiliser Docker dans un environnement privé et contrôlé.

Par contre c'est un gros frein pour son utilisation massive par les hébergeurs Cloud, sauf à y adjoindre un autre niveau de sécurité. Sans surprise, le support Docker proposé par Google utilise une VM par déploiement, ce qui en soit est une régression de la part de l'éditeur qui utilise des containers en interne depuis presque 10 ans.



Je m'interroge sur les solutions retenues par les autres hébergeurs qui proposent du Docker aujourd'hui. S'ils veulent bien me contacter pour en discuter en privé je serais ravi d'échanger sur le sujet.

Vous pouvez aussi lire http://blog.docker.com/2013/08/containers-docker-how-secure-are-they/ pour en savoir plus sur ce thème.

Regardez aussi cette vidéo qui montre ce qui se passe lorsqu'on sort du container et qu'on rencontre la protection SELinux, qui évite à "root" de devenir "root" :-\


11 juin 2014

DockerCon

Pendant deux jours, Docker a été à l'honneur avec la première édition de la DockerCon, à laquelle participait mon collègue Michael Neale que je maudis pour avoir eu une place et pas moi.



Pendant notre petit tour des JUG avec David Gageot, nous abordons en fin de session un "what's next" avec un gros disclaimer, de circonstance lorsque de l'autre côté de l'atlantique ont lieu des annonces officielles. 

Nous ne nous sommes pas trop trompés jusqu'ici, car les annonces majeures ce sont :

  1. Docker production ready 1.0 - ok, ça fait conference-driven-development, et un 1.0.1 va évidemment suivre, ceci dit la version 0.12 qui a précédé était déjà super-stable, donc ce n'est pas que du marketing.
  2. Des témoignages d'acteurs majeurs. RackSpace, NewRelic, Ebay, Twitter ... autant d'innovateurs qui ont déjà commencé a adopter Docker dans leur boite à outil. J'espère que vous allez leur emboiter le pas :)
  3. Le re-vamping de l'index (build et hébergement des images Docker) en "DockerHub". Michael a discuté avec eux de l'intégration Jenkins, présentée en keynote de la conférence. L'idée est de "laisser faire Jenkins pour valider une image, chacun son taf" et j'ai donc préparé l'indispensable plugin qui va avec, n'allez pas voir pour l'instant il ne fait rien :) Je vais surtout bosser sur une intégration OAuth propre, la partie "validation d'une image" ayant par définition une signification différente pour chacun.
  4. Des annonces en tout genre, entre autre le positionnement très fort de Google sur Docker. Il faut dire que Google est à l'origine de cgroup donc fait partie de l'écosystème des containers depuis un moment.
  5. De nouvelles briques pour l'écosystème Docker. Si vous avez vu notre prez', Docker gère le container mais laisse aux outils tiers l'orchestration de l'infrastructure. CoreOs et Mesos sont les gros-mots qui reviennent souvent sur ce sujet, mais l'équipe Docker a aussi lancé libChan (communication entre containers) et libSwarm (composition de services à base de containers).
Bref, nous n'avions certes pas tout prévu, et tant mieux, mais nous n'étions pas complètement à côté de la plaque :)


10 juin 2014

Votre avis nous intéresse (aka "LikeBox")

En tant qu'organisateur du BreizhCamp, un stress particulier concerne la programmation de la conférence. Les thèmes choisis reflètent-ils les attentes ? Notre sélection de speakers a t-elle été la bonne ?

Obtenir du feedback du public est donc indispensable. Nous avons testé le tableau de post-it pour collecter votre avis général sur la conférence, mais cela ne nous informe pas sur les sujets eux-même.

En 2013 nous avions placé en sortie de salle des feuilles de vote proposant trois smileys, et vous demandant de cocher celui qui correspond à votre état d'esprit. Si d'un point de vue logistique cette solution est simple, elle ne rencontre pas un succès terrible, peu de personne prenant le temps de s'arrêter pour choper un stylo, cocher, remettre le bouchon. Certains ont également regretté l'absence d'un mode d'emploi pour expliquer clairement nos attentes face à une feuille vierge.

Très clairement, la facilité et la rapidité de vote est un facteur important.

Lors de DevoxxFrance, Xebia avait mis en place des boitiers de vote à la sortie de chaque salle :



J'ai vu peu de monde s'attarder pour voter, même si les données recueillies ont été très utiles pour les organisateurs. Un souci important était de mon point de vue la complexité excessive du système :

  • 5 boutons, donc un choix assez délicat. J'ai du mal à imaginer que le bouton "très mauvais" ai beaucoup été utilisé. Le median non plus d'ailleurs, pourquoi s'arrêter pour voter si on a pas un avis spécialement tranché ? Accessoirement, sans repère visuel sur les boutons, leur sens n'était pas évident. Résultat, passer au vote nécessitait une réflexion et donc un frein à l'expression spontanée.
  • Une identification NFC, destinée à éviter les votes multiples. Si vous avez déjà vécu la sortie d'une salle Devoxx vous savez qu'on a guère le temps de voter, alors voter 3 fois ... Sans parler de la question fatidique "mais heu, c'est vraiment anonyme du coup ?


Leçon #1 : ne pas laisser trop de choix, sous peine de perdre en compréhensibilité et donc en spontanéité du vote, et au final en nombre de votants.

Leçon #2 : ne pas mettre en place de barrières à l'expression des votants. Le vote doit être quasi instantané et ne pas ralentir la sortie de la salle.

Leçon #3 : utiliser comme Xebia des pieds d'enceinte sono, solides et pas cher. 

Devoxx.be a de longue date tenté de récolter les avis des participants à chaud. La formule retenue est basée sur ce qui a participé au succès de FaceBook, les "like".


Ici aussi, on identifie le participant par puce NFC, cependant il n'y a que deux états "content" / "pas content". En 2013 ils avait rajouté au centre un capteur pour ajouter la session dans votre compte parleys, afin que les déçus de la salle pleine à craquer puisse avoir une seconde change offline.

Le système est simple, de compréhension évidente (surtout ce modèle avec les pouces intégrés dans la forme du boitier, mieux qu'en 2011). Le NFC reste un léger frein à la fluidité de la sortie de salle, et maintien une certaine interrogation sur l'exploitation des données personnelles,mais globalement le système fonctionne bien.

Leçon #4 : proposer une user-interface aussi explicite que possible.

Leçon #5 : le côté Geek du matos apparaissant en transparence est un élément clé de l'intérêt du public à expérimenter les systèmes de vote. De ce point de vue le boitier en alu brossé utilisé par Xebia était contre-productif (sans même évoquer les problèmes de masse qui leur a plombé leur nuit pré-devoxx).


Pour JavaOne, les organisateurs avait mis en place des boitiers avec 4 boutons de vote, du vert au rouge avec un joli dégradé de smileys.



J'ai vu bien peu de personnes prendre le temps de voter sur ces boitiers, mais l'approche est simple, explicite, et saine sur la nature des "données" fournies au système. Ici je passe devant et j'ai juste à mettre un coup de poing sur le bouton de mon choix.

Pour le BreizhCamp, nous n'avions pas l'intention de faire des bracelets avec puce NFC, entre autre en raison du coût de ces gadgets. Une solution de ce type était donc clairement ce qui nous correspondait le mieux.

Comment éviter les votes multiples ? D'ailleurs, qu'est-ce qu'un vote multiple ?

Celui qui est super-super-content et va rester 3 minutes devant la machine pour exprimer son contentement en votant 10 fois, finalement fournit une information utile. Le tout est de savoir l'exploiter (problème de BigData :P). Evidemment il y a le cas du Aurelien qui durant toute sa pres' vient voter +1 chaque minute, mais ça reste un cas isolé et très facilement identifiable.

Nous avons donc défini notre cahier des charges :


  1. le boitier doit être d'utilisation limpide, sans aucune interrogation sur sa bonne utilisation. Deux boutons +1 / -1 suffisent, et obligent à se positionner plutôt qu'à voter "neutre".
  2. le vote doit être physique, par bouton, pour être rapide et implicitement anonyme. 
  3. le double vote involontaire (rebond du bouton) doit être évité, pas forcément le vote multiple absolu
  4. le boitier doit être geek, fun, donc transparent. L'idée est rapidement venu d'intégrer leds / bip / écran pour signaler la prise en compte du vote.
  5. le boitier doit être costaud. Bouton coup-de-poing industriel, plexi de 8mm, pied d'enceinte 50kg.
  6. le CPU dédié à enregistrer les votes ne risquant pas la surcharge, la sortie vidéo HDMI est exploitée pour afficher programme, tweetwall, etc
  7. l'accès réseau se fait en filaire. Nous savons tous ce que donne le Wifi en conférence.

Dans la pratique il s'agit du cahier des charges a posteriori, ce projet ayant été conçu entre deux emails de manière très informelle.

Pour la réalisation, je vous met entre les mains de Laurent qui explique ça mieux que moi. Ma contribution a surtout consisté à découper au dernier moment les plaques de Plexy (d'où une finition douteuse) avec l'aide de Julien (7 ans, d'où un alignement des perçages ... hasardeux)


Nous avons également réalisé un test grandeur nature en nous mettant à trois en file, imitant une sortie de salle, pour valider les timings anti-rebond, l'affichage du LCD, etc. 

Nous avons bien sur tout un tas d'idées pour améliorer ce produit, que nous avons nommé "LikeBox" :

  • Utiliser des cartes BeagleBone, plus puissantes que la RaspBerry, et plus classe (PCB noir, LED bleues) 
  • Donner à nos boitiers la forme de la box Internet de l'opérateur historique, ce qui suppose de cintrer du plexiglass de 8mm #challenge.
  • intégrer un port pour connecter rapidement une console de debug - nous avons eu quelques surprises
  • ...

Bref, encore quelques soirées bricolage en perspective...



Ce boitier, nous le mettons à dispositions des conférences amies contre un dédommagement symbolique et une entrée gratuite (:P) => likebox@breizhcamp.org


06 juin 2014

Windows Sucks

Un problème récurrent que les clients CloudBees reportent au support est l'utilisation de machines de build Windows. Nous recommandons clairement d'utiliser un Linux pour le master, mais bien sur il est nécessaire à de nombreux projets de faire tourner les diverses variantes de Windows comme "esclave" de build.

Jenkins offre de contrôler les slaves Windows via DCOM. Soucis, ce protocole historique a deux modes : "marche" et "marche pas". Autrement dit, une quelconque erreur de configuration se traduit systématiquement par un "Access is denied. [0x00000005]" sans plus d'explication.


Bien plus grave, les différentes astuces référencées sur le wiki et récemment mises au propre par Jesse nécessitent toutes de bricoler les droits système et le registre Windows, sans compréhension claire de l'impact de ces changements sur le système. Il n'est pas exclu qu'on ouvre par ce biais une énorme faille de sécurité. Bonus, il s'avère que les versions 64 bits de Windows se comportent assez différemment, et nous avons des retours assez étrange sur l'utilisation de Windows 8. Je ne vous parle même pas des versions "serveur" de Windows (dont je n'ai jamais compris ce qu'il a de "serveur" mais bon).

Nous décourageons donc à nos clients d'utiliser ce mécanisme. L'approche alternative utilise Java Web Start, autrement dit la création d'une connection à l'initiative de la machine Windows, ce qui coupe court aux problèmes de sécurité. Installé comme service windows, l'agent jenkins slave va donc se connecter au Jenkins master au démarrage. Dans de nombreux cas c'est très nettement mieux, cependant il s'avère que cette connection est parfois instable, pour des raisons encore inexpliquées, et bien difficile à diagnostiquer.



Une autre solution, qui s'avère plus stable, est de remplacer le slave Windows par un slave GNU/Linux. Pas de panique, je parle en fait d'installer Cygwin sur la machine Windows, pour la "GNU-ifier" et d'y faire tourner un service openSSH. La machine peut alors être contrôlée par Jenkins comme n'importe quel esclave Linux SSH, ce qui accessoirement unifie l'infrastructure de build.

Ce qui est triste dans l'affaire c'est de se dire qu'on aurait pas besoin de toute cette tambouille si Windows avait un server SSH natif :'(




05 juin 2014

Docker "Oignon" FileSystem

Pour présenter le mécanisme de fichiers 'en couches' utilisé par Docker (Union File System) David s'amuse à lancer un container ubuntu, faire un méchant rm -RF /, quitter le container et relancer la commande pour montrer que "de retour dans le containeur, le file système est clean".

L'effet attendu est atteint, à savoir faire prendre conscience au public, plus habitué à FAT32 qu'aux capacités des filesystems avancés de type ZFS, du mécanisme de copy-on-write et d'empilage de couches sur le filesystem en mode delta.

Pour ce qui me concerne, je présente souvent ce mécanisme comme du "oignon-filesystem" pour bien montrer ce concept de couches fines empilées, qu'on peut à volonté dépiler/empiler sous réserve de respecter le même ordre.


Nous jouons cependant un peu avec le feu en introduisant une fausse idée sur ce qui se passe. Histoire de rétablir un peu de rigueur, explication de texte :

Lorsque vous lancez docker run -i -t ubuntu /bin/bash, docker crée un container avec le filesystem ubuntu en read-only et active une "couche" AUFS en copy-on-write que vous allez modifier lors de vos actions dans le shell - par exemple via un rm -rf /.

Lorsque vous quittez le shell, le container s'arrête - mais il existe encore pour le démon docker, il est simplement à l'état stopped. Vos modifications sont bien là, stockées par AUFS, il n'y a juste plus aucun process qui y accède.

Lorsque vous relancez la commande docker run -i -t ubuntu /bin/bash vous créez un second container, strictement équivalent au précédent lorsqu'il a été lancé initialement. C'est d'ailleurs le point intéressant en termes de processus de développement / déploiement : la reproductibilité de votre livrable.

Cependant nous ne sommes pas à proprement parlé "revenus dans le conteneur". Nous pourrions par contre relancer le container initialement modifié avec la commande docker start  pour relancer le conteneur initial. Comme il n'est pas évident d'obtenir les ID des conteneurs ni de les mémoriser, si vous voulez jouer à ça je vous conseille de nommer vos containers.

Bon ceci dit, ceci est juste une petite mise au point théorique, dans la pratique relancer un conteneur arrêté n'a pas un intérêt énorme amha par rapport à la possibilité de relancer un conteneur tout propre, sachant que les données que l'on doit persister sont confiées à un volume, autrement dit un répertoire de l'hôte.

Le seul cas d'utilisation que je peux imaginer - qui est tout de même non négligeable - c'est le diagnostic post-mortem d'une appli que vous avez lancée via docker et qui s'est arrêtée. Docker start vous permettra alors de lancer un bash et d'aller inspecter le cadavre.



04 juin 2014

Containerization vs Virtualization

En accompagnant David Gageot pour un East-JUG-Docker-Tour nous avons pu discuter de nos approches de présentation respectives et de la difficulté de bien faire comprendre un concept fondamentaux qui est la clé de voute de Docker : les containers.

Tel que je le présentais jusqu'ici, vu les questions qui suivaient la présentation, il est clair que j'allais trop vite et que du coup le message passait mal. David a repris toute cette partie pour l'expliciter dans le détail avec démos d'illustration. Nous testerons le résultat sur le public Strasbourgeois ce soir ...

Une image m'a été suggérée par Guillaume pour illustrer la différence entre un container et l'approche "à la virtualbox". Je l'ai intégrée à la présentation, car c'est le genre d'image choc qui marque les esprits et aide donc à bien mémoriser le concept.



A propos d'image marquantes, une photo souvenir. Pour la petite histoire, dans le train qui nous transportait de Nancy au prochain JUG de ce East-Tour, scotchés à nos écrans à essayer de bosser un peu (tout de même) et entendant le haut parleur crachoter l'annonce "notre train va arriver en gare de S..a..bourg" nous sommes descendus sans broncher, même pas surpris par la taille très modeste de la gare. Le temps de réaliser notre erreur, le train était reparti. #Boulets




02 juin 2014

Docker-tour squatt

Suite au succès de la session "la révolution Docker" à Devoxx, je me suis proposé de faire un petit tour des JUGs sur ce thème. Après consultation des organisateurs, il s'est rapidement avéré que David Gageot avait eu la même idée (j'ai du rater un tweet ...). Je passe donc du statut de speaker à celui de ... squatteur.


Blague à part, cela devrait être enrichissant de comparer nos approches du sujet. Rendez-vous demain 4 juin à Nancy et mercredi 5 juin à Strasbourg.

28 mai 2014

Publier sur Parleys

De retour du BreizhCamp, nous voici avec quelques Go de vidéo AVCHD à publier.

L'encodage de ces vidéos n'est pas distribué pour des raisons de volumétrie. Il faudra qu'on réfléchisse à une façon de gérer ce "problème" un jour, mais dans un premier temps j'ai Adobe Media Encoder qui tourne toute la nuit chaque jour, suivi d'un upload sur Youtube - je n'ai malheureusement pas la fibre, mais bon, l'encoding reste plus long que l'upload, donc ce n'est pas le facteur limitant.

Les vidéos sont donc mises à disposition sur la playlist BreizhCamp 2014 du BreizhJUG.

Le montage sur Parleys est une étape qui s'est grandement simplifiée au cours des années. C'est aujourd'hui une appli HTML5 directement intégrée au site. Si vous voulez nous aider, contactez team@breizhcamp.org pour être ajouté comme publisher.

Allez sur le channel du JUG sur lequel la session sera publiée. Cliquez "Add presentation" et indiquez le nom du talk tel qu'il est défini sur le programme.

Dans la session (vierge) qui s'affiche, sélectionnez "timeline", la partie édition de parleys s'affiche alors. Sélectionnez la Lirary, c'est ici que l'on va importer le contenu à monter : vidéo youtube et slides PDF.

Il suffit ensuite de glisser/déposer la vidéo dans la timeline, puis de sélectionner les slides PDF, lancer la vidéo, et tapper s+space à chaque changement de slide par le speaker - en vérifiant qu'il ai bien suivi l'ordre de ses slides :P. L'onglet "shortcut" indique d'autres raccourcis pour un montage rapide sans galérer avec la souris.


S'il y a un phase de démo, insérer une "chapter" vide, ce qui masquera les slides dans le lecteur parleys pour n'afficher que la vidéo (éventuellement en plus grand, selon la configuration sélectionnée par l'utilisateur final).



Choisissez un moment représentatif de la session pour capturer un image de couverture via le tab "Settings". Dans la partie "attachement", glisser/déposer les slides de la librairie,



quand tout semble ok,  [Publish] !

Le talk sera alors disponible à l'état staging. L'édition des méta-données (speakers, résumé) consiste à reprendre les infos du programme. Si vous n'avez pas ces infos (nouveau speaker dont vous n'avez pas l'e-mail) on s'en chargera, le gros du boulot aura été fait de toute façon. Indiquez juste l'état "staging" dans le spreadsheet, qu'on sache qu'il n'y a que la dernière étape de publication à prendre en charge




25 mai 2014

Machistes ?

On nous a signalé cet article sur la programmation du BreizhCamp.

Il y es dénoncé le machisme du comité de sélection qui aurait écarté les femmes du programme.
D'une part, je ne sais pas sur quels chiffres ces bien-pensants se basent, mais je n'ai jamais vu plus de 2 à 4% de femmes dans une équipe de développement - je parle bien de développement, pas de l'IT en général, le chiffre monte alors à 20% et quelques d'après le syntec, ce qui reste peu - j'ai l'impression que l'auteur se base sur ce chiffre quand il note "l’inégalité est flagrante, bien plus importante que la proportion réelle de femmes dans le domaine". Dommage de se baser sur des chiffres aussi générique lorsqu'on parle d'un domaine très ciblé.

Nous avons retenu 3 filles au programme et non une comme indiqué initialement par l'article, soit 50% de réussite à l'épreuve du call-for-papers, comme pour les hommes. Nous sommes en effet neutres et ne faisons pas de discrimination positive sur le sexe du speaker. Ce serait contre-productif à mon avis en proposant des sujets de moins bonne qualité et en les associants finalement aux speakeuses. Certaines femmes techos proposent d'excellent sujet, et n'ont pas besoin de cela pour être retenues.

On nous accuse aussi d'avoir une équipe 100% masculine à sélectionner les propositions. C'est en effet le cas, Marie-Christine étant partie à d'autres occupations, mais nous n'avons jamais communiqué la liste des membres du comité de sélection, il s'agit donc à nouveau d'une conclusion gratuite.

On nous accuse de ne pas prendre en compte le cas de femmes dans l'IT. Ca tombe bien, un sujet était au programme pour présenter Women in IT, co-présenté par un des organisateurs à l'initiative de ce mouvement sur Nantes.

Je suis moi-même membre de JDuchess, et bien que peu actif je pense être sensibilisé et tenter d'y apporter des réponse concrètes, comme d'héberger une après-midi Devoxx4Kids pendant le BreizhCamp et promouvoir ce mouvement, actuellement le meilleur moyen pour que la prochaine génération ne plafonne pas à nouveau à 2% dans les domaines techniques. L'un des membres de l'équipe (Nicolas Ledez) anime tout au long de l'année des ateliers, et est donc très impliqué dans la démarche.

Quand aux "maladresses (photos ou ton déplacé)" notées par l'auteur, qui sont en général le fait de quelques speakers et non des organisateurs, pour les femmes présentes que je connais elles sont bien vécues - certaines n'étant pas les dernières sur le sujet.

Alors quand je lis un article tirant de mauvaises conclusion sans plus de recherche, sur un site qui se veut observatoire du machisme dans les tech et de toute évidence bien mal informé, ça me fait mal. L'auteur, déjà contacté par quelques uns d'entre nous n'a pour l'instant pas répondu, en dehors d'un update mineur sur son décompte des speakeuses.

Je n'ai aucunement l'intention d'imposer un guide de bonne conduite à l'américaine. Au BreizhCamp il y aura aussi des gros mots, voir même quelques trolls contre PHP ou Python, j'espère que l'observatoire du bon parlé français ou le site des Pythonistes-béliquex ne nous en voudront pas - d'autant plus que c'est le but de la conférence : confronter les points de vue, parfois sur un ton ... canaillou :P. Donc si tu es une femme, que tu peux nous parler de la supériorité de PHP sur Java, et le tout sans le moindre gros-mot, tu es la bienvenue - par contre, pas de mauvaise blague sur les gens de couleur (*) ni sur les tendances sexuelles, on ne veut pas d'ennuis avec un autre site bien-pensant.

(*) nous avons un asiat' dans l'équipe. Il s'est de lui même proposé pour faire des sushis. Nous avons même quelque SysAdmins, c'est dire si on est ouverts.


14 mai 2014

workflow plugin

Il y a parfois des coincidences.

Je publiais hier un billet expliquant pourquoi j'abandonne le build-flow plugin au bon soins de la communauté. Quelques heures plus tard Kohsuke annonçait sur la mailing list jenkins son plugin de workflow.

Nous nous serions concertés pour faire un lancement produit nous n'aurions pas fait mieux ! Mais non, c'est juste une coincidence :P

Ce nouveau plugin n'est pas à proprement parler la continuité du build-flow, même s'il en partage certains aspects. On retrouve un DSL qui décrit le workflow, mais ici l'unité de base n'est plus un job, mais un build-step, qu'on va exécuter sur un slave donné.

Le plugin est encore assez jeune mais permet déjà de définir des choses comme :

git.checkout( repo: “git@sm.com:app.git”, branch: “master”)
mvn “install”

je ne doute pas que KK ai prévu tout le nécessaire pour que chaque plugin jenkins puisse ajouter ses propres mot clé au DSL et l'enrichir...

En regardant les slides de présentation, je me demande si ce même DSL (réduit) ne pourrait pas être utilisé pour définir le build via un fichier à la travis, autrement dit un .jenkins stocké dans le SCM dans lequel vous définiriez les étapes de build et tout ce qui va bien pour votre project, ne déclarant dans jenkins que la partie SCM.

A réfléchir ...

12 mai 2014

build flow future

Depuis trois ans je développe par petites touches le plugin Jenkins Build Flow, dont l'objectif est de fournir une solution d'orchestration de jobs jenkins, pour des process de build non triviaux et non nécessairement linéaires. L'idée est de reposer sur un DSL pour exprimer les relations entre jobs d'un même "pipeline", de manière concise et centralisée - et non dans chaque job via divers plugins spécialisés.

Ce plugin a été largement adopté (3500 installations) malgré tout je l'ai toujours considéré en phase expérimentale (d'où le numéro de version : 0.11). Ce succès a révélé un effet de bord majeur : de nombreux utilisateurs ont exploité la syntaxe Groovy du DSL pour venir "bidouiller" Jenkins à l'aide du build-flow. Initialement je pensais que le DSL devait être un pur langage indépendant des APIs de Jenkins, ce qui permettrait de faire évoluer le moteur interne. La facilité de créer un DSL en Groovy et l'absence totale d'expérience de ma part dans ce domaine a ouvert la boite de pandore. Aujourd'hui il est impensable de conserver la compatibilité et de revoir l'implémentation du moteur.

Or le build-flow a un défaut majeur : ce n'est pas une machine a état qui est modélisée puis exécutée, mais un thread java qui est lancé. Impossible de figer le flow (redémarrage de jenkins), de reprendre à flow à une étape précédente (reprise après erreur), etc. Bref, de prendre en charge des process de développement réellement complexes et de correspondre à ce que fait par exemple le plugin build-pipeline pour les cas "linéaires".

Bloqué par ce problème technique, je n'ai plus travaillé sur le plugin depuis un moment, et je manque de temps et d'idée pour m'y atteler. Accessoirement je n'utilise pas ce plugin moi même, le dogfood étant le meilleur moteur pour faire avancer un projet, celui-ci s'enlise.

J'ai donc décidé d'abandonner ce projet, qui est à la disposition de la communauté -  en termes d'écosystème Jenkins cela signifie que le premier qui prend le temps de le maintenir devient mainteneur officiel. J'ai lancé un appel à volontaire sur jenkins-dev. Si vous êtes tenté, je suis évidemment disposé à vous expliquer en bon Français le pourquoi du comment avant de vous passer la main, contactez-moi.

Ce plugin ayant ses fans, déçus par les tentatives de recentrage que j'ai appliqué après la version 0.10, je ne doute pas que quelqu'un prendra la main dessus, et le fera évoluer selon ses besoins. Il ne correspond plus à ma vision, mais peut tout à faire correspondre aux besoins de nombreux autres utilisateurs.

Kohsuke travaille sur un nouveau plugin de workflow. Je n'ai suivi son initiative que de loin pour le moment et je ne sais pas très bien le recouvrement. Je sais juste qu'il a profité des enseignements du build-flow, même si nous n'en avons pas nécessairement la même perception. Wait'n see.


07 mai 2014

test des accès base

Je vous présentais hier un petit outil bien fait pour écrire les tests d'API REST. Sur une application qui fait autre chose qu'un hello world, il faut cependant "bouchonner" les resources externes pour rendre ces appels prédictibles et donc reproductibles dans le cadre de tests automatisés.

Une pratique courante de test consiste à utiliser des Mocks, en considérant qu'on veut valider l'utilisation d'un système tiers, pas son implémentation. Dans le cas un peu particulier d'une base de donnée cependant on est confronté à un problème : le SQL

Les accès à la base de donnée sont en effet liés à son interprétation de ces fameuses requêtes, et le seul moyen de s'assurer que leur syntaxe est correcte, correspond au schéma de la base de données, et retourne bien les données attendues, c'est ... de l'exécuter.

Que l'on fasse du JDBC à l'ancienne ou qu'on utilise un outil de requêtage type-name-safe comme jooq le problème reste le même, une requête n'est vraiment fiable que si on a pu la valider sur une base de données réelle. La solution que tout le monde (?) utilise est une base de donnée H2 - base qui tourne en mémoire - ce qui permet de démarrer rapidement et sans complication une base juste pour la durée des tests. Je me suis fait une Rule junit pour monter cette base H2 et appliquer les scripts de création du schéma, qui sont - évidemment - stocké dans mon repo Git avec le code de mon appli (what else ?).

Pour mettre la base dans un état donné et valider le résultat de mes requêtes, à la recherche d'une solution sympa, légère et qui soit un peu plus productive que des fichiers xml DBunit, je suis tombé sur dbassert.

    @Rule
    public InMemoryDataBase dataBase = new InMemoryDataBase();

    @Test
    public void list_items() throws Exception {

        DbAssert db = DbAssert.init("dbassert.yml");
        DbSource h2 = db.source("h2", getClass());
        h2.clean_table("items");
        h2.fixture("items");

        // Proposal returned
        when()
            .get("/items")
        .then()
            .assertThat().body(containsString("Test item"));

    }

Ca reste un chouille verbeux, donc pour faire clair :

le init consiste à configurer DBAssert pour accéder à la base de test. La DBSource sert à définir où trouver les fichier de données - dans le même package que la classe indiquée. On applique ensuite des fixtures, des fichiers yml de données pour la table du nom correspondant. On peut de même comparer l'état de la base après un update.

Quelques points négatifs qui me font penser que c'est un projet encore jeune, ou bien qu'il y a mieux ailleurs :)


  • le projet est sous SVN sur google code. Clairement pas adapté pour la contribution a l'aire de GithHub.
  • la librairie n'est pas disponible sur maven central. J'ai fait un export des sources dans mon src/test/java, vu qu'il n'y a que quelques classes
  • l'API est perfectible. Je voudrais pouvoir initialiser DbAssert via une DataSource - que j'ai préparée par ailleurs dans ma InMemoryDatabase  - plutôt que via un fichier yml
  • l'application d'une fixture utilise un INSERT bête et méchant, sans rechercher les données déjà insérée. On doit donc faire un clean_table systématiquement.
Rien de bien grave, qui devrait pouvoir se corriger via une petite contribution (d'où le premier point).

Si vous connaissez un autre outil comparable, je suis preneur de vos retours d'expérience.




05 mai 2014

test de services Rest

Il y a quelques années, lorsque je développais des applications web (avant de devenir essentiellement un développeur  middleware/backend) il y avait une explosion de frameworks MVC. Struts, WebWork, Wicket, Stripes, pour n'en citer que quelques-uns.

Les applications actuelles tendent vers un modèle à base de vue riches JavaScript et un backend REST, et on voit émerger une foultitude de Frameworks JavaScript et de backend REST.

Je n'ai jamais été très fan des tests web, selenium ou htmlunit, qui ont toujours été délicat à stabiliser et bons pour la casse à la moindre refonte de l'UI. L'évolution vers une architecture JS+REST a l'avantage de permettre au moins de tester facilement la partie REST - je n'ai pas encore exploré les solutions pour la partie Web à proprement parler, c'est quelque part dans ma todo-list ...

Comme toujours, il y a pléthore de frameworks pour un même besoin, chacun avec ses propres spécificités et avantages. Je n'ai pas l'ambition de vous dire avoir trouvé la perle rare ni proposer un palmares exhaustif, vu que je n'en ai essayé qu'un : Rest-assured.

Ce que j'aime bien dans Rest-assured c'est la syntaxe très, très simple et lisible des conditions de test et des assertions, très inspirée de l'approche BDD ("given/when/then") :

    @Test
    public void should_create_user() {
        given()
           .body("{ \"name\": \"nicolas\" }")
        .when()
           .post("/users")
        .then()
           .assertThat().statusCode(CREATED);
    }

Très peu de code parasite dans la description d'un tel test d'API. Que le scénario de test soit lisible même par ma grand-mère (ou pire : ma MOA) comme le voudraient les partisans des tests fonctionnels m'importe peu, par contre que je puisse rapidement définir une condition de test sans partir dans des imbrications d'API sans fin, ça me parle.

L'approche "fluent" (qu'on appelait Builder Pattern dans le temps, mais c'est moins hype) apporte aussi beaucoup en lisibilité. En gros, si on fait abstraction de la ponctuation on peut lire une phrase quasi naturelle (enfin, humanoïde quoi), c'est ce qu'on appelle un Domain Specific Language. On retrouve ce pattern dans tous les frameworks récents, et les lambdas de Java 8 aident pas mal à étendre cette approche à de nouveaux cas d'application.

Ce que je constate surtout, c'est qu'à côté l'explosion des frameworks applicatifs on a aussi une explosion de l'outillage de test, souvent (toujours ?) la cinquième roue d'un développement, mal ficelé, mal entretenu, mal outillé. Pour ce qui me concerne je les redécouvre tardivement. Ne faites pas la même erreur que moi, gardez un oeil sur vos tests et la boite à outil qui va avec.


Bon ceci dit, c'est bien connu "tester c'est douter". Perso j'ai appris à mes dépends à douter et à prendre quelques précautions pour éviter les mauvaises surprises.



Small is beautiful

Faire des tests rapides, un build qui ne dépasse pas quelques minutes, ça reste un voeu pieux confronté à une appli de centaines de milliers (millions?) de lignes avec une architecture alambiquée. Je ne jette la pierre à personne, j'ai moi même largement contribué à rendre ces applications alambiquées à grand coup de Spring-truc et d'AOP.



Aujourd'hui, avec du recul et surtout en travaillant dans une équipe totalement distribuée (donc où il faut savoir limiter les besoins de synchronisation et  de communication), j'apprend les mérite d'une autre approche.

Vive les micro-services.

Le concept de micro-service est expliqué en détail par Martin Fowler et James Lewis. 

Une application mastodonte-monolithique est délicate à faire vivre et ardue à appréhender. Le découpage en couches à la JavaEE et les modules maven associés ne changent pas grand chose à la donne, et au contraire ont tendance à figer de possibles mauvais choix. Si par exemple j'ai développé mon UserRepository avec plein de beaux tests, et que je veux faire un savant refactoring de mon modèle, je vais m'assoir sur tous mes tests, car ils sont ciblés sur la vision de mon architecture à un instant t, alors que le besoin de départ est fonctionnel. On touche ici au distingo test unitaire / test fonctionnel. 

Selon une approche micro-service, plusieurs applications spécialisées prennent en charge des domaines métier restreints. Une équipe plus spécialisée et plus restreinte s'occupe de ce "fragment" et peut plus facilement le faire évoluer. Dans le cas d'une équipe distribuée à la CloudBees, ça donne des équipes de 1 :-)  Chaque service étant très spécialisé et ciblé il est facile de rentrer dans le code "en renfort".

Ces micro-services communiquent ensemble via des APIs, et peuvent utiliser des protocoles binaires pour limiter l'impact d'un appel HTTP sur les performances, mais ce qui compte ce sont les frontières qu'on a défini dans le modèle métier.


Ces frontières et la réduction du scope allègent grandement chaque service et permettent de mettre en place des pratiques de développement efficaces, et d'augmenter l'agilité de chaque service. L'agilité de l'application dans son ensemble s'améliore aussi, malgré un surcout de synchronisation des développements de chaque service. C'est un peu le principe des scrums-de-scrum.

Autre bénéfice qui émerge rapidement, chaque micro-service peut avoir sa propre architecture, voir son propre langage d'implémentation, et donc mieux répondre au besoin "local". 

Ce n'est pas forcement lié, mais si on ajoute Docker dans l'équation, tous ces services peuvent tourner sur la même machine et la communication entre micro-services a alors un coût minimal. Docker permet de donner des quotas à chaque service, et donc d'identifier facilement lequel part en vrille lorsque c'est le cas - ce qui est souvent un challenge ardu sur une grosse appli monolithique. Il permet aussi de gérer un dimensionnement différent de chaque service, un cycle de vie différent, etc.

Bref, vous l'aurez compris, je suis fan :)