Chez Nuxeo, nous nous efforçons de faciliter le travail des développeurs. Nous avons par exemple Nuxeo Studio, qui permet à nos clients (et à leurs équipes de développement) de personnaliser notre solution en fonction de leur logique opérationnelle en seulement quelques clics en définissant de nouveaux types de documents, de nouveaux workflows et de nouvelles règles. Mais lorsque la situation nécessite un niveau de personnalisation plus élevé, les développeurs doivent écrire du code en Java et déployer ce code dans Nuxeo Platform via de nouveaux bundles. Pour ce faire, nous mettons à disposition des packages Nuxeo personnalisés qui facilitent le déploiement.

Si vous suivez notre blog, vous aurez peut-être remarqué que nous sommes particulièrement intéressés par OpenShift Container Platform. Lorsque nous avons analysé les différentes options de déploiement, nous nous sommes naturellement tournés vers OpenShift. Nous voulions proposer un environnement de déploiement continu avec OpenShift, ce qui signifie que lorsque vous écrivez du nouveau code et de nouveaux tests et que vous pushez votre code vers GitHub, celui-ci sera déployé sur votre instance de développement Nuxeo. Voyons en détail comment c'est possible.

Source To Image OpenShift

L'une des possibilités pour déployer une instance dans OpenShift est d'utiliser sourceStrategy. L'idée est de cibler un référentiel GitHub capable d'accueillir le projet.

Par défaut, le système peut concevoir des projets avec un Dockerfile, mais vous pouvez spécifier une image capable de créer le projet, le placer dans un package et créer une image Docker contenant ce projet. Ce procédé est connu sous le nom Source To Image. Vous partez d'un bloc de code (par exemple Java) et vous arrivez avec une image Docker prête à l'emploi.

Dans la routine Docker Build, Ship, Run, Source To Image gère la partie Build*. Une fois créée, l'image est ensuite envoyée en tant qu'ImageStream dans OpenShift, qui gère la partie Ship. Enfin, vous pouvez utiliser cet ImageStream dans un DeploymentConfig. C'est la partie Run**.

Image Nuxeo S2I

Pour mettre en application ce cycle de déploiement complet, nous avons créé une image Docker Nuxeo S2I (Source to Image) capable de créer un projet Nuxeo et contenant un JDK, Maven et des outils Node.

Créons un projet Nuxeo de test à l'aide de Nuxeo CLI :

    # mkdir nuxeo-s2i-sample
    # cd nuxeo-s2i-sample
    # nuxeo bootstrap single-module

    ...
         info You'll be prompted for generation of:
         info   nuxeo-s2i-sample-core: single-module

       create Generate Module: nuxeo-s2i-sample-core

       create Generating Single module
         info   Parameters: Parent group, Parent artifact, Parent version, Nuxeo version, Project group, Project artifact, Project version, Project description
    ? Parent Group id (use white space to cancel default value.): org.nuxeo
    ? Parent Artifact id: nuxeo-addons-parent
    ? Parent Version: 9.2
    ? Project Group id: org.nuxeo.sample
    ? Project Artifact id: nuxeo-s2i-sample
    ? Project version: 1.0-SNAPSHOT
    ? Project description: Sample project to demonstrate S2I usage
       create pom.xml
       create src/main/resources/META-INF/MANIFEST.MF
       create src/main/java/org/nuxeo/sample/package-info.java
       create src/test/resources/jndi.properties
       create src/test/resources/log4j.xml
         info You can start editing code or you can continue with calling another generator (nuxeo bootstrap [<generator>..])

Cela vous permet de créer un projet Nuxeo vide que vous pouvez déployer avec Maven. Au lieu de ça, nous allons invoquer le client s2i pour qu'il déploie une image Docker Nuxeo contenant ce bundle.

s2i build . nuxeo/s2i:9.2 nuxeo-s2i-sample

Après un moment, vous obtiendrez une image Docker nuxeo-s2i-sample que vous pouvez exécuter comme l'image Nuxeo avec :

docker run --rm -ti -p 8080:8080 nuxeo-s2i-sample

Vérifiez si votre package a été déployé ou non en vous rendant dans l'Admin Center à partir de la zone d'informations de la distribution.

Utiliser Source to Image dans OpenShift

OpenShift sait comment utiliser s2i. Il nous suffit de créer des ressources qui référencent notre image Nuxeo S2I. Utilisez un ImageStream pour cette étape :

    apiVersion: v1
    kind: ImageStream
    metadata:
      name: nuxeo-s2i
      annotations:
        openshift.io/display-name: Nuxeo Source to image
    spec:
      tags:
        - name: "latest"
          annotations:
            openshift.io/display-name: Nuxeo (latest)
            description: |
              Build and run a Nuxeo application. For more information about using this builder image, see https://github.com/nuxeo-sandbox/nuxeo-s2i

              WARNING: By selecting this tag, your application will automatically update to use the latest version of Ruby available on OpenShift, including major versions updates.
            iconClass: icon-java
            tags: builder, java, nuxeo
            supports: nuxeo
            sampleRepo: https://github.com/nuxeo/nuxeo-sample-project
          from:
            kind: ImageStreamTag
            name: "9.3-SNAPSHOT"            
        - name: "9.3-SNAPSHOT"
          annotations:
            openshift.io/display-name: Nuxeo 9.3-SNAPSHOT
            description: |
              Build and run a Nuxeo application. For more information about using this builder image, see https://github.com/nuxeo-sandbox/nuxeo-s2i
            iconClass: icon-java
            tags: builder, java, nuxeo
            supports: nuxeo
            sampleRepo: https://github.com/nuxeo/nuxeo-sample-project
          from:
            kind: DockerImage
            name: nuxeo/s2i:master

