1950 lines
		
	
	
		
			69 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			1950 lines
		
	
	
		
			69 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
| #!/bin/bash
 | |
| # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
 | |
| source "$(dirname "$0")/lib/ulib/auto" || exit 1
 | |
| urequire pff
 | |
| 
 | |
| function display_help() {
 | |
|     uecho "$scriptname: outil pour faciliter l'utilisation de docker
 | |
| 
 | |
| USAGE
 | |
|     $scriptname CMDs...
 | |
| 
 | |
| COMMANDES
 | |
|     get-profile
 | |
|         Afficher le profil courant
 | |
|     b|build [SERVICE]
 | |
|         Construire les images
 | |
|     p|push
 | |
|     p|push [SERVICES...]
 | |
|         La première syntaxe est utilisable avec un projet docker. Elle permet de
 | |
|         pousser l'image qui a été construite avec build vers le serveur
 | |
|         La deuxième syntaxe est utilisée avec un projet docker-compose. Elle
 | |
|         permet de pousser les images correspondant aux services qui ont été
 | |
|         construit vers le serveur.
 | |
|     s|start [SERVICE]
 | |
|         Démarrer le(s) service(s)
 | |
|     k|stop [SERVICE]
 | |
|         Arrêter le(s) service(s)
 | |
|     1|up
 | |
|         Créer l'environnement, démarrer les services et suivre les logs de façon
 | |
|         interactive.
 | |
|         Vaguement équivalent à -- start -- logs
 | |
|     l|logs [SERVICE]
 | |
|         Afficher les logs
 | |
|     0|down
 | |
|         Arrêter les services et supprimer l'environnement
 | |
|     r|run SERVICE [COMMAND]
 | |
|         Démarrer le service en mode interactif avec la commande spécifiée
 | |
|         Les options suivantes sont supportées, mais il faut les spécifier avant
 | |
|         SERVICE:
 | |
|         * pour docker et docker-compose: --volume
 | |
|         * uniquement pour docker-compose: --detach, -e, --label, --no-deps,
 | |
|           --service-ports, --use-aliases
 | |
|         Par défaut, --rm est activé; utiliser --no-rm pour ne pas supprimer le
 | |
|         container après utilisation.
 | |
|     x|exec SERVICE COMMAND
 | |
|         Lancer une commande dans le container correspondant au service spécifié,
 | |
|         qui doit être en fonctionnement
 | |
|     d|brd
 | |
|         Construire les images (comme avec build), démarrer les services et
 | |
|         suivre les logs de façon interactive (comme avec up). Dès que l'on
 | |
|         arrête l'affichage des logs avec Ctrl+C, arrêter les services et
 | |
|         supprimer l'environnement (comme avec down)
 | |
|         Vaguement équivalent à -- build -- start [args] -- logs
 | |
|                       suivi de -- down
 | |
|     bs
 | |
|         Construire les images (comme avec build) puis démarrer les services
 | |
|         (comme avec start)
 | |
|         Equivalent à -- build -- start [args]
 | |
|     br SERVICE [COMMAND]
 | |
|         Construire les images (comme avec build) puis démarrer le service avec
 | |
|         la commande spécifiée (comme avec run)
 | |
|         Equivalent à -- build -- run [args]
 | |
|     y|deploy [args...]
 | |
|         (Re)déployer un stack. Cette commande ne fonctionne qu'en mode swarm.
 | |
|         Implique --stack
 | |
|     by|bd [args...]
 | |
|         Equivalent à --stack -- build -- deploy args...
 | |
|         Utilisable notamment en développement
 | |
|     bp [args...]
 | |
|         Equivalent à --stack -- build -- push args...
 | |
|     bpy|bpd [args...]
 | |
|         Equivalent à --stack -- build -- push -- deploy args...
 | |
|     service COMMAND SERVICE [args...]
 | |
|         Frontend pour 'docker service COMMAND args... SERVICE'
 | |
|         Cette commande ne fonctionne qu'en mode swarm. Il n'est pas nécessaire
 | |
|         de préfixer le nom du service avec le nom du stack, pour être cohérent
 | |
|         avec les autres commandes
 | |
|         IMPORTANT: notez que les arguments sont placés avant le nom du service.
 | |
|         Celà signifie qu'on ne peut spécifier que des options à la commande.
 | |
|         Penser aussi à protéger ces options de l'analyse eg.
 | |
|             $scriptname -- service logs web -f
 | |
|         Pour des cas d'utilisation plus complexe, il faut lancer directement
 | |
|         docker service
 | |
|     u|update SERVICE [args...]
 | |
|         Mettre à jour un service, équivalent à 'service update SERVICE'
 | |
|     scale SERVICE=REPLICAS [args...]
 | |
|         Mettre à jour le nom de réplicas d'un service, équivalent à la commande
 | |
|         'service scale SERVICE=REPLICAS'
 | |
|     ip|show-ip [SERVICE]
 | |
|         Afficher l'adresse IP interne du service
 | |
|     systemd|systemd-unit
 | |
|         Générer une unité systemd qui démarre les services. A priori, ce n'est
 | |
|         nécessaire que si aucune politique de redémarrage n'a été définie.
 | |
|     ps [filter|name=value]
 | |
|         Afficher les containers en cours d'exécution
 | |
|         Le filtre est une expression régulière de type awk qui est mise en
 | |
|         correspondace avec les noms de l'image et de la tâche.
 | |
|         Il est aussi possible d'utiliser un filtre docker de la forme name=value
 | |
|             - ancestor=(<image-name>[:tag]|<image-id>| <image@digest>)
 | |
|               containers created from an image or a descendant.
 | |
|             - before=(<container-name>|<container-id>)
 | |
|             - expose=(<port>[/<proto>]|<startport-endport>/[<proto>])
 | |
|             - exited=<int> an exit code of <int>
 | |
|             - health=(starting|healthy|unhealthy|none)
 | |
|             - id=<ID> a container's ID
 | |
|             - is-task=(true|false)
 | |
|             - label=<key> or label=<key>=<value>
 | |
|             - name=<string> a container's name
 | |
|             - network=(<network-id>|<network-name>)
 | |
|             - publish=(<port>[/<proto>]|<startport-endport>/[<proto>])
 | |
|             - since=(<container-name>|<container-id>)
 | |
|             - status=(created|restarting|removing|running|paused|exited)
 | |
|             - volume=(<volume name>|<mount point destination>)
 | |
|     ls [filter|name=value]
 | |
|         Lister les images actuellement présentes
 | |
|         Le filtre est une expression régulière de type awk qui est mise en
 | |
|         correspondance avec le nom de l'image. Un suffixe :tag permet de ne
 | |
|         sélectionner que les images correspondant au filtre qui ont le tag
 | |
|         spécifié.
 | |
|         Il est aussi possible d'utiliser un filtre docker de la forme name=value
 | |
|             - dangling=(true|false) - find unused images
 | |
|             - label=<key> or label=<key>=<value>
 | |
|             - before=(<image-name>[:tag]|<image-id>| <image@digest>)
 | |
|             - since=(<image-name>[:tag]|<image-id>| <image@digest>)
 | |
|             - reference=(pattern of an image reference)
 | |
|     pull filter
 | |
|         Mettre à jour une ou plusieurs images
 | |
|         Le filtre est une expression régulière de type awk qui est mise en
 | |
|         correspondance avec le nom de l'image. Un suffixe :tag permet de ne
 | |
|         sélectionner que les images correspondant au filtre qui ont le tag
 | |
|         spécifié.
 | |
|     rm filter
 | |
|         Supprimer une ou plusieurs images
 | |
|         Le filtre est une expression régulière de type awk qui est mise en
 | |
|         correspondance avec le nom de l'image. Un suffixe :tag permet de ne
 | |
|         sélectionner que les images correspondant au filtre qui ont le tag
 | |
|         spécifié.
 | |
|     X|prune
 | |
|         Supprimer les containers et les images inutilisées
 | |
| 
 | |
|     composer|ci|cu|cr|cs [args...]
 | |
|         Frontend pour lancer composer à l'intérieur d'un container. Les
 | |
|         commandes 'ci', 'cu', 'cr', 'cs' sont des alias pour 'composer install',
 | |
|         'composer update', 'composer rshell' et 'composer shell' respectivement
 | |
|         S'il existe un fichier .composer.conf dans le répertoire du projet, il
 | |
|         est sourcé. Ce fichier définit des variables qui indiquent comment la
 | |
|         commande composer est lancée. Les variables suivantes peuvent être
 | |
|         définies:
 | |
|         * COMPOSER_PHP -- Version de PHP en dessous de laquelle COMPOSER_IMAGE
 | |
|           est utilisé. En d'autres termes, c'est la version minimum de PHP
 | |
|           nécessaire pour faire tourner composer. L'idée est que si la version
 | |
|           de PHP installée est suffisante, il n'est pas nécessaire de passer par
 | |
|           une image docker.
 | |
|           Cette valeur doit être spécifiée avec le format de PHP_VERSION_ID i.e
 | |
|           70300 pour PHP 7.3
 | |
|           Spécifier 'any' ou 'force' pour forcer l'utilisation de l'image docker
 | |
|         * COMPOSER_PHP_MAX -- Version de PHP à partir de laquelle COMPOSER_IMAGE
 | |
|           est utilisée. En d'autres termes, c'est la version maximum de PHP, à
 | |
|           partir de laquelle il faut passer par une image docker. L'idée est que
 | |
|           si la version de PHP installée est trop récente, ça peut poser
 | |
|           problème avec le calcul des dépendances.
 | |
|           Cette valeur doit être spécifiée avec le format de PHP_VERSION_ID i.e
 | |
|           70300 pour PHP 7.3
 | |
|           Si la valeur n'est pas spécifiée ou vaut 'none', elle est ignorée.
 | |
|         * COMPOSER_IMAGE -- Image utilisée pour lancer composer. La valeur par
 | |
|           défaut est:
 | |
|             $DEFAULT_COMPOSER_IMAGE
 | |
|           Spécifier 'none' pour lancer directement composer sans passer par une
 | |
|           image docker.
 | |
|           L'image spécifiée doit disposer de la commande 'su-exec' afin de
 | |
|           pouvoir lancer la commande avec l'utilisateur courant. Le répertoire
 | |
|           \$HOME est monté à l'intérieur du container et le script composer.phar
 | |
|           du projet est utilisé le cas échéant.
 | |
|         * COMPOSER_MACHINE -- Nom de la docker machine sur laquelle se connecter
 | |
|           pour lancer l'image docker. La valeur par défaut est -u, ce qui force
 | |
|           l'utilisation de l'instance docker locale.
 | |
|         * COMPOSER_CMD -- Chemin vers l'exécutable composer. Par défaut,
 | |
|           utiliser composer.phar s'il existe dans le répertoire du projet. Sinon
 | |
|           utiliser /usr/bin/composer
 | |
|         * COMPOSER_SETUP -- Liste de commandes à lancer pour configurer le
 | |
|           container. Dans ce cas, un container ayant pour base \$COMPOSER_IMAGE
 | |
|           et nommé d'après le nom du projet est préparé et les commandes
 | |
|           spécifiées y sont lancées. Ce container est réutilisé à chaque fois.
 | |
|           Ce paramétrage est utilisé pour par exemple installer certains
 | |
|           packages nécessaire au projet.
 | |
|         La commande 'rshell' est une extension qui lance un shell bash au lieu
 | |
|         de lancer la commande composer, ce qui permet de faire des opérations
 | |
|         plus complexes si le besoin s'en fait sentir. NB: le shell est lancé
 | |
|         avec l'utilisateur root. La commande alternative 'shell' lance le shell
 | |
|         avec le compte utilisateur.
 | |
|         Pour faciliter l'utilisation dans un script, les premiers arguments
 | |
|         peuvent être utilisés pour redéfinir les variables COMPOSER_*, e.g
 | |
|             $scriptname composer COMPOSER_IMAGE=none install
 | |
| 
 | |
| OPTIONS générales
 | |
|     (ces options sont communes à toutes les commandes)
 | |
|     -d, --chdir PROJDIR
 | |
|         Spécifier le répertoire du projet
 | |
|     -c, --config CONFIG[.yml]
 | |
|         Spécifier le fichier de configuration à utiliser. le fichier de profil
 | |
|         CONFIG.PROFILE.yml est chargé aussi s'il existe.
 | |
|         NB: il n'est pas nécessaire d'ajouter l'extension .yml au nom, cela
 | |
|         permet de faciliter l'utilisation avec l'auto-complétion quand il existe
 | |
|         des fichiers de profil
 | |
|         Si cette option n'est pas spécifiée, docker-compose.yml est utilisé par
 | |
|         défaut (ou avec l'option --stack docker-stack.yml s'il existe)
 | |
|     -p, --profile PROFILE
 | |
|     -P, --prod
 | |
|     -T, --test
 | |
|         Spécifier le profil
 | |
|     -m, --set-machine MACHINE
 | |
|         Choisir l'environnement docker-machine spécifié avant de lancer les
 | |
|         commandes. Utiliser -u pour desélectionner la machine en cours, e.g -m-u
 | |
|     -n, --fake
 | |
|         Ne pas lancer les commandes, simplement les afficher
 | |
|     -e, --build-arg, --env VAR=VALUE
 | |
|         (Re)définir un argument pour le build ou une variable d'environnement
 | |
|     -f, --force
 | |
|         Forcer l'opération (là où cela a du sens)
 | |
|     -h, --host HOST
 | |
|         Spécifier l'hôte pour la commande systemd-unit
 | |
| 
 | |
| OPTIONS build
 | |
|     (ces options ne sont valides que pour les commandes build, brd, bs, bd, bpd)
 | |
|     --stack
 | |
|         Indiquer que le build est fait pour un déploiement avec deploy.
 | |
|         S'il existe un fichier docker-stack.yml, il est utilisé de préférence à
 | |
|         la place de docker-compose.yml. De même, les fichiers de profil de la
 | |
|         forme docker-stack.PROFILE.yml sont utilisés de préférence aux fichiers
 | |
|         docker-compose.PROFILE.yml
 | |
|         Cette option n'est nécessaire qu'avec build puisque les commandes
 | |
|         deploy, bd, bpd et update impliquent --stack
 | |
|     -j, --no-cache
 | |
|         Ne pas utiliser le cache lors du build
 | |
|     -g, --ug, --no-update-apps
 | |
|         ne pas mettre à jour les dépôts dépendants. ces dépôts sont définis dans
 | |
|         le fichier update-apps.conf qui a le format suivant:
 | |
|             DEFAULT_DEVEL_SRCDIR=
 | |
|             DEFAULT_ORIGIN=
 | |
|             DEFAULT_BRANCH=
 | |
|             DEFAULT_COMPOSER_ACTION=
 | |
|             PROFILE_CLEAN=        # fonction de nettoyage spécifique au profil
 | |
|             CLEAN=                # ou... fonction de nettoyage par défaut
 | |
|             APPS=()               # applications à mettre à jour par défaut
 | |
|             PROFILE_APPS=()       # ou... spécifique au profil 'PROFILE'
 | |
|             app_URL=              # url du dépôt
 | |
|             app_DEVEL_SRCDIR=     # répertoire source en mode devel
 | |
|             app_DEST=             # répertoire dans lequel faire le checkout
 | |
|             app_PROFILE_ORIGIN=   # origine spécifique au profil 'PROFILE'
 | |
|             app_ORIGIN=           # ou... origine par défaut de la branche
 | |
|             app_PROFILE_BRANCH=   # branche spécifique au profil 'PROFILE'
 | |
|             app_BRANCH=           # ou... branche par défaut
 | |
|             app_TYPE=             # type de projet (composer|none)
 | |
|             app_AFTER_UPDATE=()   # liste de commandes à lancer après le checkout
 | |
|             app_COMPOSER_ACTION=  # action projet composer (install|update|none)
 | |
|     -u, --uu, --update-apps-only
 | |
|         Ne faire que la mise à jour depuis les dépôts dépendants.
 | |
|     -w, --ww, --update-apps-devel
 | |
|         Faire la mise à jour en mode devel: le projet ainsi que ses fichiers des
 | |
|         répertoires vendor/lib et vendor/ur sont synchronisés via rsync depuis
 | |
|         \$DEFAULT_DEVEL_SRCDIR qui vaut par défaut \$HOME/wop/php
 | |
|     --uo, --update-apps-origin ORIGIN
 | |
|         Spécifier l'origine par défaut pour update-apps
 | |
|     --ub, --update-apps-branch BRANCH
 | |
|         Spécifier la branche par défaut pour update-apps
 | |
| 
 | |
| OPTIONS deploy
 | |
|     -l, --without-registry-auth
 | |
|         Ne pas transporter les informations d'autorisation aux agents swarm
 | |
|         (c'est à dire ne pas utiliser l'option --with-registry-auth)
 | |
| 
 | |
| VARIABLES de update-apps.conf
 | |
|     DEVEL_SRCDIR
 | |
|         répertoire source pour le mode devel. attention, il s'agit du répertoire
 | |
|         du projet, alors que DEFAULT_DEVEL_SRCDIR est le répertoire de base par
 | |
|         défaut des projets
 | |
|     ORIGIN
 | |
|         vaut 'origin' par défaut
 | |
|     BRANCH
 | |
|         vaut 'develop' par défaut
 | |
|     TYPE
 | |
|         vaut 'composer' par défaut si le fichier composer.json existe à la
 | |
|         racine du projet. sinon vaut 'none' par défaut
 | |
|     AFTER_UPDATE
 | |
|         Cette variable est une liste de commandes à lancer après la maj du dépôt
 | |
|         - si le chemin est absolu ou relatif, lancer la commande telle quelle
 | |
|         - s'il n'y a pas de chemin, alors ce doit être le nom d'une fonction
 | |
|           existante auquel on enlève le préfixe update_apps_func_
 | |
|         Au moment où la commande est lancée, le répertoire courant est celui du
 | |
|         projet. Les variables suivantes sont disponibles:
 | |
|             URL=                  # url du dépôt
 | |
|             DEVEL_SRCDIR=         # répertoire source en mode devel
 | |
|             DEST=                 # répertoire dans lequel faire le checkout
 | |
|             ORIGIN=               # origine de la branche
 | |
|             BRANCH=               # branche sélectionnée dans le dépôt
 | |
|             TYPE=                 # type de projet (composer|none)
 | |
|     COMPOSER_ACTION
 | |
|         vaut 'install' par défaut. Indique ce qu'il faut faire pour un projet de
 | |
|         type 'composer' après avoir lancé les commandes de AFTER_UPDATE. Les
 | |
|         directives supportées sont 'install', 'update' et 'none'
 | |
| 
 | |
| FONCTIONS de update-apps.conf
 | |
|     sqlmig [DESTDIR [SRCDIR [NOFIX]]]
 | |
|         Copier les définitions des bases de données au format sqlmig de
 | |
|         SRCDIR/config/sqlmig vers DESTDIR/config/mariadb/sqlmig
 | |
|         Si SRCDIR ne se termine pas par '/config/sqlmig' ou si DESTDIR ne se
 | |
|         termine pas par '/config/mariadb/sqlmig', rajouter ces suffixes
 | |
|         automatiquement, sauf si une valeur NOFIX est spécifiée.
 | |
|     pff [MAPS [PFFDIR]]
 | |
|         Si PFFDIR est un projet pff, mettre à jour le profil pff en fonction du
 | |
|         profil de déploiement.
 | |
|         MAPS détermine le mapping entre profil de déploiement (prod, test,
 | |
|         devel) et le profil pff. Il s'agit d'une liste de valeurs séparées par
 | |
|         des virgules de la forme DEST[:SRC]
 | |
|         - Une valeur de la forme 'DEST:SRC' fait correspondre le profil de
 | |
|           déploiement SRC au profil pff 'DEST'
 | |
|         - Une valeur de la forme 'DEST' force le choix du profil pff DEST quel
 | |
|           que soit le profil de déploiement
 | |
|         - Pour simplifier l'écriture des mappings, les aliases suivants sont
 | |
|           reconnus:"'
 | |
|             PTD        est remplacé par   prod:prod,test:test,devel:devel
 | |
|             PT          "     "      "    prod:prod,test:test
 | |
|         '"Si aucun profil de déploiement ne correspond, le comportement par défaut
 | |
|         est de forcer le premier profil défini dans le projet pff"
 | |
| }
 | |
