Diffusion continue de votre solution InterSystems à l'aide de GitLab - Partie VIII : CD utilisant l'ICM
Dans cette série d'articles, j'aimerais présenter et discuter de plusieurs approches possibles pour le développement de logiciels avec les technologies d'InterSystems et GitLab. J'aborderai des sujets tels que:
- Git 101
- Flux Git (processus de développement)
- Installation de GitLab
- Flux de travail GitLab
- Diffusion continue
- Installation et configuration de GitLab
- GitLab CI/CD
- Pourquoi des conteneurs?
- Infrastructure de conteneurs
- CD utilisant des conteneurs
- CD utilisant ICM
Dans cet article, nous allons créer une diffusion continue avec InterSystems Cloud Manager. ICM est une solution de déploiement et de provisionnement en nuage pour les applications basées sur InterSystems IRIS. Il vous permet de définir la configuration de déploiement souhaitée et ICM la provisionne automatiquement. Pour plus d'informations, consultez : First Look : ICM.
Flux de Travail
Dans notre Diffusion continue, nous allons :
- Introduire le code dans le référentiel GitLab
- Construire l' image docker
- Publier l'image dans le registre docker
- La tester sur un serveur de test
- Si les tests sont positifs, déployer sur un serveur de production
Ou en format graphique :