On peut ensuite utiliser le bouton Add project pour créer un nouveau projet Nuxeo en sélectionnant l'ImageStream que nous venons de créer.

Nous allons référencer l'adresse du référentiel GitHub de notre projet Nuxeo :

Et c'est tout ! OpenShift va invoquer l'image S2I, distribuer notre projet Maven, trouver l'artéfact dans le répertoire cible, l'ajouter au répertoire bundles de notre image Docker Nuxeo, distribuer l'image et la déployer dans une DeploymentConfig.

Après avoir lancé Nuxeo Platform, vérifiez si le package est installé avec rsh dans le conteneur et que la liste de packages installée se trouve dans le répertoire bundles.

# oc get po
NAME                  READY     STATUS      RESTARTS   AGE
nuxeosample-1-7z7s2   1/1       Running     0          5m
# oc rsh nuxeosample-1-7z7s2
nux...z7s2:/opt/nuxeo/server$ ls /opt/nuxeo/server/nxserver/bundles | grep sample
nuxeo-s2i-sample-1.0-SNAPSHOT.jar

Déploiement continu

Notre projet Nuxeo est vide et nous voulons lui ajouter un comportement et le déployer à la place du pod actuel. Nous pourrions transmettre nos modifications à GitHub et lancer un nouveau build qui déclencherait un nouveau déploiement. Mais on peut également éviter cette étape manuelle en utilisant un webhook.

Dans OpenShift, nous allons éditer le build Nuxeo et ouvrir le panneau de paramètres avancés. Ensuite, il suffit de chercher la zone Triggers et de copier la terminaison du webhook GitHub.

Nous allons configurer dans GitHub un webhook qui ciblera cette terminaison à chaque commit.

Nous allons maintenant créer un listener qui mettra à jour la description de chaque nouvelle note créée. Lors de la création d'un document Note dans Nuxeo, sa description sera mise à jour avec le texte « Happily deployed thru s2i. »

# nuxeo bootstrap listener
...
create Generating Listener
    info Parameters: Listener package, Listener class name, Trigger on event, Custom events, Is it an asynchronous listener, Is it a post commit listener
? Listener package: org.nuxeo.sample
? Listener class name: NoteCreationListener
? Trigger on events: aboutToCreate
? Is it an asynchronous Listener? No
? Is it a post-commit Listener? No
    info Maven dependency: org.nuxeo.runtime:nuxeo-runtime-test:::test
        info Maven dependency: org.nuxeo.ecm.platform:nuxeo-platform-test:::test
        info Maven dependency: org.nuxeo.ecm.core:nuxeo-core-event
        force pom.xml
        force src/main/resources/META-INF/MANIFEST.MF
create src/main/java/org/nuxeo/sample/NoteCreationListener.java
create src/test/java/org/nuxeo/sample/TestNoteCreationListener.java
create src/main/resources/OSGI-INF/notecreationlistener-listener-contrib.xml
info You can start editing code or you can continue with calling another generator (nuxeo bootstrap [<generator>..])

Éditez ensuite le code Java du fichier src/main/java/org/nuxeo/sample/NoteCreationListener.java pour que le listener mette le document à jour.

public class NoteCreationListener implements EventListener {

    @Override
    public void handleEvent(Event event) {
        EventContext ctx = event.getContext();
        if (!(ctx instanceof DocumentEventContext)) {
            return;
        }

        DocumentEventContext docCtx = (DocumentEventContext) ctx;
        DocumentModel doc = docCtx.getSourceDocument();

        // Add some logic starting from here.
        doc.setPropertyValue("dc:description","Happily deployed thru s2i");
    }
}

Après un commit sur GitHub, Openshift lance le build et le déploiement. Pour vérifier que tout fonctionne, nous allons créer un document Note de test. Et voilà notre description mise à jour !

Pour aller plus loin avec l'image S2I

Dans sa forme basique, l'image S2I prend les JAR présents dans le répertoire target et les copie dans le répertoire $NUXEO_HOME/nxserver/bundles. Ça peut être problématique si vous disposez d'un projet Maven multimodule. Pour faciliter la configuration, vous pouvez ajouter un fichier manifeste .nuxeo-s2i à la racine du projet spécifiant les éléments à déployer. Et vous pouvez bien sûr spécifier un package Nuxeo. Voici un exemple de fichier test :

# Directory where to find JAR artifacts to deploy
#ARTIFACT_DIR=target

# Nuxeo package to deploy
#NUXEO_PACKAGE=sample-package/target/sample-package-*.zip

# Whether to start Nuxeo in a test phase and do some smoke tests
#NUXEO_SMOKE_TEST=false

Ce n'est que le début et nous allons certainement ajouter d'autres fonctionnalités, comme l'exécution de tests d'intégration Maven sur l'instance Nuxeo déployée. N'hésitez pas à nous envoyer vos retours !

Enfin, si notre script assemble ne répond pas à vos besoins, vous pouvez toujours spécifier votre propre script en suivant les instructions Source-to-Image.

Un processus de développement continu

S2I peut être considéré comme un outil très simple permettant de transformer le code en image Docker exécutable. Mais avec OpenShift, il nous permet d'automatiser complètement notre expérience de développement et de déploiement.

L'image S2I Nuxeo est toujours en cours de finalisation. Une fois combinée avec Nuxeo Studio, vous aurez à votre disposition une chaîne complète vous permettant de développer rapidement vos applications. N'oubliez pas de nous faire part de vos retours sur vos essais avec les différentes options dont nous avons parlé aujourd'hui.