2404 lines
87 KiB
Bash
Executable File
2404 lines
87 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. Si la commande n'est pas spécifiée, la
|
|
valeur par défaut est bash. Avec les options --select-service et
|
|
--select-machine, l'argument SERVICE vaut par défaut 'SS'
|
|
Un pseudo-tty est alloué pour la commande et STDIN est ouvert.
|
|
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.
|
|
cp|copy CONTAINER:SRC DEST
|
|
cp|copy SRC CONTAINER:DEST
|
|
Copier un fichier ou un répertoire depuis/vers un container. Avec les
|
|
options --select-service et --select-machine, il est possible d'utiliser
|
|
'SS' pour signifier le container sélectionné e.g
|
|
$scriptname -s X_Y -- cp file SS:path/to/dir
|
|
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
|
|
-s, --select-service SERVICE[.N]
|
|
Sélectionner le service spécifié. Si le service a plusieurs instances,
|
|
il est possible de sélectionner une instance en particulier avec le
|
|
suffixe '.N' (par défaut, la première instance est sélectionnée)
|
|
Quand un service est sélectionné, dans les commandes 'cp' et 'exec', la
|
|
chaine 'SS' est remplacée par le nom du container correspondant e.g
|
|
$scriptname -s X_Y exec SS bash
|
|
$scriptname -s X_Y -- cp -L SS:path/to/file destdir
|
|
-t, --select-machine SERVICE[.N]
|
|
Sélectionner le service spécifié, puis choisir l'environnement
|
|
docker-machine correspondant. Cette option a la priorité sur l'option
|
|
--select-service
|
|
Cette option est traitée après l'option --set-machine, ce qui permet de
|
|
se connecter sur le manager d'un cluster puis de sélectionner le worker
|
|
sur lequel tourne un service
|
|
-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='')
|
|
app_DEST= # répertoire dans lequel faire le checkout
|
|
# ou destination si synchro avec app_SRC
|
|
app_NAME= # nom du répertoire dest si checkout; par
|
|
# défaut prendre la valeur 'app'
|
|
app_RSYNC_OPTS= # options de rsync si synchro (avec app_SRC
|
|
# ou app_DEVEL_SRCDIR)
|
|
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)
|
|
app_COMPOSER_ARGS=() # arguments de composer install|update
|
|
-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='')
|
|
DEST= # répertoire dans lequel faire le checkout
|
|
# ou destination si URL=''
|
|
NAME= # nom du répertoire dest si checkout
|
|
RSYNC_OPTS= # options de rsync si synchro avec SRC ou
|
|
# DEVEL_SRCDIR
|
|
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'
|
|
COMPOSER_ARGS
|
|
options à utiliser avec composer install|update. La valeur par défaut
|
|
dépend du profil:
|
|
prod: --no-dev -o
|
|
test: --no-dev -o
|
|
autres: (pas d'options)
|
|
|
|
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=--defaults-- PROJECT_NAME_ADD_PROFILE=
|
|
[ -f .compose.env ] && source ./.compose.env
|
|
|
|
[ -n "$PROJECT_NAME" ] || PROJECT_NAME="$(basename -- "$(pwd)")"
|
|
if [ "$PROJECT_NAME_REMOVE_SUFFIX" == --defaults-- ]; then
|
|
if [ "${PROJECT_NAME%.service}" != "$PROJECT_NAME" ]; then PROJECT_NAME="${PROJECT_NAME%.service}"
|
|
elif [ "${PROJECT_NAME%.stack}" != "$PROJECT_NAME" ]; then PROJECT_NAME="${PROJECT_NAME%.stack}"
|
|
elif [ "${PROJECT_NAME%.network}" != "$PROJECT_NAME" ]; then PROJECT_NAME="${PROJECT_NAME%.network}"
|
|
fi
|
|
else
|
|
PROJECT_NAME="${PROJECT_NAME%$PROJECT_NAME_REMOVE_SUFFIX}"
|
|
fi
|
|
|
|
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=; is_defined DEFAULT_COMPOSER_ARGS || DEFAULT_COMPOSER_ARGS=(--no-dev -o);;
|
|
test) PRODUCTION=1; DEVELOPMENT=1; is_defined DEFAULT_COMPOSER_ARGS || DEFAULT_COMPOSER_ARGS=(--no-dev -o);;
|
|
devel) PRODUCTION=; DEVELOPMENT=1; is_defined DEFAULT_COMPOSER_ARGS || DEFAULT_COMPOSER_ARGS=();;
|
|
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 NAME have_RSYNC_OPTS RSYNC_OPTS ORIGIN BRANCH TYPE after_update after_updates composer_action
|
|
local -a composer_args
|
|
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"
|
|
|
|
NAME="${var}_NAME"; NAME="${!NAME}"
|
|
[ -n "$NAME" ] || NAME="$app"
|
|
|
|
if is_defined "${var}_RSYNC_OPTS"; then
|
|
have_RSYNC_OPTS=1
|
|
RSYNC_OPTS="${var}_RSYNC_OPTS[@]"; RSYNC_OPTS=("${!RSYNC_OPTS}")
|
|
else
|
|
have_RSYNC_OPTS=
|
|
RSYNC_OPTS=()
|
|
fi
|
|
|
|
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
|
|
mkdir -p "$DEST" || { eend; return 1; }
|
|
DEST="$DEST/$NAME"
|
|
|
|
# synchronisation en mode devel
|
|
[ -n "$have_RSYNC_OPTS" ] || RSYNC_OPTS=(--delete --delete-excluded)
|
|
local -a rsync_opts; rsync_opts=(-a --exclude .git/ "${RSYNC_OPTS[@]}")
|
|
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
|
|
mkdir -p "$DEST" || { eend; return 1; }
|
|
DEST="$DEST/$NAME"
|
|
|
|
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
|
|
[ -n "$have_RSYNC_OPTS" ] || RSYNC_OPTS=(--delete --delete-excluded)
|
|
local -a rsync_opts; rsync_opts=(-a --exclude .git/ "${RSYNC_OPTS[@]}")
|
|
|
|
SRC="${SRC%/}/"
|
|
DEST="${DEST%/}"
|
|
if [ ! -d "$DEST" ]; then
|
|
# s'assurer que le répertoire parent existe
|
|
mkdir -p "$(dirname -- "$DEST")" || { eend; return 1; }
|
|
fi
|
|
DEST="$DEST/"
|
|
|
|
estep "Synchro $SRC --> $DEST"
|
|
rsync "${rsync_opts[@]}" "$SRC" "$DEST" || { eend; return 1; }
|
|
|
|
elif [ -f "$SRC" ]; then
|
|
[ -n "$have_RSYNC_OPTS" ] || RSYNC_OPTS=()
|
|
local -a rsync_opts; rsync_opts=(-a "${RSYNC_OPTS[@]}")
|
|
|
|
if [ "${DEST%/}" != "$DEST" -a ! -d "$DEST" ]; then
|
|
# on demande à ce que DEST soit un répertoire mais il
|
|
# n'existe pas: le créer
|
|
DEST="${DEST%/}"
|
|
mkdir -p "$DEST" || { eend; return 1; }
|
|
fi
|
|
|
|
if [ -d "$DEST" ]; then
|
|
DEST="$DEST/"
|
|
elif [ ! -f "$DEST" ]; then
|
|
# la destination n'existe pas: s'assurer que le répertoire
|
|
# parent existe
|
|
mkdir -p "$(dirname -- "$DEST")" || { eend; return 1; }
|
|
fi
|
|
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"
|
|
|
|
composer_args="${var}_${PROFILE}_COMPOSER_ARGS"
|
|
is_defined "$composer_args" || composer_args="${var}_COMPOSER_ARGS"
|
|
is_defined "$composer_args" || composer_args="DEFAULT_COMPOSER_ARGS"
|
|
composer_args="${composer_args}[@]"; composer_args=("${!composer_args}")
|
|
|
|
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" "${composer_args[@]}" || { 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
|
|
local container="$1"; shift
|
|
if [ -n "$SELECT_CONTAINER" ]; then
|
|
[ -z "$container" -o "$container" == SS ] && container="$SELECT_CONTAINER"
|
|
fi
|
|
local command="$1"; shift
|
|
[ -n "$command" ] || command=bash
|
|
compose_exec "$container" "$command" "$@"
|
|
elif [ -f Dockerfile ]; then
|
|
docker_set_env_args
|
|
docker_check_name set_container_name
|
|
exec_args=(-it)
|
|
local command="$1"; shift
|
|
[ -n "$command" ] || command=bash
|
|
docker_exec "$command" "$@"
|
|
else
|
|
local container="$1"; shift
|
|
if [ -n "$SELECT_CONTAINER" ]; then
|
|
[ -z "$container" -o "$container" == SS ] && container="$SELECT_CONTAINER"
|
|
fi
|
|
local command="$1"; shift
|
|
[ -n "$command" ] || command=bash
|
|
${FAKE:+qvals} "$DOCKER" exec -it "$container" "$command" "$@"
|
|
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 taskID=json_get 0.ID <<<"$taskData"
|
|
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 48:taskName 32:node 8:dState 20:cState :error
|
|
fi
|
|
if [ -z "$fnum" -o "$num" == "$fnum" ]; then
|
|
taskName="$serviceName.$taskSlot"
|
|
__format 3:"$num" 48:"$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 auto_copy() {
|
|
local src="$1"; shift
|
|
local dest="$1"; shift
|
|
if [ -n "$SELECT_CONTAINER" ]; then
|
|
if [ "${src#SS:}" != "$src" ]; then
|
|
src="$SELECT_CONTAINER${src#SS}"
|
|
elif [ "${src#:}" != "$src" ]; then
|
|
src="$SELECT_CONTAINER$src"
|
|
fi
|
|
if [ "${dest#SS:}" != "$dest" ]; then
|
|
dest="$SELECT_CONTAINER${dest#SS}"
|
|
elif [ "${dest#:}" != "$dest" ]; then
|
|
dest="$SELECT_CONTAINER$dest"
|
|
fi
|
|
fi
|
|
|
|
"$DOCKER" cp "$src" "$dest" "$@"
|
|
}
|
|
|
|
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=
|
|
SELECT_CONTAINER=
|
|
SELECT_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=
|
|
-s:,--select-service: SELECT_CONTAINER=
|
|
-t:,--select-machine: SELECT_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 "$SELECT_MACHINE" -o -n "$SELECT_CONTAINER" ]; then
|
|
function __ss_process_data() {
|
|
[ -n "$found" ] && return
|
|
__status_query_task
|
|
__status_query_service
|
|
if [ -n "$slot" ]; then
|
|
if [ "$taskSlot" == "$slot" ]; then
|
|
# ne prendre que le slot qui correspond
|
|
found=1
|
|
fi
|
|
else
|
|
# prendre le premier
|
|
found=1
|
|
fi
|
|
taskName="$serviceName.$taskSlot"
|
|
}
|
|
|
|
if [ -n "$SELECT_MACHINE" ]; then service="$SELECT_MACHINE"
|
|
elif [ -n "$SELECT_CONTAINER" ]; then service="$SELECT_CONTAINER"
|
|
fi
|
|
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
|
|
docker_set_deploy_args set_container_name
|
|
service="${container_name}_${service#${container_name}_}"
|
|
fi
|
|
if [[ "$service" == *.* ]]; then
|
|
slot="${service##*.}"
|
|
service="${service%.*}"
|
|
else
|
|
slot=
|
|
fi
|
|
|
|
psargs=(
|
|
--filter desired-state=running
|
|
--format "taskID={{.ID}};node={{.Node}};__ss_process_data"
|
|
)
|
|
found=
|
|
eval "$("$DOCKER" service ps "$service" "${psargs[@]}" 2>/dev/null)"
|
|
|
|
if [ -n "$found" ]; then
|
|
SELECT_CONTAINER="$serviceName.$taskSlot.$taskID"
|
|
if [ -n "$SELECT_MACHINE" ]; then
|
|
DM_SET_MACHINE="$node"
|
|
else
|
|
enote "Sélection du container $SELECT_CONTAINER"
|
|
fi
|
|
else
|
|
die "$service${slot:+.$slot}: service introuvable"
|
|
fi
|
|
fi
|
|
if [ -n "$SELECT_MACHINE" ]; then
|
|
enote "Sélection de la machine $DM_SET_MACHINE"
|
|
[ -n "$SELECT_CONTAINER" ] && enote "Sélection du container $SELECT_CONTAINER"
|
|
|
|
[ -n "$DM_AVAILABLE" ] || die "docker-machine n'est pas disponible"
|
|
setx dm_env=docker-machine env "$DM_SET_MACHINE" || die
|
|
eval "$dm_env"
|
|
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
|
|
;;
|
|
cp|copy)
|
|
args=()
|
|
while [ $# -gt 0 -a "$1" != -- ]; do
|
|
args+=("$1"); shift
|
|
done
|
|
enote "Profil $PROFILE"
|
|
auto_copy "${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
|