| 
 | |
| function echo_lines() { local IFS=$'\n'; echo "$*"; }
 | |
| 
 | |
| function get_version() {
 | |
|     local GIT_DIR; unset GIT_DIR
 | |
|     if git rev-parse --git-dir >/dev/null 2>&1; then
 | |
|         local head commit tag
 | |
|         commit="$(git rev-list --tags --max-count=1 2>/dev/null)"
 | |
|         if [ -n "$commit" ]; then
 | |
|             tag="$(git describe --tags "$commit" 2>/dev/null)"
 | |
|             if [ -n "$tag" ]; then
 | |
|                 head="$(git rev-parse HEAD)"
 | |
|                 if [ "$commit" != "$head" ]; then
 | |
|                     echo "$tag-develop"
 | |
|                 else
 | |
|                     echo "$tag"
 | |
|                 fi
 | |
|                 return
 | |
|             fi
 | |
|         fi
 | |
|     elif [ -f VERSION.txt ]; then
 | |
|         cat VERSION.txt
 | |
|     fi
 | |
|     echo develop
 | |
| }
 | |
| 
 | |
| function docker_add_build_arg() {
 | |
|     eval "replace_build_args+=(--build-arg $1=\"$2\"); $1=\"$2\""
 | |
| }
 | |
| function docker_parse_build_args() {
 | |
|     cat "$1" |
 | |
|     grep -v '^#' |
 | |
|     grep -v '^$' |
 | |
|     sed -r 's/([^=]+)=(.*)/\1=\2; replace_build_args+=(--build-arg \1="$\1")/'
 | |
| }
 | |
| function docker_parse_env_args() {
 | |
|     [ -f .build.env ] && eval "$(docker_parse_build_args .build.env)"
 | |
|     [ -f build.env ] && eval "$(docker_parse_build_args build.env)"
 | |
|     [ -n "$PROFILE" -a -f ".build.$PROFILE.env" ] && eval "$(docker_parse_build_args ".build.$PROFILE.env")"
 | |
|     [ -n "$PROFILE" -a -f "build.$PROFILE.env" ] && eval "$(docker_parse_build_args "build.$PROFILE.env")"
 | |
| }
 | |
| function docker_set_env_args() {
 | |
|     [ -f .build.env ] && source ./.build.env
 | |
|     [ -f build.env ] && source ./build.env
 | |
|     [ -n "$PROFILE" -a -f ".build.$PROFILE.env" ] && source "./.build.$PROFILE.env"
 | |
|     [ -n "$PROFILE" -a -f "build.$PROFILE.env" ] && source "./build.$PROFILE.env"
 | |
| }
 | |
| function docker_set_run_args() {
 | |
|     replace_run_args+=(--env-file "$1")
 | |
|     source "$1"
 | |
| }
 | |
| function docker_check_name() {
 | |
|     [ -n "$NAME" ] || die "Vous devez définir NAME dans .build.env"
 | |
| 
 | |
|     if [ "$1" == set_container_name ]; then
 | |
|         project_name="$NAME"
 | |
|         container_name="${project_name//[^a-zA-Z0-9_-]/}"
 | |
|         [ -n "$PROFILE" ] && container_name="${container_name}_$PROFILE"
 | |
|     fi
 | |
| }
 | |
| 
 | |
| function compose_set_project_name() {
 | |
|     local PROJECT_NAME= PROJECT_NAME_REMOVE_SUFFIX=.service PROJECT_NAME_ADD_PROFILE=
 | |
|     [ -f .compose.env ] && source ./.compose.env
 | |
| 
 | |
|     [ -n "$PROJECT_NAME" ] || PROJECT_NAME="$(basename -- "$(pwd)")"
 | |
|     PROJECT_NAME="${PROJECT_NAME%$PROJECT_NAME_REMOVE_SUFFIX}"
 | |
| 
 | |
|     if [ -n "$PROFILE" ]; then
 | |
|         [ -n "$COMPOSE_PROJECT_NAME" ] || COMPOSE_PROJECT_NAME="$PROJECT_NAME${PROJECT_NAME_ADD_PROFILE:+_${PROFILE}}"
 | |
|     else
 | |
|         [ -n "$COMPOSE_PROJECT_NAME" ] || COMPOSE_PROJECT_NAME="$PROJECT_NAME"
 | |
|     fi
 | |
|     export COMPOSE_PROJECT_NAME
 | |
| 
 | |
|     if [ "$1" == set_container_name ]; then
 | |
|         project_name="$PROJECT_NAME"
 | |
|         container_name="${project_name//[^a-zA-Z0-9_-]/}"
 | |
|         [ -n "$PROFILE" -a -n "$PROJECT_NAME_ADD_PROFILE" ] && container_name="${container_name}_$PROFILE"
 | |
|     fi
 | |
| }
 | |
