2202 lines
		
	
	
		
			78 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			2202 lines
		
	
	
		
			78 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 json
 | 
						|
 | 
						|
function display_help() {
 | 
						|
    uecho "$scriptname: outil pour faciliter l'utilisation de docker
 | 
						|
 | 
						|
USAGE
 | 
						|
    $scriptname CMDs...
 | 
						|
 | 
						|
Si une commande commence ou se termine par un underscore, e.g '_ls', elle est
 | 
						|
passée telle quelle à docker (en enlevant l'underscore d'abord, bien sûr). Si
 | 
						|
une commande ne figure pas dans la liste ci-dessous, elle est passée telle
 | 
						|
quelle à docker.
 | 
						|
 | 
						|
Certaines commandes ci-dessous ont le même nom que des commandes docker, et
 | 
						|
nécessitent un projet docker ou docker-compose. Si ces commandes sont lancées
 | 
						|
alors qu'on n'est pas dans un projet docker, alors elles sont passées telle
 | 
						|
quelles à docker. ATTENTION: comme la commande est exécutée par docker, cela
 | 
						|
veut dire qu'elle n'aura pas la même sématique.
 | 
						|
 | 
						|
COMMANDES
 | 
						|
    get-profile
 | 
						|
        Afficher le profil courant
 | 
						|
    b|build [NAME=VALUE...] [SERVICE]
 | 
						|
        Construire les images. Les variables NAME=VALUE sont des 'build args'
 | 
						|
    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 [NAME=VALUE...]
 | 
						|
        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 [NAME=VALUE...]
 | 
						|
        Construire les images (comme avec build) puis démarrer les services
 | 
						|
        (comme avec start)
 | 
						|
        Equivalent à -- build -- start [args]
 | 
						|
    br [NAME=VALUE...] SERVICE [COMMAND]
 | 
						|
        Construire les images (comme avec build) puis démarrer le service avec
 | 
						|
        la commande spécifiée (comme avec run)
 | 
						|
        Equivalent à -- build [NAME=VALUE...] -- run [args]
 | 
						|
    y|deploy [args...]
 | 
						|
        (Re)déployer un stack. Cette commande ne fonctionne qu'en mode swarm.
 | 
						|
        Implique --stack
 | 
						|
    by|bd [NAME=VALUE...] [args...]
 | 
						|
        Equivalent à --stack -- build [NAME=VALUE...] -- deploy args...
 | 
						|
        Utilisable notamment en développement
 | 
						|
    bp [NAME=VALUE...] [args...]
 | 
						|
        Equivalent à --stack -- build [NAME=VALUE...] -- push args...
 | 
						|
    bpy|bpd [NAME=VALUE...] [args...]
 | 
						|
        Equivalent à --stack -- build [NAME=VALUE...] -- push -- deploy args...
 | 
						|
    ser|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
 | 
						|
    sta|status [SERVICE] [num]
 | 
						|
        Afficher le status du service spécifié: pour chaque occurence, sur quel
 | 
						|
        noeud il tourne (ou tournait), quel est le statut actuel ainsi que le
 | 
						|
        message associé. Si le service n'est pas spécifié, prendre la liste des
 | 
						|
        services affichée par docker service ls
 | 
						|
        'num' est le numéro de l'instance de service. Si ce numéro est précisé,
 | 
						|
        afficher les informations uniquement pour cette instance là, ainsi que
 | 
						|
        les logs
 | 
						|
        Il est possible de spécifier un filtre docker name=value avant 'num'. Ce
 | 
						|
        filtre est utilisé pour sélectionner certaines instances du service.
 | 
						|
            - id=<ID> a task's ID ou prefix
 | 
						|
            - name=<string> a task's name or prefix
 | 
						|
            - node=<string> a node's name or ID
 | 
						|
            - desired-state=(running|shutdown|accepted)
 | 
						|
        Pour faciliter l'utilisation des filtres, certains aliases sont définis.
 | 
						|
        '=r', '=k' et '=a' sont des aliases pour desired-state=running,
 | 
						|
        desired-state=shutdown et desired-state=accepted respectivement
 | 
						|
    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
 | 
						|
        correspondance 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 du dépôt en mode devel
 | 
						|
            app_SRC=              # répertoire/fichier source (si URL pas renseigné)
 | 
						|
            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
 | 
						|
    SRC
 | 
						|
        répertoire/fichier source, si URL n'est pas défini. si ce chemin est
 | 
						|
        relatif, il doit être exprimé par rapport au répertoire du projet.
 | 
						|
        IMPORTANT: dans ce cas, DEST n'est pas le répertoire de base du
 | 
						|
        checkout, mais le répertoire destination pour la synchro
 | 
						|
    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
 | 
						|
            SRC=                  # répertoire/fichier source (si URL pas renseigné)
 | 
						|
            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, ne déployer en prod que la branche master
 | 
						|
    [ -z "$DEFAULT_BRANCH" -a "$PROFILE" == prod ] && DEFAULT_BRANCH=develop #XXX 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 SRC 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}"
 | 
						|
        if [ -z "$URL" ]; then
 | 
						|
            SRC="${var}_SRC"; SRC="${!SRC}"
 | 
						|
            if [ -z "$SRC" ]; then
 | 
						|
                ewarn "$app: vous devez définir ${var}_URL ou ${var}_SRC"
 | 
						|
                eend; return 1
 | 
						|
            fi
 | 
						|
        fi
 | 
						|
 | 
						|
        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}"
 | 
						|
 | 
						|
        if [ -n "$BUILD_UPDATE_DEVEL" ]; then
 | 
						|
            DEST="$DEST/$app"
 | 
						|
 | 
						|
            # 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
 | 
						|
        elif [ -n "$URL" ]; then
 | 
						|
            DEST="$DEST/$app"
 | 
						|
 | 
						|
            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 et ci-dessous
 | 
						|
                if [ -f "$DEST/composer.json" ]; then TYPE=composer
 | 
						|
                else TYPE=none
 | 
						|
                fi
 | 
						|
            fi
 | 
						|
 | 
						|
        elif [ -n "$SRC" ]; then
 | 
						|
            if [ -d "$SRC" ]; then
 | 
						|
                local -a rsync_opts; rsync_opts=(-a --delete --exclude .git/ --delete-excluded)
 | 
						|
                estep "Synchro $SRC/ --> $DEST"
 | 
						|
                rsync "${rsync_opts[@]}" "$SRC/" "$DEST/" || { eend; return 1; }
 | 
						|
            elif [ -f "$SRC" ]; then
 | 
						|
                local -a rsync_opts; rsync_opts=(-a)
 | 
						|
                estep "Synchro $SRC --> $DEST"
 | 
						|
                rsync "${rsync_opts[@]}" "$SRC" "$DEST/" || { eend; return 1; }
 | 
						|
            else
 | 
						|
                eerror "$app: $SRC: répertoire/fichier introuvable"
 | 
						|
                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
 | 
						|
 | 
						|
        else
 | 
						|
            # ne devrait pas se produire
 | 
						|
            die "ni URL ni SRC ne sont définis"
 | 
						|
        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 __parse_bargs() {
 | 
						|
    bargs=()
 | 
						|
    args=()
 | 
						|
    while [ $# -gt 0 ]; do
 | 
						|
        [[ "$1" == *=* ]] && bargs+=("$1") || args+=("$1")
 | 
						|
        shift
 | 
						|
    done
 | 
						|
}
 | 
						|
function auto_build() {
 | 
						|
    local -a replace_env_args env_args
 | 
						|
    local -a replace_build_args build_args
 | 
						|
    initialize_build_env
 | 
						|
 | 
						|
    local -a args bargs; local barg
 | 
						|
    __parse_bargs "$@"
 | 
						|
    set -- "${args[@]}"
 | 
						|
 | 
						|
    if [ -f docker-compose.yml ]; then
 | 
						|
        compose_set_env_args
 | 
						|
        update_build_env "${bargs[@]}"
 | 
						|
        build_update_apps || return 1
 | 
						|
        compose_build "$@"
 | 
						|
    elif [ -f Dockerfile ]; then
 | 
						|
        docker_parse_env_args
 | 
						|
        docker_check_name
 | 
						|
        docker_add_build_arg build_date "$(date +%y%m%d)"
 | 
						|
        update_build_env "${bargs[@]}"
 | 
						|
        build_update_apps || return 1
 | 
						|
        docker_build "$@"
 | 
						|
    else
 | 
						|
        for barg in "${bargs[@]}"; do
 | 
						|
            replace_build_args+=(--build-arg "$barg")
 | 
						|
        done
 | 
						|
        ${FAKE:+qvals} "$DOCKER" build \
 | 
						|
            ${NO_CACHE:+--no-cache} \
 | 
						|
            "${replace_build_args[@]}" "$@"
 | 
						|
    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 "$@"
 | 
						|
    elif [ -f Dockerfile ]; then
 | 
						|
        docker_parse_env_args
 | 
						|
        docker_check_name
 | 
						|
        update_build_env
 | 
						|
        docker_push "$@"
 | 
						|
    else
 | 
						|
        ${FAKE:+qvals} "$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 "$@"
 | 
						|
    elif [ -f Dockerfile ]; then
 | 
						|
        docker_set_env_args
 | 
						|
        docker_check_name set_container_name
 | 
						|
        replace_run_args=(-d --name "$container_name")
 | 
						|
        docker_up "$@"
 | 
						|
    else
 | 
						|
        ${FAKE:+qvals} "$DOCKER" run "$@"
 | 
						|
    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 "$@"
 | 
						|
    elif [ -f Dockerfile ]; then
 | 
						|
        docker_set_env_args
 | 
						|
        docker_check_name set_container_name
 | 
						|
        docker_stop "$@"
 | 
						|
    else
 | 
						|
        ${FAKE:+qvals} "$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 "$@"
 | 
						|
    elif [ -f Dockerfile ]; then
 | 
						|
        docker_set_env_args
 | 
						|
        docker_check_name set_container_name
 | 
						|
        replace_logs_args=(-f)
 | 
						|
        docker_logs "$@"
 | 
						|
    else
 | 
						|
        ${FAKE:+qvals} "$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 "$@"
 | 
						|
    elif [ -f Dockerfile ]; then
 | 
						|
        docker_set_env_args
 | 
						|
        docker_check_name set_container_name
 | 
						|
        docker_down "$@"
 | 
						|
    else
 | 
						|
        ${FAKE:+qvals} "$DOCKER" stop "$@"
 | 
						|
    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 disable_tty
 | 
						|
    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=
 | 
						|
        -T disable_tty=1
 | 
						|
        @ 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"}
 | 
						|
            ${disable_tty:+-T}
 | 
						|
        )
 | 
						|
        compose_run "$@"
 | 
						|
    elif [ -f Dockerfile ]; then
 | 
						|
        docker_set_env_args
 | 
						|
        docker_check_name set_container_name
 | 
						|
        replace_run_args=(
 | 
						|
            --name "$container_name"
 | 
						|
            ${rm:+--rm}
 | 
						|
            ${volume:+-v "$volume"}
 | 
						|
        )
 | 
						|
        docker_run "$@"
 | 
						|
    else
 | 
						|
        ${FAKE:+qvals} "$DOCKER" run ${rm:+--rm} ${volume:+-v "$volume"} "$@"
 | 
						|
    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 "$@"
 | 
						|
    elif [ -f Dockerfile ]; then
 | 
						|
        docker_set_env_args
 | 
						|
        docker_check_name set_container_name
 | 
						|
        docker_exec "$@"
 | 
						|
    else
 | 
						|
        ${FAKE:+qvals} "$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
 | 
						|
        ${FAKE:+qvals} "$DOCKER" service "$@"
 | 
						|
    fi
 | 
						|
}
 | 
						|
 | 
						|