Comme vous pouvez le voir, c'est à peu près la même chose, sauf que nous utiliserons ICM au lieu de gérer les conteneurs Docker manuellement.
Configuration ICM
Avant de commencer à mettre à jour les conteneurs, il faut les provisionner. Pour ce faire, il faut déterminer les fichiers defaults.json et definitions.json, qui décrivent notre architecture. Je fournirai ces 2 fichiers pour un serveur LIVE, les definitions pour un serveur TEST sont les mêmes, les valeurs defaults sont les mêmes à l'exception des valeurs Tag et SystemMode .
defaults.json:
{
"Provider": "GCP",
"Label": "gsdemo2",
"Tag": "LIVE","SystemMode": "LIVE",
"DataVolumeSize": "10",
"SSHUser": "sample",
"SSHPublicKey": "/icmdata/ssh/insecure.pub",
"SSHPrivateKey": "/icmdata/ssh/insecure",
"DockerImage": "eduard93/icmdemo:master",
"DockerUsername": "eduard93",
"DockerPassword": "...",
"TLSKeyDir": "/icmdata/tls",
"Credentials": "/icmdata/gcp.json",
"Project": "elebedyu-test",
"MachineType": "n1-standard-1",
"Region": "us-east1",
"Zone": "us-east1-b",
"Image": "rhel-cloud/rhel-7-v20170719",
"ISCPassword": "SYS",
"Mirror": "false"
}definitions.json
[
{
"Role": "DM",
"Count": "1",
"ISCLicense": "/icmdata/iris.key"
}
]Dans le conteneur ICM, le dossier /icmdata est installé à partir de l'hôte et :
- Les définitions du serveur TEST sont placées dans le dossier /icmdata/test
- Les définitions du serveur LIVE sont placées dans le dossier /icmdata/live
Après avoir obtenu toutes les clés requises :
keygenSSH.sh /icmdata/ssh keygenTLS.sh /icmdata/tls
Et avoir placé les fichiers requis dans /icmdata:
- iris.key
- gcp.json (pour le déploiement sur Google Cloud Platform)
Appelez ICM pour provisionner vos instances :
cd /icmdata/test icm provision icm run cd /icmdata/live icm provision icm run
Cela permet de provisionner un serveur TEST et un serveur LIVE avec une instance autonome d'InterSystems IRIS sur chacun d'entre eux.
Veuillez vous référer à ICM First Look pour un guide plus détaillé.
Construction
D'abord, nous devons construire notre image.
Notre code sera, comme d'habitude, stocké dans le référentiel, la configuration CD - dans gitlab-ci.yml mais en plus (pour renforcer la sécurité) nous stockerons plusieurs fichiers spécifiques au serveur sur un serveur build.
iris.key
Clé de licence. Elle peut également être téléchargée lors du conteneur build au lieu d'être stockée sur un serveur. Il n'est pas très sûr de la stocker dans le référentiel.
pwd.txt
Fichier contenant le mot de passe par défaut. Encore une fois, il n'est pas très sûr de la stocker dans le référentiel. De plus, si vous hébergez l'environnement de production (prod) sur un serveur séparé, il pourrait avoir un mot de passe par défaut différent.
load_ci_icm.script
Script initial qui :
- Télécharge l'installateur
- L'installateur effectue l'initialisation de l'application
- Télécharge le code
set dir = ##class(%File).NormalizeDirectory($system.Util.GetEnviron("CI_PROJECT_DIR"))
do ##class(%SYSTEM.OBJ).Load(dir _ "Installer/Global.cls","cdk")
do ##class(Installer.Global).init()
haltNotez que la première ligne est intentionnellement laissée vide.
Certains éléments diffèrent des exemples précédents. Tout d'abord, nous n'activons pas l'authentification du système d'exploitation car ICM interagit avec le conteneur plutôt qu'avec GitLab directement. Ensuite, j'utilise le manifeste de l'installateur pour initialiser notre application afin de montrer différentes approches de l'initialisation. Pour en savoir plus sur Installer, consultez cet article. Enfin, nous publierons notre image dans un Docher Hub en tant que dépôt privé.
Installateur/Global.cls
Notre manifeste d'installateur se présente comme suit :
<Manifest>
<Log Text="Creating namespace ${Namespace}" Level="0"/>
<Namespace Name="${Namespace}" Create="yes" Code="${Namespace}" Ensemble="" Data="IRISTEMP">
<Configuration>
<Database Name="${Namespace}" Dir="${MGRDIR}/${Namespace}" Create="yes" MountRequired="true" Resource="%DB_${Namespace}" PublicPermissions="RW" MountAtStartup="true"/>
</Configuration>
<Import File="${Dir}MyApp" Recurse="1" Flags="cdk" IgnoreErrors="1" />
</Namespace>
<Log Text="Mapping to USER" Level="0"/>
<Namespace Name="USER" Create="no" Code="USER" Data="USER" Ensemble="0">
<Configuration>
<Log Text="Mapping MyApp package to USER namespace" Level="0"/>
<ClassMapping From="${Namespace}" Package="MyApp"/>
</Configuration>
<CSPApplication Url="/" Directory="${Dir}client" AuthenticationMethods="64" IsNamespaceDefault="false" Grant="%ALL" />
<CSPApplication Url="/myApp" Directory="${Dir}" AuthenticationMethods="64" IsNamespaceDefault="false" Grant="%ALL" />
</Namespace>
</Manifest>Et il implémente les modifications suivants:
- Crée l'espace de noms de l'application.
- Crée la base de données du code de l'application (les données sont stockées dans la base de données USER).
- télécharge le code dans la base de données du code de l'application.
- Associe le paquet MyApp à l'espace de noms USER.
- Crée 2 applications web: pour HTML et pour REST.
gitlab-ci.yml
Passons maintenant à la configuration de la diffusion continue :
build image:
stage: build
tags:
- master
script:
- cp -r /InterSystems/mount ci
- cd ci
- echo 'SuperUser' | cat - pwd.txt load_ci_icm.script > temp.txt
- mv temp.txt load_ci.script
- cd ..
- docker build --build-arg CI_PROJECT_DIR=$CI_PROJECT_DIR -t eduard93/icmdemo:$CI_COMMIT_REF_NAME .Que se passe-t-il ici?
Tout d'abord, comme docker build ne peut accéder qu'aux sous-référentiel d'un référentiel de base build qui est dans notre cas la racine du référentiel, nous devons copier notre référentiel "secret" (celui qui contient iris.key, pwd.txt et load_ci_icm.script) dans le référentiel cloné.
Ensuite, le premier accès au terminal nécessite un utilisateur/pass, nous les ajouterions donc à load_ci.script (c'est ce que la ligne vide au début de load_ci.script est pour btw).
Enfin, nous construisons l'image docker et la balisons de manière appropriée : eduard93/icmdemo:$CI_COMMIT_REF_NAME
où $CI_COMMIT_REF_NAME est le nom d'une branche courante. Notez que la première partie de la balise de l'image doit être nommée de la même manière que le nom du projet dans GitLab, de manière à ce qu'elle puisse être vue dans l'onglet Registre de GitLab (les instructions sur le balisage sont disponibles dans l'onglet Registre).
Dockerfile
La construction de l'image docker se fait en utilisant Dockerfile, la voici :
FROM intersystems/iris:2018.1.1-released ENV SRC_DIR=/tmp/src ENV CI_DIR=$SRC_DIR/ci ENV CI_PROJECT_DIR=$SRC_DIR COPY ./ $SRC_DIR RUN cp $CI_DIR/iris.key $ISC_PACKAGE_INSTALLDIR/mgr/ \ && cp $CI_DIR/GitLab.xml $ISC_PACKAGE_INSTALLDIR/mgr/ \ && $ISC_PACKAGE_INSTALLDIR/dev/Cloud/ICM/changePassword.sh $CI_DIR/pwd.txt \ && iris start $ISC_PACKAGE_INSTANCENAME \ && irissession $ISC_PACKAGE_INSTANCENAME -U%SYS < $CI_DIR/load_ci.script \ && iris stop $ISC_PACKAGE_INSTANCENAME quietly
Nous partons du conteneur iris de base.
Tout d'abord, nous copions notre référentiel (ainsi que le référentiel "secret") à l'intérieur du conteneur.
Ensuite, nous copions la clé de licence dans le référentiel mgr.
Ensuite, nous remplaçons le mot de passe par la valeur du fichier pwd.txt. Notez que le fichier pwd.txt est supprimé lors de cette opération.
Ensuite, l'instance est démarrée et le fichier load_ci.script est exécuté.
Finalement, l'instance iris est arrêtée.
Notez que j'utilise l' exécuteur Shell GitLab et non exécuteur Docker. L'exécuteur Docker est utilisé lorsque vous avez besoin de quelque chose de l'intérieur de l'image, par exemple, vous créez une application Android dans un conteneur java et vous n'avez besoin que d'un apk. Dans notre cas, il nous faut un conteneur complet et pour cela nous avons besoin de l'exécuteur Shell. Nous exécutons donc des commandes Docker via l'exécuteur GitLab Shell.
Publication
Maintenant, publions notre image dans un Docker Hub
publish image:
stage: publish
tags:
- master
script:
- docker login -u eduard93 -p ${DOCKERPASSWORD}
- docker push eduard93/icmdemo:$CI_COMMIT_REF_NAMENotez la variable ${DOCKERPASSWORD}, c'est un GitLab variable secrète. Nous pouvons les ajouter dans GitLab > Projet > Paramètres > CI/CD > Variables:

Les journaux de tâches ne contiennent pas non plus de valeur de mot de passe :
Running with gitlab-runner 10.6.0 (a3543a27)
on icm 82634fd1
Using Shell executor...
Running on docker...
Fetching changes...
Removing ci/
HEAD is now at 8e24591 Add deploy to LIVE
Checking out 8e245910 as master...Skipping Git submodules setup$ docker login -u eduard93 -p ${DOCKERPASSWORD}
WARNING! Using --password via the CLI is insecure. Use --password-stdin.
Login Succeeded
$ docker push eduard93/icmdemo:$CI_COMMIT_REF_NAME
The push refers to repository [docker.io/eduard93/icmdemo]
master: digest: sha256:d1612811c11154e77c84f0c08a564a3edeb7ddbbd9b7acb80754fda97f95d101 size: 2620
Job succeeded
et sur Docker Hub, nous pouvons voir notre nouvelle image :

Exécution
Nous avons notre image, maintenant nous allons l'exécuter sur notre serveur test. Voici le script.
run image:
stage: run
environment:
name: $CI_COMMIT_REF_NAME
tags:
- master
script:
- docker exec icm sh -c "cd /icmdata/test && icm upgrade -image eduard93/icmdemo:$CI_COMMIT_REF_NAME"Avec ICM, il suffit d'exécuter une seule commande (icm upgrade) pour mettre à jour le déploiement existant. Nous l'appelons en exécutant "docker exec icm sh -c " qui exécute une commande spécifiée à l'intérieur du conteneur icm. D'abord, nous passons à /icmdata/test où notre définition de déploiement ICM est définie pour un serveur TEST. Ensuite nous appelons icm upgrade pour remplacer un conteneur existant par un nouveau conteneur.
Test
Exécutons quelques tests.
test image:
stage: test
tags:
- master
script:
- docker exec icm sh -c "cd /icmdata/test && icm session -namespace USER -command 'do \$classmethod(\"%UnitTest.Manager\",\"RunTest\",\"MyApp/Tests\",\"/nodelete\")' | tee /dev/stderr | grep 'All PASSED' && exit 0 || exit 1"Encore une fois, nous exécutons une commande à l'intérieur de notre conteneur icm. La session icm exécute une commande sur un nœud déployé. La commande exécute des tests unitaires. Ensuite, il envoie tous les résultats à l'écran et à grep pour trouver les résultats des tests unitaires et quitter le processus avec succès ou avec une erreur.
Déploiement
Le déploiement sur un serveur de production est absolument identique au déploiement sur un serveur test, à l'exception d'un autre répertoire pour la définition du déploiement LIVE. En cas d'échec des tests, cette étape n'est pas exécutée.
deploy image:
stage: deploy
environment:
name: $CI_COMMIT_REF_NAME
tags:
- master
script:
- docker exec icm sh -c "cd /icmdata/live && icm upgrade -image eduard93/icmdemo:$CI_COMMIT_REF_NAME"