| function compose_set_env_args() {
 | |
|     if [ -n "$CONFIG" ]; then
 | |
|         # autocomplétion friendly
 | |
|         [ ! -f "$CONFIG" -a -f "${CONFIG}yml" ] && CONFIG="${CONFIG}yml"
 | |
|         [ ! -f "$CONFIG" -a -f "$CONFIG.yml" ] && CONFIG="$CONFIG.yml"
 | |
|         ##
 | |
|         replace_env_args+=(-f "$CONFIG")
 | |
|         if [ -n "$PROFILE" -a -f "${CONFIG%.yml}.$PROFILE.yml" ]; then
 | |
|             replace_env_args+=(-f "${CONFIG%.yml}.$PROFILE.yml")
 | |
|         fi
 | |
|     else
 | |
|         if [ -n "$USE_STACK" -a -f docker-stack.yml ]; then
 | |
|             replace_env_args+=(-f docker-stack.yml)
 | |
|         else
 | |
|             replace_env_args+=(-f docker-compose.yml)
 | |
|         fi
 | |
|         if [ -n "$USE_STACK" -a -f docker-stack.override.yml ]; then
 | |
|             replace_env_args+=(-f docker-stack.override.yml)
 | |
|         elif [ -f docker-compose.override.yml ]; then
 | |
|             replace_env_args+=(-f docker-compose.override.yml)
 | |
|         fi
 | |
|         if [ -n "$PROFILE" ]; then
 | |
|             if [ -n "$USE_STACK" -a -f "docker-stack.$PROFILE.yml" ]; then
 | |
|                 replace_env_args+=(-f "docker-stack.$PROFILE.yml")
 | |
|             elif [ -f "docker-compose.$PROFILE.yml" ]; then
 | |
|                 replace_env_args+=(-f "docker-compose.$PROFILE.yml")
 | |
|             fi
 | |
|         fi
 | |
|     fi
 | |
| 
 | |
|     compose_set_project_name "$@"
 | |
| }
 | |
| function docker_set_deploy_args() {
 | |
|     if [ -n "$CONFIG" ]; then
 | |
|         # autocomplétion friendly
 | |
|         [ ! -f "$CONFIG" -a -f "${CONFIG}yml" ] && CONFIG="${CONFIG}yml"
 | |
|         [ ! -f "$CONFIG" -a -f "$CONFIG.yml" ] && CONFIG="$CONFIG.yml"
 | |
|         ##
 | |
|         replace_deploy_args+=(-c "$CONFIG")
 | |
|         if [ -n "$PROFILE" -a -f "${CONFIG%.yml}.$PROFILE.yml" ]; then
 | |
|             replace_deploy_args+=(-c "${CONFIG%.yml}.$PROFILE.yml")
 | |
|         fi
 | |
|     else
 | |
|         if [ -n "$USE_STACK" -a -f docker-stack.yml ]; then
 | |
|             replace_deploy_args+=(-c docker-stack.yml)
 | |
|         else
 | |
|             replace_deploy_args+=(-c docker-compose.yml)
 | |
|         fi
 | |
|         if [ -n "$USE_STACK" -a -f docker-stack.override.yml ]; then
 | |
|             replace_deploy_args+=(-c docker-stack.override.yml)
 | |
|         elif [ -f docker-compose.override.yml ]; then
 | |
|             replace_deploy_args+=(-c docker-compose.override.yml)
 | |
|         fi
 | |
|         if [ -n "$PROFILE" ]; then
 | |
|             if [ -n "$USE_STACK" -a -f "docker-stack.$PROFILE.yml" ]; then
 | |
|                 replace_deploy_args+=(-c "docker-stack.$PROFILE.yml")
 | |
|             elif [ -f "docker-compose.$PROFILE.yml" ]; then
 | |
|                 replace_deploy_args+=(-c "docker-compose.$PROFILE.yml")
 | |
|             fi
 | |
|         fi
 | |
|     fi
 | |
| 
 | |
|     compose_set_project_name "$@"
 | |
| }
 | |
| 
 | |
| function host_run() {
 | |
|     # lancer le script $2..@ sur l'hôte $1
 | |
|     # si $1 n'est pas défini ou est le nom de l'hôte local ou vaut 'localhost',
 | |
|     # lancer le script en local avec les droits root
 | |
|     # sinon, si docker-machine existe, l'hôte doit correspondre à la machine active
 | |
|     # sinon, lancer inconditionnellement le script sur l'hôte distant
 | |
|     local host="$1" script="$2"; shift; shift
 | |
|     if [ -n "$host" -a "$host" != localhost ]; then
 | |
|         if check_hostname "$host"; then
 | |
|             estep "Lancement de $script localement"
 | |
|             runscript_as_root "$script" "$@"
 | |
|         elif progexists docker-machine; then
 | |
|             if [ "${host%%.*}" == "$DOCKER_MACHINE_NAME" ]; then
 | |
|                 estep "Copie du script vers root@$host"
 | |
|                 scp "$script" "root@$host:/tmp/tmp-dk-service-script" || die
 | |
|                 estep "Lancement du script à distance"
 | |
|                 local -a args; args=(/tmp/tmp-dk-service-script "$@")
 | |
|                 ssh -qt "root@$host" "$(qvals "${args[@]}"); rm -f /tmp/tmp-dk-service-script"
 | |
|             else
 | |
|                 ewarn "La machine active ($DOCKER_MACHINE_NAME) n'est pas la destination ($host)"
 | |
|             fi
 | |
|         else
 | |
|             estep "Copie du script vers root@$host"
 | |
|             scp "$script" "root@$host:/tmp/tmp-dk-service-script" || die
 | |
|             estep "Lancement du script à distance"
 | |
|             local -a args; args=(/tmp/tmp-dk-service-script "$@")
 | |
|             ssh -qt "root@$host" "$(qvals "${args[@]}"); rm -f /tmp/tmp-dk-service-script"
 | |
|         fi
 | |
|     else
 | |
|         estep "Lancement de $script localement"
 | |
|         runscript_as_root "$script" "$@"
 | |
|     fi
 | |
| }
 | |
| function local_run() {
 | |
|     # lancer le script $2..@ sur l'hôte $1 uniquement si c'est l'hôte courant
 | |
|     local host="$1" script="$2"; shift; shift
 | |
|     if [ -n "$host" ]; then
 | |
|         if ! check_hostname "$host"; then
 | |
|             eerror "Cette commande doit obligatoirement être lancée depuis l'hôte $host"
 | |
|             return 1
 | |
|         fi
 | |
|     fi
 | |
|     estep "Lancement de $script localement"
 | |
|     runscript_as_root "$script" "$@"
 | |
| }
 | |
| 
 | |
| BUILD_UPDATE_APPS=
 | |
| BUILD_BUILD=
 | |
| UPDATE_APPS_ORIGIN=
 | |
| UPDATE_APPS_BRANCH=
 | |
| function build_set_options() {
 | |
|     BUILD_BUILD=
 | |
|     BUILD_UPDATE_APPS=
 | |
|     BUILD_UPDATE_DEVEL=
 | |
|     [[ "$1" == *b* ]] && BUILD_BUILD=1
 | |
|     [[ "$1" == *u* ]] && BUILD_UPDATE_APPS=1
 | |
|     [[ "$1" == *w* ]] && BUILD_UPDATE_DEVEL=1
 | |
|     UPDATE_APPS_ORIGIN="$2"
 | |
|     UPDATE_APPS_BRANCH="$3"
 | |
| }
 | |
| 
 | |
| function update_apps_func_sqlmig() {
 | |
|     local destdir="$1" srcdir="$2" nofix="$3"
 | |
|     [ -n "$destdir" ] || destdir=db
 | |
|     [ -n "$srcdir" ] || srcdir="$DEST"
 | |
| 
 | |
|     if [ -z "$nofix" ]; then
 | |
|         [ "${destdir%/config/mariadb/sqlmig}" != "$destdir" ] || destdir="$destdir/config/mariadb/sqlmig"
 | |
|         [ "${srcdir%/config/sqlmig}" != "$srcdir" ] || srcdir="$srcdir/config/sqlmig"
 | |
|     fi
 | |
| 
 | |
|     if [ ! -d "$srcdir" ]; then
 | |
|         eerror "$srcdir: répertoire introuvable"
 | |
|         return 1
 | |
|     fi
 | |
| 
 | |
|     local -a sqlmigs; local sqlmig name
 | |
|     array_lsall sqlmigs "$srcdir"
 | |
|     mkdir -p "$destdir" || return 1
 | |
|     for sqlmig in "${sqlmigs[@]}"; do
 | |
|         if [ -d "$sqlmig" ]; then
 | |
|             setx name=basename -- "$sqlmig"
 | |
|             rsync -av --delete-after "$sqlmig/" "$destdir/$name"
 | |
|         else
 | |
|             rsync -av "$sqlmig" "$destdir"
 | |
|         fi
 | |
|     done
 | |
|     return 0
 | |
| }
 | |
| 
 | |
| function __maps_replace() {
 | |
|     if [ "${maps#$1,}" != "$maps" ]; then
 | |
|         maps="$2,${maps#$1,}"
 | |
|     elif [ "${maps%,$1}" != "$maps" ]; then
 | |
|         maps="${maps%,$1},$2"
 | |
|     elif [ "${maps/,$1,/}" != "$maps" ]; then
 | |
|         maps="${maps/,$1,/,$2,}"
 | |
|     elif [ "$maps" == "$1" ]; then
 | |
|         maps="$2"
 | |
|     fi
 | |
| }
 | |
| 
 | |
| function update_apps_func_pff() {
 | |
|     local maps="$1" pffdir="${2:-$DEST}"
 | |
|     [ -f "$pffdir/$PFF_CONF" ] || return 0
 | |
| 
 | |
|     # aliases
 | |
|     __maps_replace PTD prod:prod,test:test,devel:devel
 | |
|     __maps_replace PT prod:prod,test:test
 | |
| 
 | |
|     source "$pffdir/$PFF_CONF"
 | |
|     pff_autofix "$pffdir"
 | |
| 
 | |
|     local map src dest
 | |
|     array_split maps "$maps" ,
 | |
|     for map in "${maps[@]}"; do
 | |
|         if [ -z "$map" ]; then
 | |
|             continue
 | |
|         elif [[ "$map" == *:* ]]; then
 | |
|             # mapping de profil
 | |
|             splitpair "$map" dest src
 | |
|             if [ "$src" == "$PROFILE" ]; then
 | |
|                 if array_contains PROFILES "$dest"; then
 | |
|                     estep "Sélection du profil pff $dest"
 | |
|                     pff_select_profile "$dest" "$pffdir"
 | |
|                     return 0
 | |
|                 fi
 | |
|                 eerror "$dest: profil invalide, il a été ignoré"
 | |
|             fi
 | |
|         else
 | |
|             # forcer le profil
 | |
|             dest="$map"
 | |
|             if array_contains PROFILES "$dest"; then
 | |
|                 estep "Sélection du profil pff $dest"
 | |
|                 pff_select_profile "$dest" "$pffdir"
 | |
|                 return 0
 | |
|             fi
 | |
|             eerror "$dest: profil invalide, il a été ignoré"
 | |
|         fi
 | |
|     done
 | |
|     # sélectionner le premier profil
 | |
|     setx dest=pff_get_first_profile "$pffdir"
 | |
|     if [ -n "$dest" ]; then
 | |
|         estep "Sélection du profil pff $dest"
 | |
|         pff_select_profile "$dest" "$pffdir"
 | |
|     fi
 | |
| }
 | |
| 
 | |