function __format() {
 | 
						|
    # formatter une liste de valeur. chaque argument est de la forme [SIZE:]VALUE
 | 
						|
    # il ne faudrait utiliser la forme VALUE que pour le dernier argument
 | 
						|
    local size value
 | 
						|
    for value in "$@"; do
 | 
						|
        if [[ "$value" == *:* ]]; then
 | 
						|
            size="${value%%:*}"
 | 
						|
            value="${value#*:}"
 | 
						|
        else
 | 
						|
            size=
 | 
						|
        fi
 | 
						|
        if [ -n "$size" ]; then
 | 
						|
            while [ "${#value}" -lt "$size" ]; do
 | 
						|
                value="$value "
 | 
						|
            done
 | 
						|
            if [ "${#value}" -gt "$size" ]; then
 | 
						|
                [ "$size" -gt 1 ] && value="${value:0:$(($size - 1))}"
 | 
						|
                value="$value"$'\xe2\x80\xa6'
 | 
						|
            fi
 | 
						|
        fi
 | 
						|
        echo -n "${value} "
 | 
						|
    done
 | 
						|
    echo
 | 
						|
}
 | 
						|
 | 
						|
function __status_query_task() {
 | 
						|
    setx taskData="$DOCKER" inspect "$taskID"
 | 
						|
    setx taskSlot=json_get 0.Slot <<<"$taskData"
 | 
						|
    setx taskStatus=json_get 0.Status.Err <<<"$taskData"
 | 
						|
    setx serviceID=json_get 0.ServiceID <<<"$taskData"
 | 
						|
}
 | 
						|
