From c202a279dd78c3b2515993715e4053d29918d2f5 Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Thu, 3 Oct 2019 15:58:07 +0400 Subject: [PATCH] dk: support COMPOSER_SETUP et COMPOSER_CMD --- dk | 196 +++++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 144 insertions(+), 52 deletions(-) diff --git a/dk b/dk index e50fc1c..fdb1278 100755 --- a/dk +++ b/dk @@ -140,17 +140,36 @@ COMMANDES Frontend pour lancer composer à l'intérieur d'un container. Les commandes 'ci', 'cu' et 'cs' sont respectivement des alias pour 'composer install', 'composer update' et 'composer shell' - Le répertoire \$HOME est monté à l'intérieur du container et le script - composer.phar du projet est utilisé le cas échéant. - L'image utilisée pour lancer composer est indiquée par la variable - d'environnement COMPOSER_IMAGE et vaut par défaut: + 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_IMAGE -- Image utilisée pour lancer composer. + 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. + La valeur par défaut est: $DEFAULT_COMPOSER_IMAGE - Cette image doit disposer de la commande 'su-exec' afin de pouvoir - lancer la commande avec l'utilisateur courant. - La commande shell est une extension qui lance un shell bash au lieu de + Spécifier 'none' pour lancer directement composer sans passer par une + image docker. + * 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 'shell' 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. + l'utilisateur root. La commande alternative 'ushell' 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) @@ -191,19 +210,21 @@ OPTIONS 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_DEVEL_SRCDIR= - APPS=() # liste d'applications à mettre à jour - app_URL= # url du dépôt - app_DEVEL_SRCDIR= # répertoire source en mode devel - app_DEST= # répertoire dans lequel faire le checkout - app_PROFILE_ORIGIN= # origine spécifique au profil 'PROFILE' - app_PROFILE_BRANCH= # branche spécifique au profil 'PROFILE' - app_ORIGIN= # ou... origine par défaut de la branche - app_BRANCH= # ou... branche par défaut - app_TYPE= # type de projet (composer par défaut) - app_AFTER_UPDATE=() # liste de commandes à lancer après le checkout + DEFAULT_COMPOSER_ACTION= + APPS=() # liste d'applications à mettre à jour + app_URL= # url du dépôt + app_DEVEL_SRCDIR= # répertoire source en mode devel + app_DEST= # répertoire dans lequel faire le checkout + app_PROFILE_ORIGIN= # origine spécifique au profil 'PROFILE' + app_ORIGIN= # ou... origine par défaut de la branche + app_PROFILE_BRANCH= # branche spécifique au profil 'PROFILE' + app_BRANCH= # ou... branche par défaut + app_TYPE= # type de projet (composer|none) + app_AFTER_UPDATE=() # liste de commandes à lancer après le checkout + app_COMPOSER_ACTION= # action projet composer (install|update|none) -u, --uu, --update-apps-only Ne faire que la mise à jour depuis les dépôts dépendants. -w, --ww, --update-apps-devel @@ -231,7 +252,7 @@ VARIABLES de update-apps.conf vaut 'develop' par défaut TYPE vaut 'composer' par défaut si le fichier composer.json existe à la - racine du projet. sinon vaut 'inconnu' par défaut + 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 @@ -239,12 +260,12 @@ VARIABLES de update-apps.conf existante auquel on enlève le préfixe update_apps_func_ Au moment où la commande est lancée, le répertoire courant est celui du projet. Les variables suivantes sont disponibles: - URL= # url du dépôt - DEVEL_SRCDIR= # répertoire source en mode devel - DEST= # répertoire dans lequel faire le checkout - ORIGIN= # ou... origine par défaut de la branche - BRANCH= # ou... branche par défaut - TYPE= # type de projet (composer par défaut) + URL= # url du dépôt + DEVEL_SRCDIR= # répertoire source en mode devel + DEST= # répertoire dans lequel faire le checkout + ORIGIN= # origine de la branche + BRANCH= # branche sélectionnée dans le dépôt + TYPE= # type de projet (composer|none) COMPOSER_ACTION vaut 'install' par défaut. Indique ce qu'il faut faire pour un projet de type 'composer' après avoir lancé les commandes de AFTER_UPDATE. Les @@ -267,8 +288,8 @@ FONCTIONS de update-apps.conf 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 - - La valeur par défaut si aucun profil de déploiement ne correspond est - de forcer le premier profil défini" + 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 "$*"; } @@ -613,7 +634,7 @@ function build_update_apps() { # 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=inconnu + else TYPE=none fi fi @@ -649,7 +670,7 @@ function build_update_apps() { # 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=inconnu + else TYPE=none fi fi fi @@ -669,9 +690,6 @@ function build_update_apps() { [ -n "$composer_action" ] || { composer_action="${var}_COMPOSER_ACTION"; composer_action="${!composer_action}"; } [ -n "$composer_action" ] || composer_action="$DEFAULT_COMPOSER_ACTION" - composer=/usr/bin/composer - [ -x "$DEST/composer.phar" ] && composer="$DEST/composer.phar" - if [ -z "$BUILD_UPDATE_DEVEL" ]; then case "${composer_action:-install}" in i|install) composer_action=install;; @@ -680,8 +698,11 @@ function build_update_apps() { *) ewarn "$composer_action: action invalide"; composer_action=;; esac if [ -n "$composer_action" ]; then + setx cwd=pwd + cd "$DEST" estep "Installation des dépendances composer" - "$composer" -d"$DEST" "$composer_action" ${PRODUCTION:+--no-dev -o} || { eend; return 1; } + auto_composer "$composer_action" ${PRODUCTION:+--no-dev -o} || { eend; return 1; } + cd "$cwd" fi fi fi @@ -1208,26 +1229,58 @@ EOF } function auto_composer() { - local -a replace_env_args env_args - if [ -f docker-compose.yml ]; then compose_set_env_args - else docker_set_env_args + local COMPOSER_IMAGE="$DEFAULT_COMPOSER_IMAGE" + 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_IMAGE=*) setv "$1"; shift;; + COMPOSER_CMD=*) setv "$1"; shift;; + COMPOSER_SETUP=*) setv "$1"; shift;; + *) break;; + esac + done + + if [ "$COMPOSER_IMAGE" == none ]; then + # lancement direct + case "$1" in + rootshell|shell|rootbash|bash) + # ewarn parce qu'on est pas root dans ce shell contrairement à ce qui est demandé + ewarn "Lancement d'un shell utilisateur" + bash "$@" + ;; + usershell|ushell|userbash|ubash) + 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 + return $? fi - local user group projdir - local actualcmd args - + 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|shell|rootbash|bash) - shift actualcmd='eval "bash $args"' + shift ;; usershell|ushell|userbash|ubash) - shift actualcmd='eval "su-exec \"$user\" bash $args"' + shift ;; *) actualcmd='eval "su-exec \"$user\" \"$composer\" $args"' @@ -1235,13 +1288,13 @@ function auto_composer() { esac setx args=qvals "$@" - local -a cmd - cmd=( - docker run -it --rm + local -a basecmd cmd setupscript runscript + basecmd=( -e user="$user" -e group="$group" - -e home="$HOME" -e projdir="$projdir" + -e setup="$COMPOSER_SETUP" + -e composer="$COMPOSER_CMD" -e args="$args" -v "$HOME:$HOME" ) @@ -1249,20 +1302,59 @@ function auto_composer() { # si le répertoire de projet ne se trouve pas dans $HOME, le monter aussi cmd+=(-v "$projdir:$projdir") fi - cmd+=( - "${COMPOSER_IMAGE:-$DEFAULT_COMPOSER_IMAGE}" - bash -c ' + setupscript='eval "$setup"' + runscript=' echo "$user" >>/etc/passwd; user="${user%%:*}" echo "$group" >>/etc/group; group="${group%%:*}" cd "$projdir" -if [ -x composer.phar ]; then composer=./composer.phar +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: unable to find composer" + 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[@]}" }