| function build_update_apps() {
 | |
|     [ -n "$BUILD_UPDATE_APPS" ] || return 0
 | |
|     [ -f update-apps.conf ] || return 0
 | |
| 
 | |
|     # charger le fichier de configuration
 | |
|     local DEFAULT_ORIGIN DEFAULT_BRANCH APPS
 | |
|     DEFAULT_ORIGIN="$UPDATE_APPS_ORIGIN"
 | |
|     [ -z "$DEFAULT_ORIGIN" ] && DEFAULT_ORIGIN=origin
 | |
|     DEFAULT_BRANCH="$UPDATE_APPS_BRANCH"
 | |
|     #XXX à terme, on déploiera la branche master en prod
 | |
|     [ -z "$DEFAULT_BRANCH" -a "$PROFILE" == prod ] && DEFAULT_BRANCH=develop #master
 | |
|     [ -z "$DEFAULT_BRANCH" ] && DEFAULT_BRANCH=develop
 | |
|     DEFAULT_DEVEL_SRCDIR="$HOME/wop/php"
 | |
|     DEFAULT_COMPOSER_ACTION=install
 | |
|     APPS=()
 | |
|     CLEAN=
 | |
|     [ -f update-apps.conf ] && source ./update-apps.conf
 | |
| 
 | |
|     local apps # liste des applications spécifique au profil
 | |
|     apps="${PROFILE}_APPS[@]"; apps=("${!apps}")
 | |
|     [ ${#apps[*]} -gt 0 ] && APPS=("${apps[@]}")
 | |
|     [ ${#APPS[*]} -gt 0 ] || return 0
 | |
| 
 | |
|     local PRODUCTION DEVELOPMENT
 | |
|     case "$PROFILE" in
 | |
|     prod) PRODUCTION=1; DEVELOPMENT=;;
 | |
|     test) PRODUCTION=1; DEVELOPMENT=1;;
 | |
|     devel) PRODUCTION=; DEVELOPMENT=;;
 | |
|     esac
 | |
| 
 | |
|     local clean
 | |
|     clean="${PROFILE}_CLEAN"; clean="${!clean}"
 | |
|     [ -n "$clean" ] && CLEAN="$clean"
 | |
|     if [ -n "$CLEAN" ]; then
 | |
|         etitle "Nettoyage"
 | |
|         "$CLEAN"
 | |
|         eend
 | |
|     fi
 | |
| 
 | |
|     etitle "Mise à jour des dépendances"
 | |
|     local app var URL DEVEL_SRCDIR DEST ORIGIN BRANCH TYPE after_update after_updates composer_action
 | |
|     for app in "${APPS[@]}"; do
 | |
|         etitle "$app"
 | |
| 
 | |
|         var="${app//-/_}"
 | |
| 
 | |
|         URL="${var}_URL"; URL="${!URL}"
 | |
|         [ -n "$URL" ] || {
 | |
|             ewarn "$app: vous devez définir l'url"
 | |
|             eend; return 1
 | |
|         }
 | |
| 
 | |
|         DEVEL_SRCDIR="${var}_DEVEL_SRCDIR"; DEVEL_SRCDIR="${!DEVEL_SRCDIR}"
 | |
|         [ -n "$DEVEL_SRCDIR" ] || DEVEL_SRCDIR="$DEFAULT_DEVEL_SRCDIR/${URL##*/}"
 | |
| 
 | |
|         DEST="${var}_DEST"; DEST="${!DEST}"
 | |
|         [ -n "$DEST" ] || DEST="$app/b"
 | |
|         mkdir -p "$DEST" || { eend; return 1; }
 | |
| 
 | |
|         ORIGIN="${var}_${PROFILE}_ORIGIN"; ORIGIN="${!ORIGIN}"
 | |
|         [ -n "$ORIGIN" ] || { ORIGIN="${var}_ORIGIN"; ORIGIN="${!ORIGIN}"; }
 | |
|         [ -n "$ORIGIN" ] || ORIGIN="$DEFAULT_ORIGIN"
 | |
| 
 | |
|         BRANCH="${var}_${PROFILE}_BRANCH"; BRANCH="${!BRANCH}"
 | |
|         [ -n "$BRANCH" ] || { BRANCH="${var}_BRANCH"; BRANCH="${!BRANCH}"; }
 | |
|         [ -n "$BRANCH" ] || BRANCH="$DEFAULT_BRANCH"
 | |
| 
 | |
|         # calculer le type maintenant, on en a besoin pour le mode devel
 | |
|         TYPE="${var}_TYPE"; TYPE="${!TYPE}"
 | |
| 
 | |
|         DEST="$DEST/$app"
 | |
|         if [ -n "$BUILD_UPDATE_DEVEL" ]; then
 | |
|             # synchronisation en mode devel
 | |
|             local -a rsync_opts; rsync_opts=(-a --delete --exclude .git/ --delete-excluded)
 | |
|             estep "Synchro $DEVEL_SRCDIR --> $DEST"
 | |
|             rsync "${rsync_opts[@]}" "$DEVEL_SRCDIR/" "$DEST" || { eend; return 1; }
 | |
| 
 | |
|             if [ -z "$TYPE" ]; then
 | |
|                 # possible de détecter le type quand on a le projet
 | |
|                 # en cas de maj ici, mettre à jour aussi le code ci-dessous
 | |
|                 if [ -f "$DEST/composer.json" ]; then TYPE=composer
 | |
|                 else TYPE=none
 | |
|                 fi
 | |
|             fi
 | |
| 
 | |
|             if [ "$TYPE" == composer ]; then
 | |
|                 # Synchronisation des dépendances
 | |
|                 local -a depdirs; local depdir pname
 | |
|                 setx -a depdirs=ls -d "$DEST/vendor/"{lib,ur}/* 2>/dev/null
 | |
|                 for depdir in "${depdirs[@]}"; do
 | |
|                     [ -L "$depdir" ] && rm "$depdir"
 | |
|                     pname="${depdir#$DEST/vendor/}"; pname="${pname/\//-}"
 | |
|                     estep "Synchro $DEFAULT_DEVEL_SRCDIR/$pname --> $depdir"
 | |
|                     rsync "${rsync_opts[@]}" --exclude /vendor/ "$DEFAULT_DEVEL_SRCDIR/$pname/" "$depdir"
 | |
|                 done
 | |
|             fi
 | |
|         else
 | |
|             if [ -d "$DEST" -a -d "$DEST/.git" ]; then
 | |
|                 # mise à jour
 | |
|                 estep "Maj dépôt $URL:$BRANCH --> $DEST"
 | |
|                 setx cwd=pwd
 | |
|                 cd "$DEST"
 | |
|                 git fetch --all -p -f || { eend; return 1; }
 | |
|                 git reset --hard "$ORIGIN/$BRANCH" || { eend; return 1; }
 | |
|                 cd "$cwd"
 | |
|             else
 | |
|                 # reliquat mode devel?
 | |
|                 [ -d "$DEST" ] && rm -rf "$DEST"
 | |
|                 # clonage initial
 | |
|                 estep "Clonage $URL:$BRANCH --> $DEST"
 | |
|                 git clone -o "$ORIGIN" -b "$BRANCH" "$URL" "$DEST" || { eend; return 1; }
 | |
|             fi
 | |
| 
 | |
|             if [ -z "$TYPE" ]; then
 | |
|                 # possible de détecter le type quand on a le projet
 | |
|                 # en cas de maj ici, mettre à jour aussi le code ci-dessus
 | |
|                 if [ -f "$DEST/composer.json" ]; then TYPE=composer
 | |
|                 else TYPE=none
 | |
|                 fi
 | |
|             fi
 | |
|         fi
 | |
| 
 | |
|         after_updates="${var}_AFTER_UPDATE"
 | |
|         if is_defined "$after_updates"; then
 | |
|             after_updates="$after_updates[@]"; after_updates=("${!after_updates}")
 | |
|         elif [ "$TYPE" == composer ]; then
 | |
|             after_updates=(sqlmig)
 | |
|         else
 | |
|             after_updates=()
 | |
|         fi
 | |
| 
 | |
|         estep "Type de dépôt: $TYPE"
 | |
|         if [ "$TYPE" == composer ]; then
 | |
|             composer_action="${var}_${PROFILE}_COMPOSER_ACTION"; composer_action="${!composer_action}"
 | |
|             [ -n "$composer_action" ] || { composer_action="${var}_COMPOSER_ACTION"; composer_action="${!composer_action}"; }
 | |
|             [ -n "$composer_action" ] || composer_action="$DEFAULT_COMPOSER_ACTION"
 | |
| 
 | |
|             if [ -z "$BUILD_UPDATE_DEVEL" ]; then
 | |
|                 case "${composer_action:-install}" in
 | |
|                 i|install) composer_action=install;;
 | |
|                 u|update) composer_action=update;;
 | |
|                 none|nop) composer_action=;;
 | |
|                 *) ewarn "$composer_action: action invalide"; composer_action=;;
 | |
|                 esac
 | |
|                 if [ -n "$composer_action" ]; then
 | |
|                     setx cwd=pwd
 | |
|                     cd "$DEST"
 | |
|                     estep "Installation des dépendances composer"
 | |
|                     auto_composer "$composer_action" ${PRODUCTION:+--no-dev -o} || { eend; return 1; }
 | |
|                     cd "$cwd"
 | |
|                 fi
 | |
|             fi
 | |
|         fi
 | |
| 
 | |
|         for after_update in "${after_updates[@]}"; do
 | |
|             if [ "${after_update#/}" != "$after_update" ]; then
 | |
|                 # commande absolue, la lancer telle quelle
 | |
|                 etitle "$after_update"
 | |
|                 eval "$after_update" || { eend; eend; return 1; }
 | |
|                 eend
 | |
|             elif [ "${after_update#./}" != "$after_update" ]; then
 | |
|                 # commande relative, la lancer telle quelle
 | |
|                 etitle "$after_update"
 | |
|                 eval "$after_update" || { eend; eend; return 1; }
 | |
|                 eend
 | |
|             else
 | |
|                 # c'est une fonction update_apps_func_*
 | |
|                 etitle "$after_update"
 | |
|                 eval "update_apps_func_$after_update" || { eend; eend; return 1; }
 | |
|                 eend
 | |
|             fi
 | |
|         done
 | |
| 
 | |
|         eend
 | |
|     done
 | |
|     eend
 | |
| }
 | |
| 
 | |
| function initialize_build_env() {
 | |
|     CTXDIR=.
 | |
|     NAME=
 | |
|     TAGS=(latest)
 | |
|     VERSION=
 | |
|     DIST=
 | |
| }
 | |
| function default_update_build_env() {
 | |
|     local var
 | |
|     if [ -n "$DIST" ]; then
 | |
|         [ -n "$VERSION" ] && VERSION="$VERSION-"
 | |
|         VERSION="$VERSION$DIST"
 | |
|         TAGS+=("$DIST")
 | |
|     fi
 | |
|     [ -n "$VERSION" ] || docker_add_build_arg VERSION "$(get_version)"
 | |
|     [ -n "$VERSION" ] && TAGS+=("$VERSION")
 | |
|     # Variables en ligne de commande
 | |
|     for var in "${VARS[@]}"; do
 | |
|         docker_add_build_arg "${var%%=*}" "${var#*=}"
 | |
|     done
 | |
| }
 | |
| function update_build_env() { default_update_build_env; }
 | |
| 
 | |
| function default_compose_build() {
 | |
|     ${FAKE:+qvals} docker-compose \
 | |
|         "${replace_env_args[@]}" "${env_args[@]}" \
 | |
|         build \
 | |
|         ${NO_CACHE:+--no-cache} \
 | |
|         "${replace_build_args[@]}" "${build_args[@]}" \
 | |
|         "$@"
 | |
| }
 | |
| function default_docker_build() {
 | |
|     local tag
 | |
|     for tag in "${TAGS[@]}"; do
 | |
|         replace_build_args+=(-t "$NAME:$tag")
 | |
|     done
 | |
|     ${FAKE:+qvals} "$DOCKER" build \
 | |
|         ${NO_CACHE:+--no-cache} \
 | |
|         "${replace_env_args[@]}" "${env_args[@]}" \
 | |
|         "${replace_build_args[@]}" "${build_args[@]}" \
 | |
|         "$@" "$CTXDIR"
 | |
| }
 | |
| function compose_build() {
 | |
|     [ -n "$BUILD_BUILD" ] || return 0
 | |
|     default_compose_build "$@"
 | |
| }
 | |
| function docker_build() {
 | |
|     [ -n "$BUILD_BUILD" ] || return 0
 | |
|     default_docker_build "$@"
 | |
| }
 | |
| function auto_build() {
 | |
|     local -a replace_env_args env_args
 | |
|     local -a replace_build_args build_args
 | |
|     initialize_build_env
 | |
|     if [ -f docker-compose.yml ]; then
 | |
|         compose_set_env_args
 | |
|         update_build_env
 | |
|         build_update_apps || return 1
 | |
|         compose_build "$@"
 | |
|     else
 | |
|         docker_parse_env_args
 | |
|         docker_check_name
 | |
|         docker_add_build_arg build_date "$(date +%y%m%d)"
 | |
|         update_build_env
 | |
|         build_update_apps || return 1
 | |
|         docker_build "$@"
 | |
|     fi
 | |
| }
 | |
| 
 | |
| function default_compose_push() {
 | |
|     ${FAKE:+qvals} docker-compose \
 | |
|         "${replace_env_args[@]}" "${env_args[@]}" \
 | |
|         push \
 | |
|         "$@"
 | |
| }
 | |
| function default_docker_push() {
 | |
|     ${FAKE:+qvals} "$DOCKER" push \
 | |
|         "${replace_env_args[@]}" "${env_args[@]}" \
 | |
|         "$@"
 | |
| }
 | |
| function compose_push() {
 | |
|     default_compose_push "$@"
 | |
| }
 | |
| function docker_push() {
 | |
|     local tag
 | |
|     for tag in "${TAGS[@]}"; do
 | |
|         default_docker_push "$NAME:$tag" "$@"
 | |
|     done
 | |
| }
 | |
| function auto_push() {
 | |
|     local -a replace_env_args env_args
 | |
|     local -a replace_build_args build_args
 | |
|     initialize_build_env
 | |
|     if [ -f docker-compose.yml ]; then
 | |
|         compose_set_env_args
 | |
|         update_build_env
 | |
|         compose_push "$@"
 | |
|     else
 | |
|         docker_parse_env_args
 | |
|         docker_check_name
 | |
|         update_build_env
 | |
|         docker_push "$@"
 | |
|     fi
 | |
| }
 | |
| 
 | |
| function default_compose_up() {
 | |
|     ${FAKE:+qvals} docker-compose \
 | |
|         "${replace_env_args[@]}" "${env_args[@]}" \
 | |
|         up "${replace_run_args[@]}" "${run_args[@]}" \
 | |
|         "${replace_user_args[@]}" "${user_args[@]}" "$@"
 | |
| }
 | |
| function default_docker_up() {
 | |
|     ${FAKE:+qvals} "$DOCKER" run \
 | |
|            "${replace_env_args[@]}" "${env_args[@]}" \
 | |
|            "${replace_run_args[@]}" "${run_args[@]}" \
 | |
|            "$NAME" \
 | |
|            "${replace_user_args[@]}" "${user_args[@]}" "$@"
 | |
| }
 | |
| function compose_up() { default_compose_up "$@"; }
 | |
| function docker_up() { default_docker_up "$@"; }
 | |
| function auto_up() {
 | |
|     local -a replace_env_args env_args
 | |
|     local -a replace_run_args run_args
 | |
|     local -a replace_user_args user_args
 | |
|     local project_name container_name
 | |
|     if [ -f docker-compose.yml ]; then
 | |
|         compose_set_env_args
 | |
|         replace_run_args=(-d)
 | |
|         compose_up "$@"
 | |
|     else
 | |
|         docker_set_env_args
 | |
|         docker_check_name set_container_name
 | |
|         replace_run_args=(-d --name "$container_name")
 | |
|         docker_up "$@"
 | |
|     fi
 | |
| }
 | |
| 
 | |
| function default_compose_stop() {
 | |
|     ${FAKE:+qvals} docker-compose \
 | |
|         "${replace_env_args[@]}" "${env_args[@]}" \
 | |
|         stop "${replace_stop_args[@]}" "${stop_args[@]}" \
 | |
|         "$@"
 | |
| }
 | |
| function default_docker_stop() {
 | |
|     ${FAKE:+qvals} "$DOCKER" container stop \
 | |
|            "${replace_stop_args[@]}" "${stop_args[@]}" \
 | |
|            "$container_name" "$@"
 | |
| }
 | |
| function compose_stop() { default_compose_stop "$@"; }
 | |
| function docker_stop() { default_docker_stop "$@"; }
 | |
| function auto_stop() {
 | |
|     local -a replace_env_args env_args
 | |
|     local -a replace_stop_args stop_args
 | |
|     local project_name container_name
 | |
|     if [ -f docker-compose.yml ]; then
 | |
|         compose_set_env_args
 | |
|         compose_stop "$@"
 | |
|     else
 | |
|         docker_set_env_args
 | |
|         docker_check_name set_container_name
 | |
|         docker_stop "$@"
 | |
|     fi
 | |
| }
 | |
| 
 | |
| function default_compose_logs() {
 | |
|     ${FAKE:+qvals} docker-compose \
 | |
|         "${replace_env_args[@]}" "${env_args[@]}" \
 | |
|         logs "${replace_logs_args[@]}" "${logs_args[@]}" \
 | |
|         "$@"
 | |
| }
 | |
| function default_docker_logs() {
 | |
|     ${FAKE:+qvals} "$DOCKER" logs \
 | |
|            "${replace_logs_args[@]}" "${logs_args[@]}" \
 | |
|            "$container_name" "$@"
 | |
| }
 | |
| function compose_logs() { default_compose_logs "$@"; }
 | |
| function docker_logs() { default_docker_logs "$@"; }
 | |
| function auto_logs() {
 | |
|     local -a replace_env_args env_args
 | |
|     local -a replace_logs_args logs_args
 | |
|     local project_name container_name
 | |
|     if [ -f docker-compose.yml ]; then
 | |
|         compose_set_env_args
 | |
|         replace_logs_args=(-f)
 | |
|         compose_logs "$@"
 | |
|     else
 | |
|         docker_set_env_args
 | |
|         docker_check_name set_container_name
 | |
|         replace_logs_args=(-f)
 | |
|         docker_logs "$@"
 | |
|     fi
 | |
| }
 | |
| 
 | |
| function default_compose_down() {
 | |
|     ${FAKE:+qvals} docker-compose \
 | |
|         "${replace_env_args[@]}" "${env_args[@]}" \
 | |
|         down "${replace_down_args[@]}" "${down_args[@]}" \
 | |
|         "$@"
 | |
| }
 | |
| function default_docker_down() {
 | |
|     estep "stop"
 | |
|     ${FAKE:+qvals} "$DOCKER" container stop \
 | |
|            "${replace_down_args[@]}" "${down_args[@]}" \
 | |
|            "$container_name" "$@"
 | |
|     estep "rm"
 | |
|     ${FAKE:+qvals} "$DOCKER" container rm \
 | |
|            "${replace_rm_args[@]}" "${rm_args[@]}" \
 | |
|            "$container_name"
 | |
| }
 | |
| function compose_down() { default_compose_down "$@"; }
 | |
| function docker_down() { default_docker_down "$@"; }
 | |
| function auto_down() {
 | |
|     local -a replace_env_args env_args
 | |
|     local -a replace_down_args down_args
 | |
|     local -a replace_rm_args rm_args
 | |
|     local project_name container_name
 | |
|     if [ -f docker-compose.yml ]; then
 | |
|         compose_set_env_args
 | |
|         compose_down "$@"
 | |
|     else
 | |
|         docker_set_env_args
 | |
|         docker_check_name set_container_name
 | |
|         docker_down "$@"
 | |
|     fi
 | |
| }
 | |
| 
 | |
| function default_compose_run() {
 | |
|     ${FAKE:+qvals} docker-compose \
 | |
|         "${replace_env_args[@]}" "${env_args[@]}" \
 | |
|         run "${replace_run_args[@]}" "${run_args[@]}" \
 | |
|         "${replace_user_args[@]}" "${user_args[@]}" "$@"
 | |
| }
 | |
| function default_docker_run() {
 | |
|     ${FAKE:+qvals} "$DOCKER" run \
 | |
|            "${replace_env_args[@]}" "${env_args[@]}" \
 | |
|            "${replace_run_args[@]}" "${run_args[@]}" \
 | |
|            "$NAME" \
 | |
|            "${replace_user_args[@]}" "${user_args[@]}" "$@"
 | |
| }
 | |
| function compose_run() { default_compose_run "$@"; }
 | |
| function docker_run() { default_docker_run "$@"; }
 | |
| function auto_run() {
 | |
|     eval "$(utools_local parse_opts)"
 | |
|     local detach no_deps rm=1 service_ports use_aliases volume
 | |
|     local -a envs labels
 | |
|     local var
 | |
|     for var in "${VARS[@]}"; do
 | |
|         envs+=(-e "$var")
 | |
|     done
 | |
| 
 | |
|     args=(
 | |
|         +
 | |
|         -d,--detach detach=1
 | |
|         -e: '$add@ envs -e; add@ envs'
 | |
|         -l:,--label: '$add@ labels -l; add@ labels'
 | |
|         --no-deps no_deps=1
 | |
|         --no-rm rm=
 | |
|         --rm rm=1
 | |
|         --service-ports service_ports=1
 | |
|         --use-aliases use_aliases=1
 | |
|         -v:,--volume: volume=
 | |
|         @ args -- "$@"
 | |
|     )
 | |
|     parse_opts "${args[@]}" && set -- "${args[@]}" || { eerror "$args"; return 1; }
 | |
| 
 | |
|     local -a replace_env_args env_args
 | |
|     local -a replace_run_args run_args
 | |
|     local -a replace_user_args user_args
 | |
|     local project_name container_name
 | |
|     if [ -f docker-compose.yml ]; then
 | |
|         compose_set_env_args
 | |
|         replace_run_args=(
 | |
|             ${detach:+-d}
 | |
|             "${envs[@]}" "${labels[@]}"
 | |
|             ${no_deps:+--no-deps}
 | |
|             ${rm:+--rm}
 | |
|             ${service_ports:+--service-ports}
 | |
|             ${use_aliases:+--use-aliases}
 | |
|             ${volume:+-v "$volume"}
 | |
|         )
 | |
|         compose_run "$@"
 | |
|     else
 | |
|         docker_set_env_args
 | |
|         docker_check_name set_container_name
 | |
|         replace_run_args=(
 | |
|             --name "$container_name"
 | |
|             ${rm:+--rm}
 | |
|             ${volume:+-v "$volume"}
 | |
|         )
 | |
|         docker_run "$@"
 | |
|     fi
 | |
| }
 | |
| 
 | |
| function default_compose_exec() {
 | |
|     ${FAKE:+qvals} docker-compose \
 | |
|         "${replace_env_args[@]}" "${env_args[@]}" \
 | |
|         exec "${replace_exec_args[@]}" "${exec_args[@]}" \
 | |
|         "$@"
 | |
| }
 | |
| function default_docker_exec() {
 | |
|     ${FAKE:+qvals} "$DOCKER" container exec \
 | |
|            "${replace_exec_args[@]}" "${exec_args[@]}" \
 | |
|            "$container_name" "$@"
 | |
| }
 | |
| function compose_exec() { default_compose_exec "$@"; }
 | |
| function docker_exec() { default_docker_exec "$@"; }
 | |
| function auto_exec() {
 | |
|     local -a replace_env_args env_args
 | |
|     local -a replace_exec_args exec_args
 | |
|     local project_name container_name
 | |
|     if [ -f docker-compose.yml ]; then
 | |
|         compose_set_env_args
 | |
|         compose_exec "$@"
 | |
|     else
 | |
|         docker_set_env_args
 | |
|         docker_check_name set_container_name
 | |
|         docker_exec "$@"
 | |
|     fi
 | |
| }
 | |
| 
 | |
| function default_docker_deploy() {
 | |
|     ${FAKE:+qvals} "$DOCKER" \
 | |
|         stack deploy \
 | |
|         "${replace_deploy_args[@]}" "${deploy_args[@]}" \
 | |
|         "$container_name" "$@"
 | |
| }
 | |
| function docker_deploy() { default_docker_deploy "$@"; }
 | |
| function auto_deploy() {
 | |
|     local -a replace_env_args env_args
 | |
|     local -a replace_deploy_args deploy_args
 | |
|     local project_name container_name
 | |
|     if [ -f docker-compose.yml -o -f docker-stack.yml ]; then
 | |
|         docker_set_deploy_args set_container_name
 | |
|         [ -n "$WITH_REGISTRY_AUTH" ] && replace_deploy_args+=(--with-registry-auth)
 | |
|         docker_deploy "$@"
 | |
|     else
 | |
|         die "Impossible de trouver ni docker-compose.yml ni docker-stack.yml"
 | |
|     fi
 | |
| }
 | |
| 
 | |
| function default_docker_service() {
 | |
|     ${FAKE:+qvals} "$DOCKER" service "$@"
 | |
| }
 | |
| function docker_service() { default_docker_service "$@"; }
 | |
| function auto_service() {
 | |
|     if [ -f docker-compose.yml -o -f docker-stack.yml ]; then
 | |
|         local command="$1"; shift
 | |
|         [ -n "$command" ] || {
 | |
|             eerror "Vous devez spécifier la commande"
 | |
|             return 1
 | |
|         }
 | |
|         local -a command_args
 | |
|         [ "$command" == update -a -n "$WITH_REGISTRY_AUTH" ] && command_args+=(--with-registry-auth)
 | |
|         case "$command" in
 | |
|         ls) # ces commandes n'ont pas besoin du nom de service
 | |
|             docker_service "$command" "$@"
 | |
|             ;;
 | |
|         *) # ces commandes ont besoin du nom du service
 | |
|             local service="$1"; shift
 | |
|             [ -n "$service" ] || {
 | |
|                 eerror "Vous devez spécifier le nom du service"
 | |
|                 return 1
 | |
|             }
 | |
|             local -a replace_env_args env_args
 | |
|             local -a replace_deploy_args deploy_args
 | |
|             local project_name container_name
 | |
|             docker_set_deploy_args set_container_name
 | |
|             service="${container_name}_${service#${container_name}_}"
 | |
|             docker_service "$command" "${command_args[@]}" "$@" "$service"
 | |
|             ;;
 | |
|         esac
 | |
|     else
 | |
|         die "Impossible de trouver ni docker-compose.yml ni docker-stack.yml"
 | |
|     fi
 | |
| }
 | |
| 
 | |
| function default_compose_show_ip() {
 | |
|     local -a cmd cids; local cid
 | |
|     cmd=(
 | |
|         docker-compose
 | |
|         "${replace_env_args[@]}" "${env_args[@]}"
 | |
|         ps -q "${replace_show_ip_args[@]}" "${show_ip_args[@]}"
 | |
|         "$@"
 | |
|     )
 | |
|     if [ -n "$FAKE" ]; then
 | |
|         echo "docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' \"\$($(qvals "${cmd[@]}"))\""
 | |
|     else
 | |
|         setx -a cids="${cmd[@]}" 2>/dev/null
 | |
|         for cid in "${cids[@]}"; do
 | |
|             "$DOCKER" inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' "$cid"
 | |
|         done
 | |
|     fi
 | |
| }
 | |
| function default_docker_show_ip() {
 | |
|     ${FAKE:+qvals} "$DOCKER" inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' \
 | |
|            "${replace_show_ip_args[@]}" "${show_ip_args[@]}" \
 | |
|            "$container_name" "$@"
 | |
| }
 | |
| function compose_show_ip() { default_compose_show_ip "$@"; }
 | |
| function docker_show_ip() { default_docker_show_ip "$@"; }
 | |
| function auto_show_ip() {
 | |
|     local -a replace_env_args env_args
 | |
|     local -a replace_show_ip_args show_ip_args
 | |
|     local project_name container_name
 | |
|     if [ -f docker-compose.yml ]; then
 | |
|         compose_set_env_args
 | |
|         compose_show_ip "$@"
 | |
|     else
 | |
|         docker_set_env_args
 | |
|         docker_check_name set_container_name
 | |
|         docker_show_ip "$@"
 | |
|     fi
 | |
| }
 | |
| 
 | |
| function default_compose_systemd_unit() {
 | |
|     local docker_compose="$(which docker-compose 2>/dev/null)"
 | |
|     if [ -z "$docker_compose" ]; then
 | |
|         if [ -x /usr/bin/docker-compose ]; then
 | |
|             docker_compose=/usr/bin/docker-compose
 | |
|         elif [ -x /usr/local/bin/docker-compose ]; then
 | |
|             docker_compose=/usr/local/bin/docker-compose
 | |
|         else
 | |
|             die "Impossible de trouver docker-compose"
 | |
|         fi
 | |
|     fi
 | |
|     setx startcmd=qvals "$docker_compose" \
 | |
|         "${replace_env_args[@]}" "${env_args[@]}" \
 | |
|         up "${replace_run_args[@]}" "${run_args[@]}" \
 | |
|         "${replace_user_args[@]}" "${user_args[@]}" "$@"
 | |
|     setx stopcmd=qvals "$docker_compose" down
 | |
| }
 | |
| function default_docker_systemd_unit() {
 | |
|     local docker="$(which "$DOCKER" 2>/dev/null)"
 | |
|     if [ -z "$docker" ]; then
 | |
|         if [ -x /usr/bin/docker ]; then
 | |
|             docker=/usr/bin/docker
 | |
|         elif [ -x /usr/local/bin/docker ]; then
 | |
|             docker=/usr/local/bin/docker
 | |
|         else
 | |
|             die "Impossible de trouver docker"
 | |
|         fi
 | |
|     fi
 | |
|     setx startcmd=qvals "$docker" run \
 | |
|            "${replace_env_args[@]}" "${env_args[@]}" \
 | |
|            "${replace_run_args[@]}" "${run_args[@]}" \
 | |
|            "$NAME" \
 | |
|            "${replace_user_args[@]}" "${user_args[@]}" "$@"
 | |
|     setx stopcmd=qvals "$docker" stop "$container_name"
 | |
| }
 | |
| function compose_systemd_unit() { default_compose_systemd_unit "$@"; }
 | |
| function docker_systemd_unit() { default_docker_systemd_unit "$@"; }
 | |
| function auto_systemd_unit() {
 | |
|     local -a replace_env_args env_args
 | |
|     local -a replace_run_args run_args
 | |
|     local -a replace_user_args user_args
 | |
|     local project_name container_name startcmd stopcmd
 | |
|     local tmpscript; ac_set_tmpfile tmpscript
 | |
| 
 | |
|     estep "Génération de l'unité systemd"
 | |
|     export COMPOSE_PROJECT_NAME=
 | |
|     if [ -f docker-compose.yml ]; then
 | |
|         compose_set_env_args set_container_name
 | |
|         replace_run_args=(-d --no-color)
 | |
|         compose_systemd_unit "$@"
 | |
|         if [ -z "$HOST" -a -f .env ]; then
 | |
|             source ./.env
 | |
|             if [ -n "$PROFILE" ]; then
 | |
|                 HOST="${PROFILE^^}_HOST"; HOST="${!HOST}"
 | |
|             fi
 | |
|         fi
 | |
|     else
 | |
|         docker_set_env_args
 | |
|         docker_check_name set_container_name
 | |
|         replace_run_args=(-d --name "$container_name")
 | |
|         docker_systemd_unit "$@"
 | |
|     fi
 | |
|     [ -n "$COMPOSE_PROJECT_NAME" ] || COMPOSE_PROJECT_NAME="$project_name"
 | |
|     chmod 755 "$tmpscript"
 | |
|     cat >"$tmpscript" <<EOF
 | |
| #!/bin/bash
 | |
| # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
 | |
| cat >/etc/systemd/system/$container_name.service <<EOD
 | |
| [Unit]
 | |
| Description=$project_name stack ($PROFILE)
 | |
| Requires=docker.service
 | |
| After=docker.service
 | |
| 
 | |
| [Service]
 | |
| Type=oneshot
 | |
| RemainAfterExit=yes
 | |
| WorkingDirectory=$(pwd)
 | |
| Environment=$(qval "COMPOSE_PROJECT_NAME=$COMPOSE_PROJECT_NAME")
 | |
| ExecStart=$startcmd
 | |
| ExecStop=$stopcmd
 | |
| TimeoutStopSec=300
 | |
| 
 | |
| [Install]
 | |
| WantedBy=multi-user.target
 | |
| EOD
 | |
| systemctl daemon-reload
 | |
| systemctl enable $container_name.service
 | |
| EOF
 | |
| 
 | |
|     estep "Installation de l'unité systemd"
 | |
|     local_run "$HOST" "$tmpscript"
 | |
| }
 | |
| 
 | |
| function default_local_composer() {
 | |
|     # lancement direct
 | |
|     case "$1" in
 | |
|     rootshell|rshell|rootbash|rbash)
 | |
|         shift
 | |
|         # ewarn parce qu'on est pas root dans ce shell contrairement à ce qui est demandé
 | |
|         ewarn "Lancement d'un shell utilisateur alors qu'un shell root est demandé"
 | |
|         bash "$@"
 | |
|         ;;
 | |
|     usershell|shell|userbash|bash)
 | |
|         shift
 | |
|         estep "Lancement d'un shell utilisateur"
 | |
|         bash "$@"
 | |
|         ;;
 | |
|     *)
 | |
|         if [ -n "$COMPOSER_CMD" ]; then :
 | |
|         elif [ -x composer.phar ]; then COMPOSER_CMD=./composer.phar
 | |
|         elif [ -x /usr/bin/composer ]; then COMPOSER_CMD=/usr/bin/composer
 | |
|         else
 | |
|             eerror "Impossible de trouver composer"
 | |
|             return 1
 | |
|         fi
 | |
|         "$COMPOSER_CMD" "$@"
 | |
|         ;;
 | |
|     esac
 | |
| }
 | |
| function default_docker_composer() {
 | |
|     # lancement dans un container
 | |
|     local user group projdir actualcmd args
 | |
|     setx user=id -un; setx user=getent passwd "$user"
 | |
|     setx group=id -gn; setx group=getent group "$group"
 | |
|     setx projdir=pwd
 | |
|     case "$1" in
 | |
|     rootshell|rshell|rootbash|rbash)
 | |
|         shift
 | |
|         actualcmd='eval "bash $args"'
 | |
|         ;;
 | |
|     usershell|shell|userbash|bash)
 | |
|         shift
 | |
|         actualcmd='eval "su-exec \"$user\" bash $args"'
 | |
|         ;;
 | |
|     *)
 | |
|         actualcmd='eval "su-exec \"$user\" \"$composer\" $args"'
 | |
|         ;;
 | |
|     esac
 | |
|     setx args=qvals "$@"
 | |
| 
 | |
|     local -a basecmd cmd setupscript runscript
 | |
|     basecmd=(
 | |
|         -e user="$user"
 | |
|         -e group="$group"
 | |
|         -e projdir="$projdir"
 | |
|         -e setup="$COMPOSER_SETUP"
 | |
|         -e composer="$COMPOSER_CMD"
 | |
|         -e args="$args"
 | |
|         -v "$HOME:$HOME"
 | |
|     )
 | |
|     if [ "${projdir#$HOME/}" == "$projdir" ]; then
 | |
|         # si le répertoire de projet ne se trouve pas dans $HOME, le monter aussi
 | |
|         cmd+=(-v "$projdir:$projdir")
 | |
|     fi
 | |
|     setupscript='eval "$setup"'
 | |
|     runscript='
 | |
| echo "$user" >>/etc/passwd; user="${user%%:*}"
 | |
| echo "$group" >>/etc/group; group="${group%%:*}"
 | |
| 
 | |
| cd "$projdir"
 | |
| if [ -n "$composer" ]; then :
 | |
| elif [ -x composer.phar ]; then composer=./composer.phar
 | |
| elif [ -x /usr/bin/composer ]; then composer=/usr/bin/composer
 | |
| else
 | |
|     echo "ERROR: Impossible de trouver composer"
 | |
|     exit 1
 | |
| fi
 | |
| '"$actualcmd"
 | |
| 
 | |
|     if [ -n "$COMPOSER_SETUP" ]; then
 | |
|         # lancement dans un container docker à préparer
 | |
|         local NAME project_name container_name dkid
 | |
|         if [ -f docker-compose.yml ]; then
 | |
|             compose_set_project_name set_container_name
 | |
|         else
 | |
|             NAME="$(basename -- "$(pwd)")"
 | |
|             docker_check_name set_container_name
 | |
|         fi
 | |
|         container_name="dk_composer_${container_name}"
 | |
| 
 | |
|         # vérifier l'existence de l'image
 | |
|         setx dkid=docker image ls --format '{{.ID}}' "${container_name}_image"
 | |
| 
 | |
|         # créer le container le cas échéant
 | |
|         if [ -z "$dkid" ]; then
 | |
|             estep "Création du container $container_name avec l'image $COMPOSER_IMAGE"
 | |
|             cmd=(
 | |
|                 "$DOCKER" create -it --name "${container_name}_ct"
 | |
|                 "${basecmd[@]}"
 | |
|                 "$COMPOSER_IMAGE"
 | |
|                 bash -c "$setupscript"
 | |
|             )
 | |
|             setx dkid="${cmd[@]}" || return 1
 | |
|             "$DOCKER" container start -ai "$dkid" || return 1
 | |
|             "$DOCKER" container commit "$dkid" "${container_name}_image" || return 1
 | |
|             "$DOCKER" container rm "$dkid" || return 1
 | |
|         fi
 | |
| 
 | |
|         # prendre comme image le container créé
 | |
|         COMPOSER_IMAGE="${container_name}_image"
 | |
|     fi
 | |
| 
 | |
|     cmd=(
 | |
|         "$DOCKER" run -it --rm
 | |
|         "${basecmd[@]}"
 | |
|         "$COMPOSER_IMAGE"
 | |
|         bash -c "$runscript"
 | |
|     )
 | |
|     "${cmd[@]}"
 | |
| }
 | |
| function local_composer() { default_local_composer "$@"; }
 | |
| function docker_composer() { default_docker_composer "$@"; }
 | |
| function auto_composer() {
 | |
|     local COMPOSER_PHP=
 | |
|     local COMPOSER_PHP_MAX=
 | |
|     local COMPOSER_IMAGE="$DEFAULT_COMPOSER_IMAGE"
 | |
|     local COMPOSER_MACHINE=-u
 | |
|     local COMPOSER_CMD=
 | |
|     local COMPOSER_SETUP=
 | |
|     [ -f .composer.conf ] && source ./.composer.conf
 | |
|     # les premiers arguments peuvent service à redéfinir les variables
 | |
|     while [ $# -gt 0 ]; do
 | |
|         case "$1" in
 | |
|         COMPOSER_PHP=*) setv "$1"; shift;;
 | |
|         COMPOSER_PHP_MAX=*) setv "$1"; shift;;
 | |
|         COMPOSER_IMAGE=*) setv "$1"; shift;;
 | |
|         COMPOSER_MACHINE=*) setv "$1"; shift;;
 | |
|         COMPOSER_CMD=*) setv "$1"; shift;;
 | |
|         COMPOSER_SETUP=*) setv "$1"; shift;;
 | |
|         *) break;;
 | |
|         esac
 | |
|     done
 | |
| 
 | |
|     local use_image
 | |
|     if [ -n "$COMPOSER_PHP_MAX" -a "$COMPOSER_PHP_MAX" != none ]; then
 | |
|         # Vérifier la version de PHP
 | |
|         php -r '
 | |
| $version = $argv[1];
 | |
| if (strpos($version, ".") !== false) {
 | |
|   $version = explode(".", $version);
 | |
|   $version = $version[0] * 10000 + $version[1] * 100 + (isset($version[2])? $version[2]: 0);
 | |
| }
 | |
| exit((PHP_VERSION_ID > $version)? 0: 1);
 | |
| ' -- "$COMPOSER_PHP_MAX" && use_image=1
 | |
|     fi
 | |
|     if [ -n "$use_image" ]; then
 | |
|         : # ok, on a déjà décidé qu'il faut utiliser une image
 | |
|     elif [ -z "$COMPOSER_PHP" ]; then
 | |
|         # pas de version minimum, tester simplement la valeur de COMPOSER_IMAGE
 | |
|         [ "$COMPOSER_IMAGE" != none ] && use_image=1
 | |
|     elif [ "$COMPOSER_PHP" == force -o "$COMPOSER_PHP" == any ]; then
 | |
|         use_image=1
 | |
|     else
 | |
|         # Vérifier la version de PHP
 | |
|         php -r '
 | |
| $version = $argv[1];
 | |
| if (strpos($version, ".") !== false) {
 | |
|   $version = explode(".", $version);
 | |
|   $version = $version[0] * 10000 + $version[1] * 100 + (isset($version[2])? $version[2]: 0);
 | |
| }
 | |
| exit((PHP_VERSION_ID < $version)? 0: 1);
 | |
| ' -- "$COMPOSER_PHP" && use_image=1
 | |
|     fi
 | |
| 
 | |
|     if [ -n "$use_image" ]; then
 | |
|         [ "$COMPOSER_IMAGE" != none ] || die "Vous devez spécifier l'image à utiliser pour composer"
 | |
| 
 | |
|         local PREVIOUS_DOCKER_MACHINE_NAME="$DOCKER_MACHINE_NAME"
 | |
|         if [ -n "$COMPOSER_MACHINE" -a "$DOCKER_MACHINE_NAME" != "$COMPOSER_MACHINE" ]; then
 | |
|             local -x DOCKER_TLS_VERIFY= DOCKER_HOST= DOCKER_CERT_PATH= DOCKER_MACHINE_NAME=
 | |
|             if [ "$COMPOSER_MACHINE" != -u ]; then
 | |
|                 local env
 | |
|                 setx env=docker-machine env "$COMPOSER_MACHINE" 2>/dev/null || {
 | |
|                     eerror "$COMPOSER_MACHINE: une erreur s'est produite lors de la sélection du noeud avec docker-machine"
 | |
|                     return 1
 | |
|                 }
 | |
|                 eval "$env"
 | |
|             fi
 | |
|         fi
 | |
| 
 | |
|         docker_composer "$@"
 | |
|     else
 | |
|         local_composer "$@"
 | |
|     fi
 | |
| }
 | |
| 
 | |
| ################################################################################
 | |
| 
 | |
| # support limité docker / podman
 | |
| if progexists docker; then DOCKER=docker
 | |
| elif progexists podman; then DOCKER=podman
 | |
| else DOCKER=docker
 | |
| fi
 | |
| 
 | |
| DEFAULT_PROFILE=devel
 | |
| # pour le moment ne pas lancer composer dans un container par défaut
 | |
| DEFAULT_COMPOSER_IMAGE=none #docker.univ-reunion.fr/image/apache-php-myiccas-utils:d9
 | |
| PROFILE=
 | |
| DM_PROFILES=()
 | |
| set_defaults dk
 | |
| export PROFILE
 | |
| 
 | |
| chdir=
 | |
| CONFIG=
 | |
| DM_SET_MACHINE=
 | |
| USE_STACK=
 | |
| FAKE=
 | |
| VARS=()
 | |
| FORCE=
 | |
| NO_CACHE=
 | |
| HOST=
 | |
| WITH_REGISTRY_AUTH=1
 | |
| update_apps_mode=ub
 | |
| update_apps_devel=
 | |
| update_apps_origin=
 | |
| update_apps_branch=
 | |
| args=(
 | |
|     --help '$exit_with display_help'
 | |
|     -d:,--chdir: chdir=
 | |
|     -c:,--config: CONFIG=
 | |
|     -p:,--profile: PROFILE=
 | |
|     -P,--prod PROFILE=prod
 | |
|     -T,--test PROFILE=test
 | |
|     -m:,--set-machine: DM_SET_MACHINE=
 | |
|     --stack USE_STACK=1
 | |
|     -n,--fake FAKE=1
 | |
|     -e:,--build-arg:,--env: VARS
 | |
|     -f,--force FORCE=1
 | |
|     -j,--no-cache NO_CACHE=1
 | |
|     -h:,--host: HOST=
 | |
|     -g,--ug,--no-update-apps update_apps_mode=b
 | |
|     -u,--uu,--update-apps-only update_apps_mode=u
 | |
|     -w,--uw,--update-apps-devel update_apps_devel=1
 | |
|     --uo:,--update-apps-origin: update_apps_origin=
 | |
|     --ub:,--update-apps-branch: update_apps_branch=
 | |
|     -l,--without-registry-auth WITH_REGISTRY_AUTH=
 | |
| )
 | |
| parse_args "$@"; set -- "${args[@]}"
 | |
| 
 | |
| progexists docker-machine && DM_AVAILABLE=1 || DM_AVAILABLE=
 | |
| if [ -n "$DM_SET_MACHINE" ]; then
 | |
|     [ -n "$DM_AVAILABLE" ] || die "docker-machine n'est pas disponible"
 | |
|     [ "$DM_SET_MACHINE" == - ] && DM_SET_MACHINE=-u
 | |
|     setx dm_env=docker-machine env "$DM_SET_MACHINE" || die
 | |
|     eval "$dm_env"
 | |
| fi
 | |
| if [ -n "$DM_AVAILABLE" ]; then
 | |
|     for dm_profile in "${DM_PROFILES[@]}"; do
 | |
|         splitpair "$dm_profile" dm profile
 | |
|         if [ "$dm" == "$DOCKER_MACHINE_NAME" ]; then
 | |
|             DEFAULT_PROFILE="$profile"
 | |
|             break
 | |
|         fi
 | |
|     done
 | |
| fi
 | |
| 
 | |
| # construire par défaut
 | |
| [ $# -eq 0 ] && set -- build
 | |
| [ -n "$PROFILE" ] || PROFILE="$DEFAULT_PROFILE"
 | |
| 
 | |
| [ -n "$chdir" ] && { cd "$chdir" || die; }
 | |
| update_apps_mode="${update_apps_mode}${update_apps_devel:+w}"
 | |
| 
 | |
| [ -f .dk.scripts.sh ] && source ./.dk.scripts.sh
 | |
| [ -f dk.scripts.sh ] && source ./dk.scripts.sh
 | |
| 
 | |
| while [ $# -gt 0 ]; do
 | |
|     [ "$1" == -- ] && { shift; continue; }
 | |
|     cmd="$1"; shift
 | |
|     case "$cmd" in
 | |
|     get-profile|get_profile|profile)
 | |
|         echo "$PROFILE"
 | |
|         exit 0
 | |
|         ;;
 | |
|     b|build)
 | |
|         build_set_options "$update_apps_mode" "$update_apps_origin" "$update_apps_branch"
 | |
|         [ -f .build.scripts.sh ] && source ./.build.scripts.sh
 | |
|         [ -f build.scripts.sh ] && source ./build.scripts.sh
 | |
|         args=()
 | |
|         while [ $# -gt 0 -a "$1" != -- ]; do
 | |
|             args+=("$1"); shift
 | |
|         done
 | |
|         enote "Profil $PROFILE"
 | |
|         auto_build "${args[@]}" || die
 | |
|         ;;
 | |
|     p|push)
 | |
|         [ -f .build.scripts.sh ] && source ./.build.scripts.sh
 | |
|         [ -f build.scripts.sh ] && source ./build.scripts.sh
 | |
|         args=()
 | |
|         while [ $# -gt 0 -a "$1" != -- ]; do
 | |
|             args+=("$1"); shift
 | |
|         done
 | |
|         enote "Profil $PROFILE"
 | |
|         auto_push "${args[@]}" || die
 | |
|         ;;
 | |
|     s|start)
 | |
|         args=()
 | |
|         while [ $# -gt 0 -a "$1" != -- ]; do
 | |
|             args+=("$1"); shift
 | |
|         done
 | |
|         enote "Profil $PROFILE"
 | |
|         auto_up "${args[@]}" || die
 | |
|         ;;
 | |
|     k|stop)
 | |
|         args=()
 | |
|         while [ $# -gt 0 -a "$1" != -- ]; do
 | |
|             args+=("$1"); shift
 | |
|         done
 | |
|         enote "Profil $PROFILE"
 | |
|         auto_stop "${args[@]}" || die
 | |
|         ;;
 | |
|     1|up)
 | |
|         args=()
 | |
|         while [ $# -gt 0 -a "$1" != -- ]; do
 | |
|             args+=("$1"); shift
 | |
|         done
 | |
|         enote "Profil $PROFILE"
 | |
|         auto_up "${args[@]}" && auto_logs || die
 | |
|         ;;
 | |
|     l|logs)
 | |
|         args=()
 | |
|         while [ $# -gt 0 -a "$1" != -- ]; do
 | |
|             args+=("$1"); shift
 | |
|         done
 | |
|         enote "Profil $PROFILE"
 | |
|         auto_logs "${args[@]}" || die
 | |
|         ;;
 | |
|     0|down)
 | |
|         args=()
 | |
|         while [ $# -gt 0 -a "$1" != -- ]; do
 | |
|             args+=("$1"); shift
 | |
|         done
 | |
|         enote "Profil $PROFILE"
 | |
|         auto_down "${args[@]}" || die
 | |
|         ;;
 | |
|     r|run)
 | |
|         args=()
 | |
|         while [ $# -gt 0 -a "$1" != -- ]; do
 | |
|             args+=("$1"); shift
 | |
|         done
 | |
|         enote "Profil $PROFILE"
 | |
|         auto_run "${args[@]}" || die
 | |
|         ;;
 | |
|     x|exec)
 | |
|         args=()
 | |
|         while [ $# -gt 0 -a "$1" != -- ]; do
 | |
|             args+=("$1"); shift
 | |
|         done
 | |
|         enote "Profil $PROFILE"
 | |
|         auto_exec "${args[@]}" || die
 | |
|         ;;
 | |
|     d|brd)
 | |
|         do_auto_down=1
 | |
|         function auto_down_trap() {
 | |
|             [ -n "$do_auto_down" ] && auto_down
 | |
|         }
 | |
|         trap auto_down_trap 1 3 15 EXIT
 | |
| 
 | |
|         build_set_options "$update_apps_mode" "$update_apps_origin" "$update_apps_branch"
 | |
|         [ -f .build.scripts.sh ] && source ./.build.scripts.sh
 | |
|         [ -f build.scripts.sh ] && source ./build.scripts.sh
 | |
|         args=()
 | |
|         while [ $# -gt 0 -a "$1" != -- ]; do
 | |
|             args+=("$1"); shift
 | |
|         done
 | |
|         enote "Profil $PROFILE"
 | |
|         if auto_build; then
 | |
|             auto_up "${args[@]}" && auto_logs || die
 | |
|         else
 | |
|             do_auto_down=
 | |
|         fi
 | |
|         ;;
 | |
|     bs)
 | |
|         build_set_options "$update_apps_mode" "$update_apps_origin" "$update_apps_branch"
 | |
|         [ -f .build.scripts.sh ] && source ./.build.scripts.sh
 | |
|         [ -f build.scripts.sh ] && source ./build.scripts.sh
 | |
|         USE_STACK=1
 | |
|         args=()
 | |
|         while [ $# -gt 0 -a "$1" != -- ]; do
 | |
|             args+=("$1"); shift
 | |
|         done
 | |
|         enote "Profil $PROFILE"
 | |
|         auto_build && auto_up "${args[@]}"
 | |
|         ;;
 | |
|     br)
 | |
|         build_set_options "$update_apps_mode" "$update_apps_origin" "$update_apps_branch"
 | |
|         [ -f .build.scripts.sh ] && source ./.build.scripts.sh
 | |
|         [ -f build.scripts.sh ] && source ./build.scripts.sh
 | |
|         USE_STACK=1
 | |
|         args=()
 | |
|         while [ $# -gt 0 -a "$1" != -- ]; do
 | |
|             args+=("$1"); shift
 | |
|         done
 | |
|         enote "Profil $PROFILE"
 | |
|         auto_build && auto_run "${args[@]}"
 | |
|         ;;
 | |
|     y|deploy)
 | |
|         USE_STACK=1
 | |
|         args=()
 | |
|         while [ $# -gt 0 -a "$1" != -- ]; do
 | |
|             args+=("$1"); shift
 | |
|         done
 | |
|         enote "Profil $PROFILE"
 | |
|         auto_deploy "${args[@]}" || die
 | |
|         ;;
 | |
|     by|bd)
 | |
|         build_set_options "$update_apps_mode" "$update_apps_origin" "$update_apps_branch"
 | |
|         [ -f .build.scripts.sh ] && source ./.build.scripts.sh
 | |
|         [ -f build.scripts.sh ] && source ./build.scripts.sh
 | |
|         USE_STACK=1
 | |
|         args=()
 | |
|         while [ $# -gt 0 -a "$1" != -- ]; do
 | |
|             args+=("$1"); shift
 | |
|         done
 | |
|         enote "Profil $PROFILE"
 | |
|         auto_build && auto_deploy "${args[@]}"
 | |
|         ;;
 | |
|     bp)
 | |
|         build_set_options "$update_apps_mode" "$update_apps_origin" "$update_apps_branch"
 | |
|         [ -f .build.scripts.sh ] && source ./.build.scripts.sh
 | |
|         [ -f build.scripts.sh ] && source ./build.scripts.sh
 | |
|         args=()
 | |
|         while [ $# -gt 0 -a "$1" != -- ]; do
 | |
|             args+=("$1"); shift
 | |
|         done
 | |
|         enote "Profil $PROFILE"
 | |
|         auto_build && auto_push "${args[@]}"
 | |
|         ;;
 | |
|     bpy|bpd)
 | |
|         build_set_options "$update_apps_mode" "$update_apps_origin" "$update_apps_branch"
 | |
|         [ -f .build.scripts.sh ] && source ./.build.scripts.sh
 | |
|         [ -f build.scripts.sh ] && source ./build.scripts.sh
 | |
|         args=()
 | |
|         while [ $# -gt 0 -a "$1" != -- ]; do
 | |
|             args+=("$1"); shift
 | |
|         done
 | |
|         enote "Profil $PROFILE"
 | |
|         auto_build && auto_push && auto_deploy "${args[@]}"
 | |
|         ;;
 | |
|     service)
 | |
|         args=()
 | |
|         while [ $# -gt 0 -a "$1" != -- ]; do
 | |
|             args+=("$1"); shift
 | |
|         done
 | |
|         enote "Profil $PROFILE"
 | |
|         auto_service "${args[@]}" || die
 | |
|         ;;
 | |
|     u|update)
 | |
|         args=()
 | |
|         while [ $# -gt 0 -a "$1" != -- ]; do
 | |
|             args+=("$1"); shift
 | |
|         done
 | |
|         enote "Profil $PROFILE"
 | |
|         auto_service update "${args[@]}" || die
 | |
|         ;;
 | |
|     scale)
 | |
|         args=()
 | |
|         while [ $# -gt 0 -a "$1" != -- ]; do
 | |
|             args+=("$1"); shift
 | |
|         done
 | |
|         enote "Profil $PROFILE"
 | |
|         auto_service scale "${args[@]}" || die
 | |
|         ;;
 | |
|     ip|show-ip)
 | |
|         args=()
 | |
|         while [ $# -gt 0 -a "$1" != -- ]; do
 | |
|             args+=("$1"); shift
 | |
|         done
 | |
|         enote "Profil $PROFILE"
 | |
|         auto_show_ip "${args[@]}" || die
 | |
|         ;;
 | |
|     systemd-unit|systemd)
 | |
|         args=()
 | |
|         while [ $# -gt 0 -a "$1" != -- ]; do
 | |
|             args+=("$1"); shift
 | |
|         done
 | |
|         enote "Profil $PROFILE"
 | |
|         auto_systemd_unit "${args[@]}" || die
 | |
|         ;;
 | |
|     ps)
 | |
|         pscmd=(
 | |
|             "$DOCKER" container ps -a
 | |
|             --format "table {{.ID}}\t{{.Image}}\t{{.Names}}\t{{.Status}}\t{{.RunningFor}}\t{{.Ports}}"
 | |
|         )
 | |
|         filtercmd=(cat)
 | |
|         awkscript='
 | |
| NR == 1 { print; next }
 | |
| ($2 ~ filter || $3 ~ filter) { print }
 | |
| '
 | |
|         if [ $# -eq 0 ]; then
 | |
|             # pas de filtre
 | |
|             :
 | |
|         elif [ "$1" == -- ]; then
 | |
|             # fin de la commande
 | |
|             shift
 | |
|         elif [[ "$1" == *=* ]]; then
 | |
|             # filtre docker
 | |
|             pscmd+=(--filter "$1")
 | |
|             shift
 | |
|         else
 | |
|             # expression régulière
 | |
|             filtercmd=(awk -v filter="$1" "$awkscript")
 | |
|             shift
 | |
|         fi
 | |
|         set -o pipefail
 | |
|         "${pscmd[@]}" | "${filtercmd[@]}" || die
 | |
|         ;;
 | |
|     ls)
 | |
|         lscmd=(docker image ls)
 | |
|         filtercmd=(cat)
 | |
|         awkscript='
 | |
| BEGIN {
 | |
|   if (split(filter, parts, /:/) > 1) {
 | |
|     filter = parts[1]
 | |
|     tag = parts[2]
 | |
|   } else {
 | |
|     tag = ""
 | |
|   }
 | |
| }
 | |
| NR == 1 { print; next }
 | |
| (filter == "" || $1 ~ filter) && (tag == "" || $2 ~ tag) { print }
 | |
| '
 | |
|         if [ $# -eq 0 ]; then
 | |
|             # pas de filtre
 | |
|             :
 | |
|         elif [ "$1" == -- ]; then
 | |
|             # fin de la commande
 | |
|             shift
 | |
|         elif [[ "$1" == *=* ]]; then
 | |
|             # filtre docker
 | |
|             lscmd+=(--filter "$1")
 | |
|             shift
 | |
|         else
 | |
|             # expression régulière
 | |
|             filtercmd=(awk -v filter="$1" "$awkscript")
 | |
|             shift
 | |
|         fi
 | |
|         set -o pipefail
 | |
|         "${lscmd[@]}" | "${filtercmd[@]}" || die
 | |
|         ;;
 | |
|     pull)
 | |
|         lscmd=(docker image ls)
 | |
|         filtercmd=(awk 'NR == 1 { print; next } $2 !~ /</ { print }')
 | |
|         awkscript='
 | |
| BEGIN {
 | |
|   if (split(filter, parts, /:/) > 1) {
 | |
|     filter = parts[1]
 | |
|     tag = parts[2]
 | |
|   } else {
 | |
|     tag = ""
 | |
|   }
 | |
| }
 | |
| NR == 1 { print; next }
 | |
| (filter == "" || $1 ~ filter) && (tag == "" || $2 ~ tag) && $2 !~ /</ { print }
 | |
| '
 | |
|         if [ $# -eq 0 -o "$1" == -- ]; then
 | |
|             # pas de filtre
 | |
|             ewarn "pull: Vous devez spécifier l'image à mettre à jour"
 | |
|             continue
 | |
|         elif [[ "$1" == *=* ]]; then
 | |
|             # filtre docker
 | |
|             lscmd+=(--filter "$1")
 | |
|             shift
 | |
|         else
 | |
|             # expression régulière
 | |
|             filtercmd=(awk -v filter="$1" "$awkscript")
 | |
|             shift
 | |
|         fi
 | |
|         all="$("${lscmd[@]}" | "${filtercmd[@]}")"
 | |
|         setx -a images awk 'NR == 1 { next } { print $1 ":" $2 }' <<<"$all"
 | |
|         if [ ${#images[*]} -gt 0 ]; then
 | |
|             echo "$all"
 | |
|             ask_yesno "Etes-vous sûr de vouloir mettre à jour ces images?" O || die
 | |
|             for image in "${images[@]}"; do
 | |
|                 "$DOCKER" pull "$image" || die
 | |
|             done
 | |
|         fi
 | |
|         ;;
 | |
|     rm)
 | |
|         lscmd=(docker image ls)
 | |
|         filtercmd=(cat)
 | |
|         awkscript='
 | |
| BEGIN {
 | |
|   if (split(filter, parts, /:/) > 1) {
 | |
|     filter = parts[1]
 | |
|     tag = parts[2]
 | |
|   } else {
 | |
|     tag = ""
 | |
|   }
 | |
| }
 | |
| NR == 1 { print; next }
 | |
| (filter == "" || $1 ~ filter) && (tag == "" || $2 ~ tag) { print }
 | |
| '
 | |
|         if [ $# -eq 0 -o "$1" == -- ]; then
 | |
|             # pas de filtre
 | |
|             ewarn "rm: Vous devez spécifier l'image à supprimer"
 | |
|             continue
 | |
|         elif [[ "$1" == *=* ]]; then
 | |
|             # filtre docker
 | |
|             lscmd+=(--filter "$1")
 | |
|             shift
 | |
|         else
 | |
|             # expression régulière
 | |
|             filtercmd=(awk -v filter="$1" "$awkscript")
 | |
|             shift
 | |
|         fi
 | |
|         all="$("${lscmd[@]}" | "${filtercmd[@]}")"
 | |
|         setx -a images awk 'NR == 1 { next } { print $3 }' <<<"$all"
 | |
|         if [ ${#images[*]} -gt 0 ]; then
 | |
|             echo "$all"
 | |
|             ask_yesno "Etes-vous sûr de vouloir supprimer ces images?" || die
 | |
|             "$DOCKER" image rm ${FORCE:+--force} "${images[@]}" || die
 | |
|         fi
 | |
|         ;;
 | |
|     X|prune)
 | |
|         "$DOCKER" container prune -f || die
 | |
|         "$DOCKER" image prune -f || die
 | |
|         ;;
 | |
|     composer|c|ci|cu|cr|cs)
 | |
|         build_set_options "$update_apps_mode" "$update_apps_origin" "$update_apps_branch"
 | |
|         [ -f .build.scripts.sh ] && source ./.build.scripts.sh
 | |
|         [ -f build.scripts.sh ] && source ./build.scripts.sh
 | |
|         args=()
 | |
|         if [ "$cmd" == ci ]; then args+=(install)
 | |
|         elif [ "$cmd" == cu ]; then args+=(update)
 | |
|         elif [ "$cmd" == cr ]; then args+=(rshell)
 | |
|         elif [ "$cmd" == cs ]; then args+=(shell)
 | |
|         fi
 | |
|         while [ $# -gt 0 -a "$1" != -- ]; do
 | |
|             args+=("$1"); shift
 | |
|         done
 | |
|         auto_composer "${args[@]}"
 | |
|         ;;
 | |
|     *)
 | |
|         # transmettre directement à docker pour les autres commandes
 | |
|         exec "$DOCKER" "$cmd" "$@"
 | |
|     esac
 | |
| done
 |