function __status_query_service() {
 | 
						|
    [ "$serviceID" == "$pServiceID" ] && return
 | 
						|
    setx serviceData="$DOCKER" inspect "$serviceID"
 | 
						|
    setx serviceName=json_get 0.Spec.Name <<<"$serviceData"
 | 
						|
    setx serviceUpdateStatus=json_get 0.UpdateStatus.Message <<<"$serviceData"
 | 
						|
    pServiceID="$serviceID"
 | 
						|
}
 | 
						|
function __status_process_data() {
 | 
						|
    __status_query_task
 | 
						|
    __status_query_service
 | 
						|
    if [ -n "$serviceUpdateStatus" ]; then
 | 
						|
        echo "\
 | 
						|
================
 | 
						|
$serviceName: $serviceUpdateStatus
 | 
						|
================"
 | 
						|
        serviceUpdateStatus=
 | 
						|
    fi
 | 
						|
    if [ "$num" -eq 0 ]; then
 | 
						|
        # afficher les en-têtes
 | 
						|
        __format 3:num 32:taskName 32:node 8:dState 20:cState :error
 | 
						|
    fi
 | 
						|
    if [ -z "$fnum" -o "$num" == "$fnum" ]; then
 | 
						|
        taskName="$serviceName.$taskSlot"
 | 
						|
        __format 3:"$num" 32:"$taskName.$taskID" 32:"$node" 8:"$desiredState" 20:"$currentState" :"$taskStatus"
 | 
						|
    fi
 | 
						|
    if [ "$num" == "$fnum" ]; then
 | 
						|
        "$DOCKER" service logs -f "$taskID"
 | 
						|
    fi
 | 
						|
    let num=num+1
 | 
						|
}
 | 
						|
function auto_status() {
 | 
						|
    local -a services
 | 
						|
    local service
 | 
						|
    if [[ "$1" == *=* ]]; then
 | 
						|
        : # le premier argument est un filtre
 | 
						|
    elif [ -n "$1" -a -z "${1//[0-9]/}" ]; then
 | 
						|
        : # le premier argument est un numéro d'instance
 | 
						|
    else
 | 
						|
        # le premier argument est un nom de service
 | 
						|
        service="$1"; shift
 | 
						|
    fi
 | 
						|
    if [ -n "$service" ]; then
 | 
						|
        if [ -f docker-compose.yml -o -f docker-stack.yml ]; then
 | 
						|
            # si on est dans répertoire de projet, il est possible de spécifier
 | 
						|
            # le service sans préfixe
 | 
						|
            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}_}"
 | 
						|
        fi
 | 
						|
        services=("$service")
 | 
						|
    else
 | 
						|
        # lister les services qui tournent actuellement
 | 
						|
        setx -a services=docker service ls --format "{{.Name}}"
 | 
						|
    fi
 | 
						|
 | 
						|
    local -a psargs
 | 
						|
    local filter fnum
 | 
						|
    psargs=(
 | 
						|
        --format "taskID={{.ID}};node={{.Node}};desiredState='{{.DesiredState}}';currentState='{{.CurrentState}}';__status_process_data"
 | 
						|
    )
 | 
						|
    while [[ "$1" == *=* ]]; do
 | 
						|
        filter="$1"
 | 
						|
        case "$filter" in
 | 
						|
        =r) filter="desired-state=running";;
 | 
						|
        =k) filter="desired-state=shutdown";;
 | 
						|
        =a) filter="desired-state=accepted";;
 | 
						|
        esac
 | 
						|
        psargs+=(--filter "$filter")
 | 
						|
        shift
 | 
						|
    done
 | 
						|
    fnum="$1"; shift
 | 
						|
 | 
						|
    local num=0 taskData taskStatus taskSlot pServiceID serviceID serviceData serviceName serviceUpdateStatus
 | 
						|
    for service in "${services[@]}"; do
 | 
						|
        eval "$("$DOCKER" service ps "$service" "${psargs[@]}")"
 | 
						|
    done
 | 
						|
}
 | 
						|
 | 
						|
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"
 | 
						|
    # pour warning ci-dessous
 | 
						|
    [ "$DM_SET_MACHINE" == -u ] && DM_SET_MACHINE=
 | 
						|
fi
 | 
						|
if [ -n "$DM_AVAILABLE" ]; then
 | 
						|
    found=
 | 
						|
    for dm_profile in "${DM_PROFILES[@]}"; do
 | 
						|
        splitpair "$dm_profile" dm profile
 | 
						|
        if [ "$dm" == "$DOCKER_MACHINE_NAME" ]; then
 | 
						|
            DEFAULT_PROFILE="$profile"
 | 
						|
            found=1
 | 
						|
            break
 | 
						|
        fi
 | 
						|
    done
 | 
						|
    if [ -n "$DM_SET_MACHINE" -a -z "$PROFILE" -a -z "$found" ]; then
 | 
						|
        ewarn "\
 | 
						|
Aucun profil n'a été défini pour $DM_SET_MACHINE dans ~/etc/default/dk
 | 
						|
== Le profil $DEFAULT_PROFILE sera utilisé =="
 | 
						|
        sleep 3
 | 
						|
    fi
 | 
						|
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"
 | 
						|
        __parse_bargs "${args[@]}"
 | 
						|
        if auto_build "${bargs[@]}"; 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"
 | 
						|
        __parse_bargs "${args[@]}"
 | 
						|
        auto_build "${bargs[@]}" && auto_up "${args[@]}" || die
 | 
						|
        ;;
 | 
						|
    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"
 | 
						|
        __parse_bargs "${args[@]}"
 | 
						|
        auto_build "${bargs[@]}" && auto_run "${args[@]}" || die
 | 
						|
        ;;
 | 
						|
    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"
 | 
						|
        __parse_bargs "${args[@]}"
 | 
						|
        auto_build "${bargs[@]}" && auto_deploy "${args[@]}" || die
 | 
						|
        ;;
 | 
						|
    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"
 | 
						|
        __parse_bargs "${args[@]}"
 | 
						|
        auto_build "${bargs[@]}" && auto_push "${args[@]}" || die
 | 
						|
        ;;
 | 
						|
    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"
 | 
						|
        __parse_bargs "${args[@]}"
 | 
						|
        auto_build "${bargs[@]}" && auto_push && auto_deploy "${args[@]}" || die
 | 
						|
        ;;
 | 
						|
    ser|service)
 | 
						|
        args=()
 | 
						|
        while [ $# -gt 0 -a "$1" != -- ]; do
 | 
						|
            args+=("$1"); shift
 | 
						|
        done
 | 
						|
        enote "Profil $PROFILE"
 | 
						|
        auto_service "${args[@]}" || die
 | 
						|
        ;;
 | 
						|
    sta|status)
 | 
						|
        args=()
 | 
						|
        while [ $# -gt 0 -a "$1" != -- ]; do
 | 
						|
            args+=("$1"); shift
 | 
						|
        done
 | 
						|
        enote "Profil $PROFILE"
 | 
						|
        auto_status "${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 } { if ($1 == "<none>" || $2 == "<none>") { print $3 } else { print $1 ":" $2 } }' <<<"$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
 | 
						|
        cmd="${cmd#_}"
 | 
						|
        cmd="${cmd%_}"
 | 
						|
        args=()
 | 
						|
        while [ $# -gt 0 -a "$1" != -- ]; do
 | 
						|
            args+=("$1"); shift
 | 
						|
        done
 | 
						|
        "$DOCKER" "$cmd" "${args[@]}"
 | 
						|
        ;;
 | 
						|
    *)
 | 
						|
        # transmettre directement à docker
 | 
						|
        args=()
 | 
						|
        while [ $# -gt 0 -a "$1" != -- ]; do
 | 
						|
            args+=("$1"); shift
 | 
						|
        done
 | 
						|
        "$DOCKER" "$cmd" "${args[@]}"
 | 
						|
    esac
 | 
						|
done
 |