3232 lines
111 KiB
Bash
Executable File
3232 lines
111 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 ptools xmlsupport
|
|
|
|
SELF="$script"
|
|
TEMPLATEDIR="$scriptdir/lib/dkbuild/templates"
|
|
|
|
[ -n "$COMPOSE_V1" ] && DOCKER_COMPOSE=(docker-compose) || DOCKER_COMPOSE=(docker compose)
|
|
|
|
function get_default_phpbuilder_image() {
|
|
echo "${REGISTRY:-pubdocker.univ-reunion.fr}/image/phpbuilder:${DIST:-d11}"
|
|
}
|
|
function get_default_javabuilder_image() {
|
|
echo "${REGISTRY:-pubdocker.univ-reunion.fr}/image/javabuilder:d11"
|
|
}
|
|
|
|
##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
## Aide
|
|
|
|
function display_help() {
|
|
uecho "$scriptname: construire une image docker
|
|
|
|
USAGE
|
|
$scriptname action [options]
|
|
|
|
OPTIONS
|
|
--hdk, --help-dkbuild
|
|
Afficher l'aide sur le format du fichier dkbuild
|
|
--href, --help-reference
|
|
Afficher la référence sur les commandes utilisables dans un fichier
|
|
dkbuild
|
|
--compose-v1
|
|
Forcer l'utilisation de docker-compose v1
|
|
|
|
ACTIONS
|
|
|
|
$scriptname templates
|
|
lister les templates valides pour 'init --template'
|
|
|
|
$scriptname init [OPTIONS] [PROJDIR [NAME [GROUP]]]
|
|
initialiser un répertoire pour la construction d'une ou plusieurs images
|
|
docker, selon un modèle prédéfini
|
|
|
|
-j, --projdir PROJDIR
|
|
Spécifier le répertoire de projet à créer/mettre à jour. le répertoire
|
|
par défaut est le répertoire courant.
|
|
-t, --template TEMPLATE
|
|
Nom du modèle à utiliser. Utiliser 'default' par défaut
|
|
-v, --var VAR=VALUE
|
|
Spécifier une variable pour la génération des fichiers à partir du
|
|
modèle. Le nom de la variable est mis en majuscule avant remplacement
|
|
dans les fichiers
|
|
-n, --name NAME
|
|
-g, --group GROUP
|
|
Raccourcis pour respectivement -vname=NAME et -vgroup=GROUP
|
|
|
|
$scriptname build [OPTIONS] [BUILDVARS...]
|
|
construire les images. C'est l'action par défaut
|
|
|
|
Les arguments BUILDVARS de la forme ARG=VALUE permettent de spécifier des
|
|
arguments de build comme avec l'option --arg
|
|
|
|
-m, --machine MACHINE
|
|
Sélectionner la machine spécifiée avant de dérouler le script
|
|
-j, --projdir PROJDIR
|
|
Spécifier le répertoire de projet. Si cette option n'est pas spécifiée,
|
|
remonter la hiérarchie et prendre le premier répertoire qui contient un
|
|
fichier nommé dkbuild.
|
|
Si PROJDIR est un fichier, c'est ce fichier qui est utilisé comme script
|
|
de build. Le répertoire de projet sélectionné est le répertoire qui
|
|
contient le script de build.
|
|
Si le répertoire PROJDIR contient un fichier du même nom de base que le
|
|
fichier de build avec l'extension '.env' (i.e dkbuild.env par défaut),
|
|
ce fichier est lu de la même façon qu'un fichier de configuration
|
|
-c, --config CONFIG
|
|
Lire un fichier de configuration au format dkbuild. Si cette option
|
|
n'est pas spécifiée, les fichiers ~/.dkbuild.env et /etc/dkbuild.env
|
|
sont testés dans l'ordre et automatiquement sélectionnés s'ils existent.
|
|
L'ordre de priorité est le suivant:
|
|
- d'abord les variables spécifiées avec --env et --arg,
|
|
- puis les variables définies dans ce fichier de configuration,
|
|
- puis celles définies dans dkbuild.env le cas échéant
|
|
- puis celles définies dans le fichier de build courant.
|
|
Utiliser la valeur spéciale 'none' pour indiquer qu'aucun fichier de
|
|
configuration ne doit être chargé.
|
|
|
|
-d, --dist DIST
|
|
-0, --d10
|
|
-1, --d11
|
|
-2, --d12
|
|
-3, --d13
|
|
--r7, --rhel7
|
|
--r8, --rhel8
|
|
--r9, --rhel9
|
|
--o7, --oracle7
|
|
--o8, --oracle8
|
|
--o9, --oracle9
|
|
Ne faire le build que pour la distribution spécifiée. Par défaut, faire
|
|
le build pour toutes les distributions définies. Si la distribution
|
|
sélectionnée n'est pas valide pour ce build, elle est ignorée
|
|
|
|
--profile PROFILE
|
|
-P, --prod
|
|
-T, --test
|
|
-E, --dtest
|
|
--devel
|
|
Spécifier le profil dans lequel construire l'image
|
|
--all-profiles
|
|
Construire l'image dans tous les profils définis
|
|
|
|
-e, --env VAR=VALUE
|
|
Spécifier la valeur d'une variable d'environnement. Cette valeur
|
|
remplace la valeur par défaut spécifiée dans le fichier de build.
|
|
--arg ARG=VALUE
|
|
Spécifier la valeur d'un argument de build. Cette valeur remplace la
|
|
valeur par défaut spécifiée dans le fichier de build.
|
|
|
|
-u, --clean-update
|
|
Avant de faire le build, faire un clean, suivi de git pull. C'est la
|
|
méthode préférée pour mettre à jour le dépôt s'il y a des fichiers
|
|
synchronisé avec la commande 'copy', parce que sinon les fichiers
|
|
sources (mis à jour par git pull) sont désynchronisés d'avec les
|
|
fichiers destination.
|
|
--clone-src-only
|
|
Ne faire que cloner les dépôts sources mentionnés avec la commande
|
|
'checkout'
|
|
--update-src-only
|
|
Ne faire que mettre à jour les dépôts sources mentionnés avec la
|
|
commande 'checkout'
|
|
--update-src
|
|
Avec la commande 'checkout', mettre à jour les dépôts avant de faire le
|
|
build. C'est la valeur par défaut.
|
|
--no-update-src
|
|
Ne pas mettre à jour les dépôts avant de faire le build. La commande
|
|
'checkout' devient un NOP si le dépôt existe déjà.
|
|
-w, --update-devel-src
|
|
Ne pas mettre à jour le dépôt, préférer la synchronisation depuis la
|
|
version de développement d'un dépôt
|
|
-s, --sync-src
|
|
Avec la commande 'copy', effectuer la mise à jour des fichiers. C'est la
|
|
valeur par défaut si on construit l'image
|
|
--no-sync-src
|
|
Ne pas mettre à jour les fichiers. La commande 'copy' devient un NOP si
|
|
le fichier destination existe.
|
|
-b, --build
|
|
Construire les images
|
|
--no-cache
|
|
Ne pas utiliser le cache lors du build
|
|
--plain-output
|
|
Afficher la sortie complète des containers lors du build
|
|
-U, --pull-image
|
|
Essayer de récupérer une version plus récente de l'image source
|
|
-p, --push-image
|
|
Pousser les images construites vers la registry
|
|
|
|
$scriptname clean [OPTIONS] [DIRS...]
|
|
nettoyer le projet des fichiers créés par 'copy gitignore=', en utilisant la
|
|
commande 'git clean -dX'
|
|
|
|
-j, --projdir PROJDIR
|
|
Spécifier le répertoire de projet
|
|
-X, --ignored
|
|
Utiliser l'option -X de git clean pour ne supprimer que les fichiers
|
|
ignorés par git. c'est l'option par défaut.
|
|
-x, --untracked
|
|
Utiliser l'option -x de git clean pour supprimer aussi les fichiers non
|
|
suivis.
|
|
-a, --all
|
|
Supprimer aussi les fichiers listés par 'git status --ignored'. Cela
|
|
permet de supprimer un maximum de fichiers qui ne font pas partie du
|
|
projet. Cette option implique --untracked
|
|
|
|
$scriptname composer DESTDIR [ACTION [PARAMS] [ARGS]]
|
|
lancer composer dans le répertoire spécifié
|
|
|
|
cf la documentation de la commande 'composer' pour la description des
|
|
paramètres
|
|
|
|
$scriptname mvn DESTDIR [ACTION [PARAMS] [ARGS]]
|
|
lancer maven dans le répertoire spécifié
|
|
|
|
cf la documentation de la commande 'mvn' pour la description des paramètres
|
|
|
|
$scriptname dump [OPTIONS]
|
|
afficher les valeurs des variables
|
|
|
|
Les options suivantes ont la même signification que pour l'action build:
|
|
--machine, --projdir, --config, --dist, --profile, --all-profiles, --env,
|
|
--arg"
|
|
}
|
|
|
|
function display_help_dkbuild() {
|
|
uecho "\
|
|
OPTIONS
|
|
--help Aide générale
|
|
* --hdk Aide sur le format du fichier dkbuild
|
|
--href Référence sur les commandes utilisables dans un fichier dkbuild
|
|
|
|
DKBUILD
|
|
=======
|
|
|
|
Un fichier dkbuild est un script shell utilisé pour construire une ou plusieurs
|
|
images docker.
|
|
|
|
A cause de l'implémentation utilisée pour les directives, le fichier doit être
|
|
parcouru (i.e exécuté) à de multiples reprises pour analyser les paramètres et
|
|
variables définis. il faut donc \"protéger\" les appels de scripts externes ou
|
|
de fonctions gourmandes avec les commandes 'run' et 'call' pour éviter que ces
|
|
commandes ne soient exécutées à plusieurs reprises.
|
|
|
|
Quand un fichier dkbuild est exécuté, le répertoire courant est toujours le
|
|
répertoire qui contient le fichier
|
|
|
|
## Distributions ###############################################################
|
|
|
|
Une distribution s'entend au sens de la distribution linux utilisée comme base
|
|
pour l'image construite. L'idée est de pouvoir construire des images similaires
|
|
qui ne diffèrent que par la version de base du système d'exploitation
|
|
|
|
Pour une même distribution, plusieurs versions d'une image peuvent être
|
|
construites. Une version est définie en ajoutant un préfixe à la distribution.
|
|
|
|
La commande 'setdists' permet de lister explicitement les distributions valides
|
|
(et les versions associées le cas échéant). Si la distribution sélectionnée par
|
|
l'utilisateur n'est pas dans la liste fournie, le script s'arrête sans erreur.
|
|
La première distribution listée est spéciale: c'est la distribution la plus
|
|
récente, celle qui reçoit le tag :latest
|
|
|
|
La commande 'dist' permet de tester si la distribution spécifiée en argument a
|
|
été sélectionnée par l'utilisateur. L'argument 'LATEST' permet de tester la
|
|
dernière distribution.
|
|
|
|
La commande 'version' permet de tester si la version spécifiée en argument a été
|
|
sélectionnée par l'utilisateur. On part du principe qu'une distribution a déjà
|
|
été testée au préalable avec 'dist'
|
|
|
|
Exemple:
|
|
setdists 3.0-d11 3.1-d11 d10 d9
|
|
if dist d11; then
|
|
if version 3.0; then
|
|
...
|
|
elif version 3.1; then
|
|
...
|
|
fi
|
|
elif dist d10; then
|
|
...
|
|
elif dist d9; then
|
|
...
|
|
fi
|
|
Dans une même distribution, les versions doivent être ordonnées de la plus
|
|
ancienne à la plus récente. ici, la version 3.1 est listée après la version 3.0
|
|
pour que l'image construite aie le tag :latest
|
|
|
|
Note: 'setdists' ne doit être utilisé qu'une seule fois. Les invocations
|
|
suivantes sont ignorées.
|
|
|
|
## Profils #####################################################################
|
|
|
|
Un profil correspond à l'environnement de destination de l'image: production,
|
|
test, développement.
|
|
|
|
La commande 'setprofiles' permet de lister explicitement les profils valides.
|
|
Si le profil sélectionné par l'utilisateur n'est pas dans la liste fournie, le
|
|
script s'arrête avec une erreur. Le premier profil listé est spécial: c'est le
|
|
profil par défaut.
|
|
|
|
La commande 'default_profile' permet de spécifier un profil par défaut à
|
|
utiliser, exactement comme s'il avait été spécifié avec l'option --profile.
|
|
Cette commande est particulièrement appropriée pour le fichier ~/.dkbuild.env
|
|
s'il s'agit de définir le profil à utiliser sur un hôte.
|
|
|
|
La commande 'profile' permet de tester si le profil spécifié en argument a été
|
|
sélectionné par l'utilisateur. L'argument 'DEFAULT' permet de tester le profil
|
|
par défaut.
|
|
|
|
Exemple:
|
|
setprofiles prod devel
|
|
if profile prod; then
|
|
...
|
|
elif profile devel; then
|
|
...
|
|
fi
|
|
|
|
Si le build est indépendant de la distribution, ou si la distribution est
|
|
utilisée sans version, alors il est possible de préfixer le profil d'une
|
|
version. Exemple:
|
|
setprofiles v1-prod v2-prod
|
|
if profile prod; then
|
|
if version v1; then
|
|
...
|
|
elif version v2; then
|
|
...
|
|
fi
|
|
fi
|
|
Dans un même profil, les versions doivent être ordonnées de la plus ancienne à
|
|
la plus récente.
|
|
|
|
Si les distributions sont utilisées avec des versions, alors c'est une erreur de
|
|
spécifier une version dans le profil
|
|
|
|
Note: 'setprofiles' et 'default_profile' ne peuvent être utilisés qu'une seule
|
|
fois. Les invocations suivantes sont ignorées.
|
|
|
|
## Versions ####################################################################
|
|
|
|
Si la version de l'image à construire n'est liée ni à la distribution, ni au
|
|
profil, il est possible de la spécifier avec la commande 'setversion'. La
|
|
version spécifiée avec 'setversion' est utilisée par défaut pour toutes les
|
|
images dont la version n'est pas spécifiée dans la distribution ou le profil.
|
|
|
|
La commande 'setversion' est évaluée en même temps que les commandes 'setenv',
|
|
ainsi il est possible d'utiliser la valeur d'une variable définie au préalable.
|
|
|
|
## Environnement ###############################################################
|
|
|
|
La commande 'machine' permet de tester si le build est fait sur la machine
|
|
spécifiée. Ce peut être la machine courante, ou la machine spécifiée avec
|
|
l'option --machine de la commande build
|
|
|
|
Exemple:
|
|
if machine host{1,2,3}-prod; then
|
|
setprofiles prod
|
|
elif machine host{1,2,3}-test; then
|
|
setprofiles test
|
|
else
|
|
setprofiles devel test prod
|
|
fi
|
|
|
|
Les variables sont de deux types: argument de build ou variable d'environnement
|
|
|
|
La commande 'setenv' permet de définir une variable d'environnement. La commande
|
|
'setarg' permet de définir un argument de build. Ces valeurs sont alors
|
|
automatiquement utilisées à l'endroit approprié.
|
|
|
|
Ces commandes acceptent une liste d'argument de la forme VAR[=VALUE]
|
|
|
|
Si la valeur n'est pas spécifiée (e.g 'setarg DESTDIR'), alors la variable doit
|
|
être définie dans l'environnement courant. Si la variable n'est pas définie dans
|
|
l'environnement, alors le script s'arrête avec une erreur.
|
|
|
|
Une fois qu'une variable est définie, il n'est plus possible de la modifier. Les
|
|
commandes alternatives 'resetenv' et 'resetarg' permettent de pallier cette
|
|
limitation.
|
|
|
|
## Valeurs par défaut ##########################################################
|
|
|
|
Toutes les commandes ont des arguments requis, mais aussi des arguments
|
|
facultatifs qui sont fournis sous la forme d'une liste d'éléments VAR=VALUE
|
|
|
|
La commande 'default' permet de spécifier les valeurs par défaut de ces
|
|
arguments. Exemple:
|
|
if profile prod; then
|
|
default composer mode=production
|
|
elif profile devel; then
|
|
default composer mode=development
|
|
fi
|
|
composer install path/to/project
|
|
|
|
Une fois qu'une valeur par défaut est définie, il n'est plus possible de la
|
|
modifier. La commande alternative 'resetdefault' permet de pallier cette
|
|
limitation.
|
|
|
|
Définir des valeurs par défaut pour la commande 'docker' impacte la commande
|
|
'build' et toutes les commandes qui utilisent docker, comme 'composer' ou 'mvn'
|
|
|
|
## Synchronisation de fichiers #################################################
|
|
|
|
On peut vouloir s'assurer de la présence de certains fichiers à certains
|
|
endroits.
|
|
|
|
La commande 'checkout URL DESTDIR' permet de s'assurer qu'un checkout du dépôt
|
|
spécifié existe dans le répertoire DESTDIR. La branche ou le commit à utiliser,
|
|
la source en mode développement, etc. peuvent être spécifiés par des arguments
|
|
facultatifs.
|
|
|
|
La commande 'copy SRC DEST' permet de s'assurer que SRC et DEST sont
|
|
synchronisés. Si possible, des liens physiques sont créés pour conserver
|
|
l'espace disque. Par défaut, les fichiers ne sont créés que s'ils n'existent
|
|
pas.
|
|
|
|
## Support Composer, Maven, commandes génériques ###############################
|
|
|
|
La commande 'composer install' permet d'installer les dépendances Composer d'un
|
|
projet
|
|
|
|
La commande 'mvn package' permet de construire un projet Java.
|
|
|
|
La commande 'run' permet de lancer une commande quelconque. La commande est
|
|
cherchée dans le PATH et exécutée avec son chemin complet. celà permet de lancer
|
|
des commandes comme 'mvn' ou 'composer' ou dont le nom correspond à une fonction
|
|
déjà définie.
|
|
|
|
La commande 'call' permet de lancer une commande quelconque. La différence avec
|
|
'run' est que la commande est lancée telle quelle, sans modifications. Si une
|
|
fonction est définie, elle sera utilisée en priorité.
|
|
|
|
Les commandes 'runb' et 'callb' sont comme 'run' et 'call' respectivement, mais
|
|
elles ne sont exécutées que si build est activé.
|
|
|
|
Si elles sont utilisées sans argument, les commandes 'composer', 'mvn', 'run' et
|
|
'call' retournent vrai si la commande doit être exécutée dans le contexte
|
|
courant. Celà permet d'implémenter des traitements complexes. Ainsi le script
|
|
suivant:
|
|
run cmd1
|
|
run cmd2
|
|
est équivalent à:
|
|
if run; then
|
|
cmd1
|
|
cmd2
|
|
fi
|
|
|
|
En phase d'analyse, ces commandes retournent faux, donc cmd1 et cmd2 ne seront
|
|
lancés qu'une seule fois lors de l'invocation de dkbuild. Cela signifie qu'il ne
|
|
faut pas utiliser des directives de définition de variables à l'intérieur. Par
|
|
exemple, le script suivant ne produit pas forcément l'effet escompté:
|
|
if run; then
|
|
setenv var=value
|
|
default
|
|
cmd args...
|
|
fi
|
|
|
|
Bien entendu, si on veut être sûr que des commandes externes soient lancées, on
|
|
peut toujours utiliser 'run' à l'intérieur, e.g
|
|
if composer; then
|
|
run extcmd
|
|
func
|
|
composer args...
|
|
fi
|
|
|
|
## Support Dockerfile et docker build ##########################################
|
|
|
|
La commande 'dockerfile OUTPUT' permet de construire de façon incrémentale et
|
|
dynamique un fichier Dockerfile. Toutes les commandes d'un fichier dockerfile
|
|
traditionnelles sont reconnues et elles doivent être spécifiées après la
|
|
commande 'dockerfile'.
|
|
|
|
La commande 'build' termine la construction du fichier Docker puis lance la
|
|
construction de l'image.
|
|
* arguments de build: les arguments de build définis dans le script sont passés
|
|
à docker pour la construction de l'image
|
|
* nom de l'image et tag: par défaut, la variable d'environnement IMAGE est
|
|
combinée le cas échéant avec DIST et VERSION pour déterminer les tags que
|
|
reçoit l'image construite.
|
|
|
|
La commande 'cbuild' lance le build de toutes les images mentionnées dans les
|
|
fichiers 'docker-compose.yml' et 'docker-compose.PROFILE.yml' le cas échéant
|
|
* variables d'environnement: les arguments de build définis sont inscrits dans
|
|
un fichier .env qui est utilisé ensuite par docker compose
|
|
|
|
Si aucune commande 'build' ou 'cbuild' ne figure dans le fichier, 'build' est
|
|
lancé automatiquement à la fin
|
|
|
|
## Autres commandes ############################################################
|
|
|
|
Il est possible d'organiser le script dans plusieurs fichiers qui sont inclus
|
|
avec la commande 'include'. Fonctionnellement, cela se passe comme si le contenu
|
|
du fichier inclus était inséré dans le script principal, à ceci près que le
|
|
répertoire courant devient temporairement celui du fichier inclus.
|
|
|
|
Exemple:
|
|
setdists d11 d10 d9
|
|
if dist d9; then
|
|
include d9/dkbuild
|
|
elif dist d10; then
|
|
include d10/dkbuild
|
|
elif dist d11; then
|
|
include d11/dkbuild
|
|
fi
|
|
|
|
La commande 'dkbuild' lance le build d'un répertoire destination. La différence
|
|
avec 'include' est que cela est fait dans un processus complètement différent,
|
|
comme si le build avait été lancé depuis la ligne de commande.
|
|
|
|
Les commandes 'section', 'note', 'info', 'debug' permettent d'afficher des
|
|
messages de différents niveaux
|
|
|
|
## Variables globales ##########################################################
|
|
|
|
PROJDIR est le chemin absolu du projet, dans lequel se trouve le fichier dkbuild
|
|
initial
|
|
|
|
La distribution actuellement sélectionnée se trouve dans la variable DIST. La
|
|
version actuellement sélectionnée se trouve dans la variable VERSION. Si la
|
|
commande 'setdists' n'est pas utilisée, alors ni DIST ni VERSION ne sont définis
|
|
|
|
Le profil actuellement sélectionné se trouve dans la variable PROFILE. La
|
|
version actuellement sélectionnée se trouve dans la variable VERSION (si les
|
|
distributions sont utilisées sans le support de la version). Si la commande
|
|
'setprofiles' n'est pas utilisée, alors ni PROFILE ni VERSION ne sont définis
|
|
|
|
IMAGE est le nom de l'image à construire. Si le nom de l'image contient le tag
|
|
(e.g IMAGE:TAG) alors le nom est utilisé tel quel. Sinon, DIST et VERSION sont
|
|
utilisés comme tags (i.e IMAGE:DIST et IMAGE:VERSION-DIST)"
|
|
}
|
|
|
|
function display_help_reference() {
|
|
uecho "\
|
|
OPTIONS
|
|
--help Aide générale
|
|
--hdk Aide sur le format du fichier dkbuild
|
|
* --href Référence sur les commandes utilisables dans un fichier dkbuild
|
|
|
|
REFERENCE
|
|
=========
|
|
|
|
## fonctions d'affichage
|
|
|
|
USAGE:
|
|
section TITLE
|
|
note MESSAGE
|
|
info MESSAGE
|
|
debug MESSAGE
|
|
|
|
## machine -- vérifier la machine courante
|
|
|
|
## setdists -- spécifier les distributions valides
|
|
|
|
## dist -- vérifier la distribution courante
|
|
|
|
## setprofiles -- spécifier les profils valides
|
|
|
|
## default_profile -- spécifier le profil à utiliser si aucun profil n'est sélectionné
|
|
|
|
## profile -- vérifier le profil courant
|
|
|
|
## setversion -- spécifier la version par défaut
|
|
|
|
USAGE: setversion VERSION
|
|
|
|
Les paramètres optionnels sont
|
|
* from-file=FILE
|
|
prendre la version depuis le fichier spécifié. les formats pom.xml et
|
|
VERSION.txt sont supportés
|
|
* from-repo=REPO
|
|
calculer la version depuis le dépôt git spécifié
|
|
* from-glob=GLOB
|
|
calculer la version depuis le chemin spécifié
|
|
* extract=REGEXP
|
|
à partir de la valeur calculée par l'un des paramètres from-*, matcher
|
|
l'expression régulière au format AWK, et prendre comme version la valeur de
|
|
l'expression \$1
|
|
Si from-glob est spécifié, la valeur par défaut de extract est calculée en
|
|
remplaçant '*' par '(.*)'
|
|
* add-prefix=PREFIX
|
|
Ajouter le préfixe spécifié à la version extraite
|
|
* add-suffix=SUFFIX
|
|
Ajouter le suffixe spécifié à la version extraite
|
|
|
|
## version -- vérifier la version courante
|
|
|
|
## setenv -- spécifier une variable d'environnement
|
|
|
|
## resetenv -- spécifier une variable d'environnement
|
|
|
|
## setarg -- spécifier une variable de build
|
|
|
|
## resetarg -- spécifier une variable de build
|
|
|
|
## default -- spécifier des arguments par défaut
|
|
|
|
## resetdefault -- spécifier des arguments par défaut
|
|
|
|
## checkout -- faire et vérifier checkout d'un dépôt git
|
|
|
|
USAGE: checkout URL [DESTDIR] [PARAMS]
|
|
|
|
Les paramètres optionnels sont
|
|
* checkout
|
|
mettre à jour dépôt. c'est la valeur par défaut. utiliser checkout= pour
|
|
désactiver la mise à jour du dépôt. utiliser checkout=devel pour synchroniser
|
|
depuis le répertoire de développement.
|
|
* origin=ORIGIN
|
|
spécifier l'origine. Par défaut, prendre 'origin'
|
|
* branch=BRANCH
|
|
spécifier la branche à utiliser dans l'origine spécifiée. La valeur par défaut
|
|
est 'master' si les profils ne sont pas utilisé. Si les profils sont utilisés,
|
|
la valeur par défaut est 'develop' pour les profils 'test' et 'devel', sinon
|
|
c'est 'master'.
|
|
Utiliser la syntaxe ^COMMIT pour ignorer l'origine et sélectionner un commit
|
|
en particulier.
|
|
* develdir=DIR
|
|
spécifier l'emplacement du répertoire de développement, utilisé avec
|
|
checkout=devel
|
|
* develtype=TYPE
|
|
spécifier le type de projet pour la synchronisation depuis le répertoire de
|
|
développement. certains projets, notamment les projets composer avec des
|
|
dépendances de type 'path', nécessitent une méthode de synchronisation
|
|
particulière. Si ce paramètre n'est pas spécifié, il est auto-détecté. Les
|
|
valeurs supportées sont:
|
|
* composer -- détecté de par la présence d'un fichier composer.json
|
|
* maven -- détecté de par la présence d'un fichier pom.xml
|
|
* none -- valeur par défaut: pas de type particulier
|
|
|
|
## copy -- synchroniser des fichiers
|
|
|
|
USAGE: copy SRC DEST [PARAMS]
|
|
|
|
Si SRC est un fichier, alors DEST doit être un chemin vers le fichier
|
|
destination. Si SRC est un répertoire, alors DEST doit être un chemin vers le
|
|
répertoire destination. On peut forcer à considérer SRC et/ou DEST comme un
|
|
répertoire en les suffixant de '/'
|
|
|
|
Par exemple:
|
|
* copy SRCDIR/ DESTDIR/
|
|
échoue si SRCDIR et/ou DESTDIR sont des fichiers
|
|
* les commandes suivantes sont équivalentes:
|
|
copy SRC DESTDIR/
|
|
copy SRC DESTDIR/SRCNAME
|
|
|
|
Les paramètres optionnels sont
|
|
* copy
|
|
synchroniser les fichiers. c'est la valeur par défaut. utiliser copy= pour
|
|
désactiver la synchronisation des fichiers.
|
|
* overwrite
|
|
autoriser l'écrasement des fichiers destination, ce qui permet de rendre la
|
|
destination identique à la source. par défaut, un fichier destination est
|
|
laissé en place, ce qui permet d'avoir le cas échéant des fichiers locaux
|
|
différents de la source.
|
|
* gitignore=BASEDIR
|
|
maintenir le fichier .gitignore de BASEDIR, qui doit être un répertoire parent
|
|
de DESTDIR. Les fichiers synchronisés sont rajouté le cas échéant dans
|
|
.gitignore, sauf si le répertoire qui les contient est déjà exclu.
|
|
NB: Un fichier n'est considéré pour l'ajout dans .gitignore que s'il a été
|
|
copié au préalable. Ainsi, un fichier déjà existant dans la destination ne
|
|
sera pas ajouté dans le fichier .gitignore si overwrite=
|
|
|
|
## genfile -- créer un fichier générique
|
|
|
|
USAGE: genfile OUTPUT [INPUT] [PARAMS]
|
|
|
|
Si le fichier INPUT est spécifié, il est utilisé pour créer le contenu initial
|
|
du fichier. Sinon, l'entrée standard *doit* être redirigée depuis un fichier, et
|
|
elle est lue pour générer le contenu initial du fichier à générer.
|
|
|
|
Les paramètres optionnels sont
|
|
* context=DIR
|
|
générer le fichier dans le répertoire spécifié
|
|
* sed=SCRIPT
|
|
script sed à appliquer au fichier
|
|
|
|
## dockerfile -- créer un fichier Dockerfile
|
|
|
|
USAGE: dockerfile [OUTPUT [INPUT]] [PARAMS]
|
|
|
|
Si le fichier INPUT est spécifié, il est utilisé pour créer le contenu initial
|
|
du fichier. Sinon, *si* l'entrée standard est redirigée depuis un fichier, elle
|
|
est lue pour générer le contenu initial du fichier.
|
|
|
|
Les paramètres optionnels sont
|
|
* context=DIR
|
|
générer le fichier dans le répertoire spécifié
|
|
* sed=SCRIPT
|
|
script sed à appliquer au fichier initial, construit à partir de l'entrée
|
|
standard. Le fichier n'est plus modifié par la suite.
|
|
|
|
## build -- construire une image avec docker
|
|
|
|
USAGE: build [PARAMS]
|
|
|
|
Les paramètres optionnels sont
|
|
* build
|
|
construire les images, c'est la valeur par défaut. utiliser build= pour
|
|
désactiver la construction.
|
|
* context=DIR
|
|
répertoire de contexte. cette valeur est en principe générée automatiquement
|
|
par la commande 'dockerfile'
|
|
* dockerfile=FILE
|
|
fichier de build à utiliser. cette valeur est en principe générée automatiquement
|
|
par la commande 'dockerfile'
|
|
* no-cache
|
|
ne pas utiliser le cache
|
|
* pull
|
|
forcer la mise à jour des images dépendantes
|
|
* host-mappings=MAPPINGS
|
|
définir des mappings d'hôte. si ce paramètre n'est pas spécifié, consulter
|
|
aussi la valeur par défaut 'docker host-mappings='
|
|
* set-tag=TAGS... ou set-tags=TAGS...
|
|
spécifier des tags à rajouter au nom de l'image, séparés par un espace. cette
|
|
liste remplace celle calculée automatiquement. ce paramètre est ignoré pour
|
|
les noms d'images comportant un tag
|
|
* add-tag=TAGS... ou add-tags=TAGS...
|
|
spécifier des tags à rajouter à la liste calculée automatiquement, séparés par
|
|
un espace. ce paramètre est ignoré pour les noms d'images comportant un tag
|
|
* image=IMAGES... ou images=IMAGES...
|
|
liste de nom d'images, séparés par un espace. si les noms n'ont pas de tag, le
|
|
tag est construit à partir de DIST et VERSION sous la forme [VERSION-]DIST
|
|
* push
|
|
pousser les images vers le registry après les avoir construites
|
|
|
|
## cbuild -- construire une image avec docker compose
|
|
|
|
USAGE: cbuild [SERVICE] [PARAMS]
|
|
|
|
Les paramètres optionnels sont
|
|
* files=FILES...
|
|
spécifier les fichiers docker-compose à utiliser. Par défaut, prendre
|
|
docker-compose.yml et docker-compose.PROFILE.yml
|
|
* project-name=PROJECT_NAME
|
|
spécifier le nom du projet
|
|
* no-cache
|
|
ne pas utiliser le cache
|
|
* pull
|
|
forcer la mise à jour des images dépendantes
|
|
|
|
## include -- inclure un autre fichier dkbuild
|
|
|
|
## dkbuild -- lancer un builder externe
|
|
|
|
La commande dkbuild qui traite le script de build courant est lancée telle
|
|
quelle, avec la même syntaxe qu'en ligne de commande. L'intérêt de cette
|
|
commande est qu'on est assuré d'utiliser le même dkbuild que celui qui traite le
|
|
script de build courant.
|
|
|
|
## composer -- gérer projet composer
|
|
|
|
USAGE: composer DESTDIR [ACTION [PARAMS] [ARGS]]
|
|
|
|
La destination est obligatoire. Sans arguments, cette commande retourne
|
|
simplement vrai
|
|
|
|
Les actions valides sont
|
|
* install -- installer les dépendances. c'est l'action par défaut
|
|
* update -- mettre à jour les dépendances
|
|
* rshell -- lancer un shell root dans le répertoire du projet
|
|
* shell -- lancer un shell utilisateur dans le répertoire du projet
|
|
* none -- ne rien faire
|
|
|
|
L'action est exécutée sur DESTDIR. Juste avant de lancer l'action, le répertoire
|
|
courant est modifié pour être DESTDIR, ce qui permet d'utiliser des chemins
|
|
relatifs le cas échéant.
|
|
|
|
La commande 'rshell' lance un shell bash avec l'utilisateur root au lieu de
|
|
lancer la commande composer, ce qui permet de faire des opérations plus
|
|
complexes si le besoin s'en fait sentir. La commande alternative 'shell' lance
|
|
le shell avec le compte utilisateur. Ces commandes sont particulièrement utiles
|
|
si composer est paramétré pour être lancé dans un container
|
|
|
|
Les paramètres optionnels sont
|
|
* args=ARGS...
|
|
arguments à rajouter à la commande composer. La valeur par défaut dépend du
|
|
profil:
|
|
* prod: --no-dev -o
|
|
* test: --no-dev -o
|
|
* autres profils: (pas d'arguments)
|
|
* php=VERSION
|
|
version de PHP en dessous de laquelle 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.
|
|
* Spécifier 'none' ou 'system' pour lancer directement composer sans passer
|
|
par une image docker.
|
|
Si php n'est pas disponible dans le PATH, ce paramètre prend par défaut la
|
|
valeur 'force'
|
|
* php-max=VERSION
|
|
version de PHP à partir de laquelle image= est utilisé. 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.
|
|
* image=COMPOSER_IMAGE
|
|
image docker utilisée pour lancer composer. La valeur par défaut est la valeur
|
|
de la variable d'environnement \$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.
|
|
* machine=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. Spécifier 'current' pour ne pas modifier la valeur courante le cas
|
|
échéant
|
|
* host-mappings=MAPPINGS
|
|
définir des mappings d'hôte. si ce paramètre n'est pas spécifié, consulter
|
|
aussi la valeur par défaut 'docker host-mappings='
|
|
* composer=PATH/TO/COMPOSER
|
|
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
|
|
* setup=CMDS...
|
|
liste de commandes à lancer pour configurer le container. 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é par exemple pour installer certains packages
|
|
nécessaire au projet.
|
|
* setup-image=SETUP_IMAGE
|
|
forcer le nom de l'image pour setup= (la valeur de project-name= est ignorée)
|
|
* project-name=PROJECT_NAME
|
|
si setup= est défini, nommer l'image sur la base de ce nom. par défaut, le nom
|
|
est calculé automatiquement
|
|
|
|
Si un fichier .composer.yaml existe dans le répertoire du projet, il est analysé
|
|
pour obtenir les valeurs par défaut des paramètres suivants:
|
|
* composer_php_min: valeur par défaut de php=
|
|
* composer_php_max: valeur par défaut de php-max=
|
|
* composer_registry: ET composer_image: valeur par défaut de image=
|
|
* composer_setup: valeur par défaut de setup=
|
|
* composer_setup_image: valeur par défaut de setup-image=
|
|
|
|
Sinon, si un fichier .composer.conf existe dans le répertoire du projet, il est
|
|
sourcé pour obtenir les valeurs par défaut des paramètres:
|
|
* COMPOSER_PHP -- valeur par défaut de php=
|
|
* COMPOSER_PHP_MAX -- valeur par défaut de php-max=
|
|
* COMPOSER_IMAGE -- valeur par défaut de image=
|
|
* COMPOSER_MACHINE -- valeur par défaut de machine=
|
|
* COMPOSER_CMD -- valeur par défaut de composer=
|
|
* COMPOSER_SETUP -- valeur par défaut de setup=
|
|
* COMPOSER_SETUP_IMAGE -- valeur par défaut de setup-image=
|
|
|
|
## mvn -- construire projet maven
|
|
|
|
USAGE: mvn DESTDIR [ACTION [PARAMS] [ARGS]]
|
|
|
|
Le répertoire de destination est obligatoire. Sans arguments, cette commande
|
|
retourne simplement vrai. L'action par défaut est 'package'
|
|
|
|
Les actions valides sont
|
|
* install -- lance mvn avec les commandes 'clean package install'
|
|
* package -- lance mvn avec les commandes 'clean package'
|
|
* package_only -- lance mvn avec uniquement la commande 'package'
|
|
* rshell -- lancer un shell root dans le répertoire du projet
|
|
* shell -- lancer un shell utilisateur dans le répertoire du projet
|
|
* java -- lancer java au lieu de lancer mvn. il est possible de spécifier la
|
|
version de java directement, e.g java7, java8, java11
|
|
|
|
L'action est exécutée sur DESTDIR. Juste avant de lancer l'action, le répertoire
|
|
courant est modifié pour être DESTDIR, ce qui permet d'utiliser des chemins
|
|
relatifs le cas échéant.
|
|
|
|
La commande 'rshell' lance un shell bash avec l'utilisateur root au lieu de
|
|
lancer la commande mvn, ce qui permet de faire des opérations plus complexes si
|
|
le besoin s'en fait sentir. La commande alternative 'shell' lance le shell avec
|
|
le compte utilisateur. Ces commandes sont particulièrement utiles si mvn est
|
|
paramétré pour être lancé dans un container
|
|
|
|
Les paramètres optionnels sont
|
|
* args=ARGS...
|
|
arguments à rajouter à la commande mvn
|
|
* java=VERSION
|
|
version de Java à sélectionner à l'intérieur de l'image docker
|
|
* Spécifier 'any' ou 'force' pour prendre la valeur par défaut
|
|
* Spécifier 'none' ou 'system' pour ne pas utiliser l'image docker
|
|
Si java ou mvn ne sont pas disponibles dans le PATH, ce paramètre prend par
|
|
défaut la valeur 'force'
|
|
* image=MAVEN_IMAGE
|
|
image docker utilisée pour lancer mvn. La valeur par défaut est la valeur
|
|
de la variable d'environnement \$MAVEN_IMAGE
|
|
Spécifier 'none' pour lancer directement mvn sans passer par une image
|
|
docker, même si java= est renseigné
|
|
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.
|
|
* machine=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. Spécifier 'current' pour ne pas modifier la valeur courante le cas
|
|
échéant
|
|
* host-mappings=MAPPINGS
|
|
définir des mappings d'hôte. si ce paramètre n'est pas spécifié, consulter
|
|
aussi la valeur par défaut 'docker host-mappings='
|
|
* mvn=PATH/TO/MVN
|
|
chemin vers l'exécutable mvn. Par défaut, utiliser la commande trouvée dans le
|
|
PATH
|
|
* setup=CMDS...
|
|
liste de commandes à lancer pour configurer le container. Un container ayant
|
|
pour base MAVEN_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é par exemple pour installer certains packages
|
|
nécessaire au projet.
|
|
* setup-image=SETUP_IMAGE
|
|
forcer le nom de l'image pour setup= (la valeur de project-name= est ignorée)
|
|
* project-name=PROJECT_NAME
|
|
si setup= est défini, nommer l'image sur la base de ce nom. par défaut, le nom
|
|
est calculé automatiquement
|
|
|
|
Si un fichier .maven.conf existe dans le répertoire du projet, il est sourcé
|
|
pour obtenir les valeurs par défaut des paramètres:
|
|
* MAVEN_JAVA -- valeur par défaut de java=
|
|
* MAVEN_IMAGE -- valeur par défaut de image=
|
|
* MAVEN_MACHINE -- valeur par défaut de machine=
|
|
* MAVEN_CMD -- valeur par défaut de mvn=
|
|
* MAVEN_SETUP -- valeur par défaut de setup=
|
|
* MAVEN_SETUP_IMAGE -- valeur par défaut de setup-image=
|
|
|
|
## run -- lancer des commandes
|
|
|
|
## runb -- lancer des commandes
|
|
|
|
## call -- lancer des commandes ou des fonctions
|
|
|
|
## callb -- lancer des commandes ou des fonctions
|
|
"
|
|
}
|
|
|
|
##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
## shared
|
|
|
|
declare -A PROTECTED_VARS=(
|
|
[PROTECTED_VARS]=1
|
|
[SELF]=1
|
|
[SHARED_LOCALS1]=1
|
|
[SHARED_ARGS1]=1
|
|
[SHARED_LOCALS2]=1
|
|
[SHARED_ARGS2]=1
|
|
[TFUNCTIONS]=1
|
|
[FFUNCTIONS]=1
|
|
[PROJDIR]=1
|
|
[DKBUILD]=1
|
|
[CONFIG]=1
|
|
[MACHINE]=1
|
|
[SETDISTS_DONE]=1
|
|
[SETDISTS]=1
|
|
[SETPROFILES_DONE]=1
|
|
[SETPROFILES]=1
|
|
[DEFAULT_PROFILE]=1
|
|
[SETVERSION_DONE]=1
|
|
[SETVERSION]=1
|
|
[AUTOBUILD]=1
|
|
[DISTS]=1
|
|
[PROFILES]=1
|
|
[_ENVIRON]=1
|
|
[ENVIRON]=1
|
|
[ARGS]=1
|
|
[DEFAULTS]=1
|
|
)
|
|
|
|
SHARED_LOCALS1="local PROJDIR DKBUILD CONFIG"
|
|
SHARED_ARGS1=(
|
|
-j:,--projdir: PROJDIR=
|
|
-c:,--config: CONFIG=
|
|
)
|
|
|
|
SHARED_LOCALS2="local DIST PROFILE ALL_PROFILES; local -a TMPENVIRON TMPARGS"
|
|
SHARED_ARGS2=(
|
|
-d:,--dist: DIST=
|
|
-0,--d10 DIST=d10
|
|
-1,--d11 DIST=d11
|
|
-2,--d12 DIST=d11
|
|
-3,--d13 DIST=d11
|
|
--r7,--rhel7 DIST=rhel7
|
|
--r8,--rhel8 DIST=rhel8
|
|
--r9,--rhel9 DIST=rhel9
|
|
--ol7,--oracle7 DIST=ol7
|
|
--ol8,--oracle8 DIST=ol8
|
|
--ol9,--oracle9 DIST=ol9
|
|
|
|
-p:,--profile: PROFILE=
|
|
-P,--prod PROFILE=prod
|
|
-T,--test PROFILE=test
|
|
-E,--dtest PROFILE=dtest
|
|
-J,--jclain PROFILE=jclain
|
|
--devel PROFILE=devel
|
|
--all-profiles ALL_PROFILES=1
|
|
|
|
-e:,--env: '$TMPENVIRON+=("$value_")'
|
|
--arg: '$TMPARGS+=("$value_")'
|
|
)
|
|
|
|
TFUNCTIONS=(
|
|
# dkbuild
|
|
section note info debug
|
|
setdists dist
|
|
setprofiles profile
|
|
default_profile
|
|
setversion version
|
|
setenv resetenv
|
|
setarg resetarg
|
|
default resetdefault
|
|
checkout
|
|
copy
|
|
genfile
|
|
dockerfile
|
|
build
|
|
cbuild
|
|
# dockerfile
|
|
FROM
|
|
RUN
|
|
CMD
|
|
LABEL
|
|
MAINTAINER
|
|
EXPOSE
|
|
ENV
|
|
ADD
|
|
COPY
|
|
ENTRYPOINT
|
|
VOLUME
|
|
USER
|
|
WORKDIR
|
|
ARG
|
|
ONBUILD
|
|
STOPSIGNAL
|
|
HEALTHCHECK
|
|
SHELL
|
|
)
|
|
FFUNCTIONS=(
|
|
# dkbuild
|
|
composer
|
|
mvn
|
|
run
|
|
runb
|
|
call
|
|
callb
|
|
dkbuild
|
|
)
|
|
|
|
function set_machine() {
|
|
local machine="$1"
|
|
if [ "$machine" == -u ]; then
|
|
# déselectionner la machine courante
|
|
local -x DOCKER_TLS_VERIFY= DOCKER_HOST= DOCKER_CERT_PATH= DOCKER_MACHINE_NAME=
|
|
machine=
|
|
fi
|
|
if [ -n "$machine" ]; then
|
|
if [ -f ~/etc/default/dk ]; then
|
|
machine="$(
|
|
CLUSTERDIRS=()
|
|
DM_ALIASES=()
|
|
source ~/etc/default/dk
|
|
for alias_machine in "${DM_ALIASES[@]}"; do
|
|
if [ "${alias_machine%%:*}" == "$machine" ]; then
|
|
echo "${alias_machine#*:}"
|
|
exit
|
|
fi
|
|
done
|
|
for clusterdir in "${CLUSTERDIRS[@]}"; do
|
|
if [ -f "$clusterdir/0config/configure.conf" ]; then
|
|
DM_ALIASES=()
|
|
source "$clusterdir/0config/configure.conf"
|
|
for alias_machine in "${DM_ALIASES[@]}"; do
|
|
if [ "${alias_machine%%:*}" == "$machine" ]; then
|
|
echo "${alias_machine#*:}"
|
|
exit
|
|
fi
|
|
done
|
|
fi
|
|
done
|
|
echo "$machine"
|
|
)"
|
|
fi
|
|
eval "$(docker-machine env "$machine" || echo false)" || die
|
|
else
|
|
machine="$DOCKER_MACHINE_NAME"
|
|
[ -n "$machine" ] || machine="${HOSTNAME%%.*}"
|
|
fi
|
|
MACHINE="$machine"
|
|
}
|
|
|
|
function get_project_name() {
|
|
local project_name
|
|
setx project_name=basename -- "$(pwd)"
|
|
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
|
|
echo "$project_name"
|
|
}
|
|
|
|
function get_container_name() {
|
|
local container_name="${1//[^a-zA-Z0-9_-]/}"
|
|
[ -n "$PROFILE" ] && container_name="${container_name}_$PROFILE"
|
|
echo "$container_name"
|
|
}
|
|
|
|
function reset_functions() {
|
|
local func
|
|
for func in "${TFUNCTIONS[@]}"; do
|
|
eval "function $func() { : echo \"$func \$*\"; return 0; }"
|
|
done
|
|
for func in "${FFUNCTIONS[@]}"; do
|
|
eval "function $func() { : echo \"$func \$*\"; return 1; }"
|
|
done
|
|
function include() {
|
|
edebug "include $(qvals "$@")"
|
|
|
|
local file="$1"
|
|
[ -d "$file" ] && file="$file/dkbuild"
|
|
[ -f "$file" ] || die "$file: fichier introuvable"
|
|
setx file=abspath "$file"
|
|
cd "$(dirname "$file")"
|
|
source "$file"
|
|
}
|
|
function machine() {
|
|
local machine version
|
|
for machine in "$@"; do
|
|
[ "$machine" == "$MACHINE" ] && return
|
|
done
|
|
return 1
|
|
}
|
|
}
|
|
|
|
function _runcmd() {
|
|
edebug "\$ $(qvals "$@")"
|
|
"$@"
|
|
}
|
|
|
|
function ensure_projdir() {
|
|
if [ -z "$PROJDIR" ]; then
|
|
local found=
|
|
if [ ! -f dkbuild ]; then
|
|
# NB: on teste $PROJDIR != $scriptdir parce qu'il ne faut pas qu'on
|
|
# prenne le présent script comme un script de build...
|
|
PROJDIR="$(pwd)"
|
|
if [ "${PROJDIR#$HOME/}" != "$PROJDIR" ]; then
|
|
while [ "$PROJDIR" != "$HOME" ]; do
|
|
if [ -f "$PROJDIR/dkbuild" -a "$PROJDIR" != "$scriptdir" ]; then
|
|
found=1
|
|
break
|
|
fi
|
|
setx PROJDIR=dirname "$PROJDIR"
|
|
done
|
|
else
|
|
while [ "$PROJDIR" != / ]; do
|
|
if [ -f "$PROJDIR/dkbuild" -a "$PROJDIR" != "$scriptdir" ]; then
|
|
found=1
|
|
break
|
|
fi
|
|
setx PROJDIR=dirname "$PROJDIR"
|
|
done
|
|
fi
|
|
fi
|
|
if [ -n "$found" ]; then
|
|
enote "Sélection du répertoire de projet $(relpath "$PROJDIR")"
|
|
else
|
|
PROJDIR=.
|
|
fi
|
|
fi
|
|
|
|
if [ -f "$PROJDIR" ]; then
|
|
DKBUILD="$PROJDIR"
|
|
setx PROJDIR=dirname "$PROJDIR"
|
|
else
|
|
DKBUILD="$PROJDIR/dkbuild"
|
|
fi
|
|
[ -d "$PROJDIR" ] || die "$PROJDIR: répertoire de projet introuvable"
|
|
|
|
setx PROJDIR=abspath "$PROJDIR"
|
|
setx DKBUILD=abspath "$DKBUILD"
|
|
cd "$PROJDIR" || die
|
|
[ -f "$DKBUILD" ] || die "$(ppath "$DKBUILD"): fichier de build introuvable"
|
|
|
|
if [ "$CONFIG" == none ]; then
|
|
edebug "no default config used"
|
|
elif [ -n "$CONFIG" ]; then
|
|
setx CONFIG=abspath "$CONFIG"
|
|
edebug "using config $CONFIG"
|
|
else
|
|
local config
|
|
for config in ~/.dkbuild.env /etc/dkbuild.env; do
|
|
if [ -f "$config" ]; then
|
|
CONFIG="$config"
|
|
edebug "using default config $CONFIG"
|
|
break
|
|
fi
|
|
done
|
|
fi
|
|
}
|
|
|
|
function load_dkbuild() {
|
|
local dkbuildenv="$PROJDIR/$(basename "$DKBUILD").env"
|
|
cd "$PROJDIR"
|
|
if [ -n "$CONFIG" ]; then
|
|
edebug "loading $CONFIG"
|
|
source "$CONFIG"
|
|
fi
|
|
if [ -f "$dkbuildenv" ]; then
|
|
edebug "loading $dkbuildenv"
|
|
source "$dkbuildenv"
|
|
fi
|
|
edebug "loading $DKBUILD"
|
|
source "$DKBUILD"
|
|
}
|
|
|
|
function load_environ() {
|
|
declare -g -A _ENVIRON
|
|
eval "$(declare -p -x | sed -r 's/^declare -x ([^=]+)=/_ENVIRON[\1]=/')"
|
|
}
|
|
|
|
function from_glob() {
|
|
local var=value value
|
|
[[ "$1" != *=* ]] && { var="$1"; shift; }
|
|
|
|
local path extract add_prefix add_suffix
|
|
while [ $# -gt 0 ]; do
|
|
case "$1" in
|
|
path=*) path="${1#path=}";;
|
|
extract=*) extract="${1#extract=}";;
|
|
add-prefix=*) add_prefix="${1#add-prefix=}";;
|
|
add-suffix=*) add_suffix="${1#add-suffix=}";;
|
|
*=*) ewarn "path: $1: argument ignoré";;
|
|
*) break;;
|
|
esac
|
|
shift
|
|
done
|
|
value="$(list_all . "$path" | sort -rn | head -1)"
|
|
[ -n "$extract" ] || extract="${path//\*/(.*)}"
|
|
if [ -n "$extract" ]; then
|
|
extract="${extract//\//\\/}"
|
|
value="$add_prefix$(awk -v version="$value" "BEGIN {
|
|
if (match(version, /$extract/, vs)) { print vs[1] }
|
|
else { print version }
|
|
}")$add_suffix"
|
|
fi
|
|
|
|
local "$var"; upvar "$var" "$value"
|
|
}
|
|
function define_functions_env() {
|
|
function setversion() {
|
|
[ -n "$SETVERSION_DONE" ] && return
|
|
# sans argument, retourner 0
|
|
[ $# -eq 0 ] && return
|
|
|
|
local from_file from_repo from_glob extract add_prefix add_suffix
|
|
while [ $# -gt 0 ]; do
|
|
case "$1" in
|
|
from-file|file) from_file=.;;
|
|
from-file=*|file=*)
|
|
from_file="${1#from-}"; from_file="${from_file#file=}"
|
|
;;
|
|
from-repo|repo) from_repo=.;;
|
|
from-repo=*|repo=*)
|
|
from_repo="${1#from-}"; from_repo="${from_repo#repo=}"
|
|
;;
|
|
from-glob=*|glob=*)
|
|
from_glob="${1#from-}"; from_glob="${from_glob#glob=}"
|
|
;;
|
|
extract=*) extract="${1#extract=}";;
|
|
add-prefix=*) add_prefix="${1#add-prefix=}";;
|
|
add-suffix=*) add_suffix="${1#add-suffix=}";;
|
|
*=*) ewarn "setversion: $1: argument ignoré";;
|
|
*) break;;
|
|
esac
|
|
shift
|
|
done
|
|
if [ -n "$from_file" ]; then
|
|
if [ -d "$from_file" ]; then
|
|
setx SETVERSION=pver --sw "$from_file" || die
|
|
elif [[ "$from_file" == *.xml ]]; then
|
|
setx SETVERSION=pver -E "$from_file" || die
|
|
else
|
|
setx SETVERSION=pver -F "$from_file" || die
|
|
fi
|
|
elif [ -n "$from_repo" ]; then
|
|
die "setversion from-repo: pas encore implémenté" #XXX
|
|
elif [ -n "$from_glob" ]; then
|
|
SETVERSION="$(list_all . "$from_glob" | sort -rn | head -1)"
|
|
[ -n "$extract" ] || extract="${from_glob//\*/(.*)}"
|
|
else
|
|
SETVERSION="$1"
|
|
fi
|
|
if [ -n "$extract" ]; then
|
|
extract="${extract//\//\\/}"
|
|
SETVERSION="$add_prefix$(awk -v version="$SETVERSION" "BEGIN {
|
|
if (match(version, /$extract/, vs)) { print vs[1] }
|
|
else { print version }
|
|
}")$add_suffix"
|
|
fi
|
|
SETVERSION_DONE=1
|
|
}
|
|
function dist() {
|
|
local dist version latest
|
|
for dist in "$@"; do
|
|
if [ "$dist" == LATEST ]; then
|
|
latest=1
|
|
continue
|
|
fi
|
|
parse_dist "$dist" dist version
|
|
[ "$dist" == "$DIST" ] || continue
|
|
[ -z "$version" -o "$version" == "$DVERSION" ] || continue
|
|
return 0
|
|
done
|
|
if [ -n "$latest" ]; then
|
|
# trouver la dernière occurence de la première distribution
|
|
# mentionnée. en effet, les versions doivent être ordonnées de la
|
|
# plus ancienne à la plus récente.
|
|
local first_dist last_version
|
|
for dist in "${SETDISTS[@]}"; do
|
|
parse_dist "$dist" dist version
|
|
if [ -z "$first_dist" ]; then
|
|
first_dist="$dist"
|
|
last_version="$version"
|
|
elif [ "$dist" == "$first_dist" ]; then
|
|
last_version="$version"
|
|
fi
|
|
done
|
|
if [ "$first_dist" == "$DIST" ]; then
|
|
if [ -z "$last_version" -o "$last_version" == "$DVERSION" ]; then
|
|
return 0
|
|
fi
|
|
fi
|
|
fi
|
|
return 1
|
|
}
|
|
function version() {
|
|
local version
|
|
for version in "$@"; do
|
|
[ "$version" == "$VERSION" ] && return 0
|
|
done
|
|
return 1
|
|
}
|
|
function profile() {
|
|
local profile version default
|
|
for profile in "$@"; do
|
|
if [ "$profile" == DEFAULT ]; then
|
|
default=1
|
|
continue
|
|
fi
|
|
parse_profile "$profile" profile version
|
|
[ "$profile" == "$PROFILE" ] || continue
|
|
[ -z "$version" -o "$version" == "$PVERSION" ] || continue
|
|
return 0
|
|
done
|
|
if [ -n "$default" ]; then
|
|
# trouver la dernière occurence du premier profil mentionné. en
|
|
# effet, les versions doivent être ordonnées de la plus ancienne à
|
|
# la plus récente.
|
|
local first_profile last_version
|
|
for profile in "${SETPROFILES[@]}"; do
|
|
parse_profile "$profile" profile version
|
|
if [ -z "$first_profile" ]; then
|
|
first_profile="$profile"
|
|
last_version="$version"
|
|
elif [ "$profile" == "$first_profile" ]; then
|
|
last_version="$version"
|
|
fi
|
|
done
|
|
if [ "$first_profile" == "$PROFILE" ]; then
|
|
if [ -z "$last_version" -o "$last_version" == "$PVERSION" ]; then
|
|
return 0
|
|
fi
|
|
fi
|
|
fi
|
|
return 1
|
|
}
|
|
declare -g -A ENVIRON
|
|
function setenv() {
|
|
local name value
|
|
for name in "$@"; do
|
|
if [[ "$name" == *=* ]]; then
|
|
value="${name#*=}"
|
|
name="${name%%=*}"
|
|
else
|
|
value="${_ENVIRON[$name]-__UNDEFINED__}"
|
|
[ "$value" == __UNDEFINED__ ] && die "la variable d'environnement $name doit être définie"
|
|
fi
|
|
if [ "${ENVIRON[$name]-__UNDEFINED__}" == __UNDEFINED__ ]; then
|
|
# Ne spécifier la valeur que si elle n'a pas déjà été définie
|
|
_ENVIRON["$name"]="$value"
|
|
ENVIRON["$name"]="$value"
|
|
[ -z "${PROTECTED_VARS[$name]}" ] && _setv "export $name" "$value"
|
|
fi
|
|
done
|
|
}
|
|
function resetenv() {
|
|
local name value
|
|
for name in "$@"; do
|
|
if [[ "$name" == *=* ]]; then
|
|
value="${name#*=}"
|
|
name="${name%%=*}"
|
|
else
|
|
value="${_ENVIRON[$name]-__UNDEFINED__}"
|
|
[ "$value" == __UNDEFINED__ ] && die "la variable d'environnement $name doit être définie"
|
|
fi
|
|
_ENVIRON["$name"]="$value"
|
|
ENVIRON["$name"]="$value"
|
|
[ -z "${PROTECTED_VARS[$name]}" ] && _setv "export $name" "$value"
|
|
done
|
|
}
|
|
declare -g -A ARGS
|
|
function setarg() {
|
|
local name value
|
|
for name in "$@"; do
|
|
if [[ "$name" == *=* ]]; then
|
|
value="${name#*=}"
|
|
name="${name%%=*}"
|
|
else
|
|
value="${_ENVIRON[$name]-__UNDEFINED__}"
|
|
[ "$value" == __UNDEFINED__ ] && die "la variable d'environnement $name doit être définie"
|
|
fi
|
|
if [ "${ARGS[$name]-__UNDEFINED__}" == __UNDEFINED__ ]; then
|
|
# Ne spécifier la valeur que si elle n'a pas déjà été définie
|
|
ARGS["$name"]="$value"
|
|
fi
|
|
done
|
|
}
|
|
function resetarg() {
|
|
local name value
|
|
for name in "$@"; do
|
|
if [[ "$name" == *=* ]]; then
|
|
value="${name#*=}"
|
|
name="${name%%=*}"
|
|
else
|
|
value="${_ENVIRON[$name]-__UNDEFINED__}"
|
|
[ "$value" == __UNDEFINED__ ] && die "la variable d'environnement $name doit être définie"
|
|
fi
|
|
ARGS["$name"]="$value"
|
|
done
|
|
}
|
|
declare -g -A DEFAULTS
|
|
function default() {
|
|
local command="$1"; shift
|
|
local name value
|
|
for name in "$@"; do
|
|
if [[ "$name" == *=* ]]; then
|
|
value="${name#*=}"
|
|
name="${name%%=*}"
|
|
else
|
|
value=1
|
|
fi
|
|
name="${command}_$name"
|
|
if [ "${DEFAULTS[$name]-__UNDEFINED__}" == __UNDEFINED__ ]; then
|
|
# Ne spécifier la valeur que si elle n'a pas déjà été définie
|
|
DEFAULTS["$name"]="$value"
|
|
fi
|
|
done
|
|
}
|
|
function resetdefault() {
|
|
local command="$1"; shift
|
|
local name value
|
|
for name in "$@"; do
|
|
if [[ "$name" == *=* ]]; then
|
|
value="${name#*=}"
|
|
name="${name%%=*}"
|
|
else
|
|
value=1
|
|
fi
|
|
name="${command}_$name"
|
|
DEFAULTS["$name"]="$value"
|
|
done
|
|
}
|
|
}
|
|
|
|
function parse_dist() {
|
|
local dist="$1" version
|
|
if [[ "$dist" == *-* ]]; then
|
|
version="${dist%-*}"
|
|
dist="${dist##*-}"
|
|
fi
|
|
local "${2:-dist}"; upvar "${2:-dist}" "$dist"
|
|
local "${3:-version}"; upvar "${3:-version}" "$version"
|
|
}
|
|
|
|
function parse_profile() {
|
|
local profile="$1" version
|
|
if [[ "$profile" == *-* ]]; then
|
|
version="${profile%-*}"
|
|
profile="${profile##*-}"
|
|
fi
|
|
local "${2:-profile}"; upvar "${2:-profile}" "$profile"
|
|
local "${3:-version}"; upvar "${3:-version}" "$version"
|
|
}
|
|
|
|
function resolve_dists_profiles() {
|
|
## construire d'abord la liste des distributions et profils
|
|
edebug "Calcul de la liste des distributions et des profils"
|
|
reset_functions
|
|
SETDISTS_DONE=
|
|
SETDISTS=()
|
|
SETPROFILES_DONE=
|
|
SETPROFILES=()
|
|
DEFAULT_PROFILE=
|
|
SETVERSION_DONE=
|
|
SETVERSION=
|
|
AUTOBUILD=1
|
|
|
|
function setdists() {
|
|
[ -n "$SETDISTS_DONE" ] && return
|
|
SETDISTS=("$@")
|
|
SETDISTS_DONE=1
|
|
}
|
|
function setprofiles() {
|
|
[ -n "$SETPROFILES_DONE" ] && return
|
|
SETPROFILES=("$@")
|
|
SETPROFILES_DONE=1
|
|
}
|
|
function default_profile() {
|
|
[ -n "$DEFAULT_PROFILE" ] || DEFAULT_PROFILE="$1"
|
|
}
|
|
function build() {
|
|
AUTOBUILD=
|
|
}
|
|
function cbuild() {
|
|
AUTOBUILD=
|
|
}
|
|
load_dkbuild
|
|
|
|
if [ -z "$PROFILE" -a -z "$ALL_PROFILES" -a -n "$DEFAULT_PROFILE" ]; then
|
|
enote "Auto-sélection du profil $DEFAULT_PROFILE"
|
|
PROFILE="$DEFAULT_PROFILE"
|
|
fi
|
|
local MANUAL_SETPROFILES=
|
|
if [ -z "$SETPROFILES_DONE" -a -n "$PROFILE" ]; then
|
|
# Si l'utilisateur spécifie un profil mais qu'aucun profil n'a été
|
|
# défini dans la configuration, considérer que c'est cet unique profil
|
|
# qui a été défini
|
|
SETPROFILES=("$PROFILE")
|
|
SETPROFILES_DONE=1
|
|
MANUAL_SETPROFILES=1
|
|
fi
|
|
|
|
## ensuite vérifier si on est dans la bonne distribution
|
|
edebug "Calcul de la distribution courante"
|
|
reset_functions
|
|
DISTS=()
|
|
function setdists() {
|
|
local dist version found
|
|
# construire la liste des distributions à considérer
|
|
if [ -n "$DIST" ]; then
|
|
# on a spécifié une distribution en argument
|
|
for dist in "${SETDISTS[@]}"; do
|
|
if [ "$dist" == "$DIST" ]; then
|
|
# matcher avec la version éventuellement
|
|
found=1
|
|
break
|
|
fi
|
|
parse_dist "$dist"
|
|
if [ "$dist" == "$DIST" ]; then
|
|
# ou matcher uniquement la distribution
|
|
found=1
|
|
break
|
|
fi
|
|
done
|
|
# si aucune distribution ne correspond, arrêter le script
|
|
[ -n "$found" ] || exit 0
|
|
# forcer à ne construire que cette distribution
|
|
DISTS=("$DIST")
|
|
else
|
|
DISTS=("${SETDISTS[@]}")
|
|
fi
|
|
}
|
|
load_dkbuild
|
|
|
|
## puis vérifier si on est dans le bon profil
|
|
edebug "Calcul du profil courant"
|
|
reset_functions
|
|
PROFILES=()
|
|
function setprofiles() {
|
|
local profile version found
|
|
# construire la liste des distributions à considérer
|
|
if [ -n "$PROFILE" ]; then
|
|
# on a spécifié une distribution en argument
|
|
for profile in "${SETPROFILES[@]}"; do
|
|
if [ "$profile" == "$PROFILE" ]; then
|
|
# matcher avec la version éventuellement
|
|
found=1
|
|
break
|
|
fi
|
|
parse_profile "$profile"
|
|
if [ "$profile" == "$PROFILE" ]; then
|
|
# ou matcher uniquement le profil
|
|
found=1
|
|
break
|
|
fi
|
|
done
|
|
# si aucune distribution ne correspond, arrêter le script
|
|
[ -n "$found" ] || die "$PROFILE: profil invalide"
|
|
# forcer à ne construire que cette distribution
|
|
PROFILES=("$PROFILE")
|
|
elif [ -n "$ALL_PROFILES" ]; then
|
|
# prendre tous les profils comme indiqué
|
|
for profile in "${SETPROFILES[@]}"; do
|
|
parse_profile "$profile"
|
|
PROFILES+=("$profile")
|
|
done
|
|
else
|
|
# prendre le profil par défaut
|
|
parse_profile "${SETPROFILES[0]}"
|
|
PROFILES=("$profile")
|
|
fi
|
|
}
|
|
load_dkbuild
|
|
|
|
if [ -n "$MANUAL_SETPROFILES" ]; then
|
|
setprofiles "$PROFILE"
|
|
fi
|
|
|
|
## Si pas de distribution ou de profil, remplacer par valeur vide
|
|
if [ ${#DISTS[*]} -eq 0 ]; then
|
|
SETDISTS=("")
|
|
DISTS=("")
|
|
fi
|
|
if [ ${#PROFILES[*]} -eq 0 ]; then
|
|
SETPROFILES=("")
|
|
PROFILES=("")
|
|
fi
|
|
|
|
## puis calculer la version par défaut
|
|
edebug "Calcul de la version par défaut"
|
|
reset_functions
|
|
define_functions_env
|
|
load_dkbuild
|
|
}
|
|
|
|
function foreach_dists_profiles() {
|
|
local each="$1" before="$2" after="$3"
|
|
|
|
local version dist dversion profile pversion
|
|
local VERSION DIST DVERSION PROFILE PVERSION
|
|
local HAVE_VERSION LAST_VERSION
|
|
declare -A dones
|
|
|
|
if [ -n "$before" ]; then
|
|
"$before"
|
|
fi
|
|
for dist in "${DISTS[@]}"; do
|
|
parse_dist "$dist" dist dversion
|
|
# y a-t-il une version dans cette distribution ou ce profil, et si oui, laquelle?
|
|
HAVE_VERSION=
|
|
LAST_VERSION=
|
|
for DIST in "${SETDISTS[@]}"; do
|
|
parse_dist "$DIST" DIST DVERSION
|
|
[ "$DIST" == "$dist" ] || continue
|
|
VERSION="$DVERSION"
|
|
for profile in "${PROFILES[@]}"; do
|
|
parse_profile "$profile" profile pversion
|
|
for PROFILE in "${SETPROFILES[@]}"; do
|
|
parse_profile "$PROFILE" PROFILE PVERSION
|
|
[ "$PROFILE" == "$profile" ] || continue
|
|
[ -n "$DVERSION" ] && PVERSION= || VERSION="$PVERSION"
|
|
[ -z "$VERSION" -a -n "$SETVERSION" ] && VERSION="$SETVERSION"
|
|
if [ -n "$VERSION" ]; then
|
|
HAVE_VERSION=1
|
|
LAST_VERSION="$VERSION"
|
|
fi
|
|
done
|
|
done
|
|
done
|
|
|
|
for DIST in "${SETDISTS[@]}"; do
|
|
parse_dist "$DIST" DIST DVERSION
|
|
[ "$DIST" == "$dist" ] || continue
|
|
[ -z "$dversion" -o "$DVERSION" == "$dversion" ] || continue
|
|
VERSION="$DVERSION"
|
|
|
|
for profile in "${PROFILES[@]}"; do
|
|
parse_profile "$profile" profile pversion
|
|
for PROFILE in "${SETPROFILES[@]}"; do
|
|
parse_profile "$PROFILE" PROFILE PVERSION
|
|
[ "$PROFILE" == "$profile" ] || continue
|
|
if [ -z "$DVERSION" ]; then
|
|
[ -z "$pversion" -o "$PVERSION" == "$pversion" ] || continue
|
|
VERSION="$PVERSION"
|
|
else
|
|
PVERSION=
|
|
fi
|
|
|
|
[ -n "${dones[$PVERSION-$PROFILE-$DVERSION-$DIST]}" ] && continue
|
|
dones["$PVERSION-$PROFILE-$DVERSION-$DIST"]=1
|
|
|
|
[ -z "$VERSION" -a -n "$SETVERSION" ] && VERSION="$SETVERSION"
|
|
|
|
"$each"
|
|
done
|
|
done
|
|
done
|
|
done
|
|
if [ -n "$after" ]; then
|
|
"$after"
|
|
fi
|
|
}
|
|
|
|
function define_functions_cmd() {
|
|
_IN_SECTION=
|
|
function section() {
|
|
[ -n "$_IN_SECTION" ] && eend
|
|
etitle "$*"
|
|
_IN_SECTION=1
|
|
}
|
|
function note() {
|
|
enote "$*"
|
|
}
|
|
function info() {
|
|
estep "$*"
|
|
}
|
|
function debug() {
|
|
edebug "$*"
|
|
}
|
|
function checkout() {
|
|
edebug "checkout $(qvals "$@")"
|
|
|
|
local url destdir
|
|
[[ "$1" != *=* ]] && { url="$1"; shift; }
|
|
[[ "$1" != *=* ]] && { destdir="$1"; shift; }
|
|
|
|
local checkout="${DEFAULTS[checkout_checkout]-1}"
|
|
local origin="${DEFAULTS[checkout_origin]}"
|
|
local branch="${DEFAULTS[checkout_branch]}"
|
|
local develdir="${DEFAULTS[checkout_develdir]}"
|
|
local develtype="${DEFAULTS[checkout_develtype]}"
|
|
while [ $# -gt 0 ]; do
|
|
case "$1" in
|
|
checkout) checkout=1;;
|
|
checkout=*) checkout="${1#checkout=}";;
|
|
origin=*) origin="${1#origin=}";;
|
|
branch=*) branch="${1#branch=}";;
|
|
develdir=*) develdir="${1#develdir=}";;
|
|
develtype=*) develtype="${1#develtype=}";;
|
|
*) ewarn "checkout: $1: argument ignoré";;
|
|
esac
|
|
shift
|
|
done
|
|
|
|
[ -n "$checkout" ] || return
|
|
[ -n "$url" -a -n "$destdir" ] || die "checkout: Vous devez spécifier l'url du dépôt et la destination"
|
|
[ -n "$origin" ] || origin=origin
|
|
if [ -z "$branch" ]; then
|
|
case "$PROFILE" in
|
|
test|devel) branch=develop;;
|
|
*) branch=master;;
|
|
esac
|
|
fi
|
|
|
|
if [ "$checkout" == devel ]; then
|
|
# synchronisation depuis le répertoire de développement
|
|
[ -n "$develdir" ] || die "checkout: vous devez spécifier le répertoire de développement"
|
|
[ -d "$develdir" ] || die "checkout: répertoire de développement introuvable"
|
|
|
|
die "Pas encore implémenté" #XXX
|
|
|
|
elif [ -d "$destdir" -a -d "$destdir/.git" ]; then
|
|
# maj du dépôt
|
|
local cwd="$(pwd)"
|
|
|
|
estep "checkout: maj du dépôt $url --> $destdir (origin=$origin, branch=$branch)"
|
|
cd "$destdir"
|
|
git fetch --all -p -f || die
|
|
if [ "${branch#^}" != "$branch" ]; then
|
|
git reset --hard "${branch#^}" || die
|
|
else
|
|
git reset --hard "$origin/$branch" || die
|
|
fi
|
|
cd "$cwd"
|
|
|
|
else
|
|
# reliquat checkout=devel?
|
|
[ -d "$destdir" ] && rm -rf "$destdir"
|
|
|
|
# clone
|
|
estep "checkout: clone du dépôt $url --> $destdir (origin=$origin, branch=$branch)"
|
|
if [ "${BRANCH#^}" != "$BRANCH" ]; then
|
|
local cwd="$(pwd)"
|
|
git clone -o "$origin" "$url" "$destdir" || die
|
|
cd "$destdir"
|
|
git reset --hard "${branch#^}" || die
|
|
cd "$cwd"
|
|
else
|
|
git clone -o "$origin" -b "$branch" "$url" "$destdir" || die
|
|
fi
|
|
fi
|
|
}
|
|
function copy() {
|
|
edebug "copy $(qvals "$@")"
|
|
|
|
local src dest
|
|
[[ "$1" != *=* ]] && { src="$1"; shift; }
|
|
[[ "$1" != *=* ]] && { dest="$1"; shift; }
|
|
|
|
local copy="${DEFAULTS[copy_copy]-1}"
|
|
local overwrite="${DEFAULTS[copy_overwrite]}"
|
|
local gitignore="${DEFAULTS[copy_gitignore]}"
|
|
while [ $# -gt 0 ]; do
|
|
case "$1" in
|
|
copy) copy=1;;
|
|
copy=*) copy="${1#copy=}";;
|
|
overwrite) overwrite=1;;
|
|
overwrite=*) overwrite="${1#overwrite=}";;
|
|
gitignore=*) gitignore="${1#gitignore=}";;
|
|
*) ewarn "copy: $1: argument ignoré";;
|
|
esac
|
|
shift
|
|
done
|
|
|
|
[ -n "$copy" ] || return
|
|
[ -n "$src" -a -n "$dest" ] || die "copy: Vous devez spécifier la source et la destination de la copie"
|
|
[ -e "$src" ] || {
|
|
ewarn "copy: $src: fichier ou répertoire introuvables"
|
|
return 1
|
|
}
|
|
|
|
local srcdir destdir
|
|
if [ "${src%/}" != "$src" ]; then
|
|
[ -d "$src" ] || die "copy: $src: doit être un répertoire"
|
|
setx srcdir=abspath "$src"
|
|
src=
|
|
elif [ -d "$src" ]; then
|
|
setx srcdir=abspath "$src"
|
|
src=
|
|
else
|
|
setx src=abspath "$src"
|
|
fi
|
|
if [ "${dest%/}" != "$dest" ]; then
|
|
[ -f "$dest" ] && die "copy: $dest: doit être un répertoire"
|
|
setx destdir=abspath "$dest"
|
|
dest=
|
|
elif [ -d "$dest" ]; then
|
|
setx destdir=abspath "$dest"
|
|
dest=
|
|
elif [ -f "$dest" ]; then
|
|
[ -n "$srcdir" ] && die "copy: $dest: doit être un répertoire"
|
|
setx dest=abspath "$dest"
|
|
elif [ -n "$srcdir" ]; then
|
|
setx destdir=abspath "$dest"
|
|
dest=
|
|
else
|
|
setx dest=abspath "$dest"
|
|
fi
|
|
|
|
local -a srcs dests
|
|
if [ -n "$srcdir" -a -n "$destdir" ]; then
|
|
# copie de répertoire à répertoire
|
|
local destpath="$(relpath "$destdir" "$PROJDIR")"
|
|
[ -n "$destpath" ] || destpath=.
|
|
estep "copy $(relpath "$srcdir" "$PROJDIR")/ --> $destpath/"
|
|
|
|
array_from_lines srcs "$(find "$srcdir/" -type f -o -type l)"
|
|
for src in "${srcs[@]}"; do
|
|
dest="$destdir/${src#$srcdir/}"
|
|
if [ -n "$overwrite" -o ! -f "$dest" ]; then
|
|
mkdirof "$dest" || die
|
|
cp -dfl "$src" "$dest" || die
|
|
dests+=("$dest")
|
|
fi
|
|
done
|
|
|
|
elif [ -n "$src" ]; then
|
|
# transformer copie de fichier à répertoire en copie de fichier à fichier
|
|
[ -n "$dest" ] || dest="$destdir/$(basename "$src")"
|
|
|
|
if [ -n "$overwrite" -o ! -f "$dest" ]; then
|
|
# copie de fichier à fichier
|
|
estep "copy $(relpath "$src" "$PROJDIR") --> $(relpath "$dest" "$PROJDIR")"
|
|
mkdirof "$dest" || die
|
|
cp -fl "$src" "$dest" || die
|
|
|
|
setx destdir=dirname "$dest"
|
|
dests+=("$dest")
|
|
fi
|
|
|
|
else
|
|
# en réalité, on ne devrait jamais arriver ici
|
|
die "copy: impossible de copier un répertoire dans un fichier"
|
|
fi
|
|
|
|
if [ -n "$gitignore" ]; then
|
|
setx gitignore=abspath "$gitignore"
|
|
[ -d "$gitignore" ] && gitignore="$gitignore/.gitignore"
|
|
|
|
local basedir
|
|
setx basedir=dirname "$gitignore"
|
|
if [ "${destdir#$basedir/}" == "$destdir" -a "$destdir" != "$basedir" ]; then
|
|
ewarn "copy: gitignore ignoré parce que le répertoire n'est pas un parent de destdir"
|
|
else
|
|
[ -f "$gitignore" ] || { mkdir -p "$basedir"; touch "$gitignore"; }
|
|
|
|
declare -A ignored_dirs
|
|
local ignored_dir
|
|
for dest in "${dests[@]}"; do
|
|
dest="/${dest#$basedir/}"
|
|
if grep -q "^$dest\$" "$gitignore"; then
|
|
ignored=1
|
|
else
|
|
ignored=
|
|
setx ignored_dir=dirname "$dest"
|
|
while [ "$ignored_dir" != / ]; do
|
|
ignored="${ignored_dirs[$ignored_dir/]-compute}"
|
|
if [ "$ignored" == compute ]; then
|
|
grep -q "^$ignored_dir/\$" "$gitignore" && ignored=1 || ignored=
|
|
ignored_dirs["$ignored_dir/"]="$ignored"
|
|
fi
|
|
if [ -n "$ignored" ]; then
|
|
# un répertoire parent est déjà ignoré, on peut
|
|
# passer au fichier suivant
|
|
break
|
|
fi
|
|
setx ignored_dir=dirname "$ignored_dir"
|
|
done
|
|
fi
|
|
|
|
if [ -z "$ignored" ]; then
|
|
# le fichier n'est pas ignoré, ni directement, ni via un
|
|
# répertoire parent. il faut donc l'ajouter à .gitignore
|
|
echo "$dest" >>"$gitignore"
|
|
fi
|
|
done
|
|
fi
|
|
fi
|
|
}
|
|
function genfile() {
|
|
edebug "genfile $(qvals "$@")"
|
|
|
|
local output input
|
|
[[ "$1" != *=* ]] && { output="$1"; shift; }
|
|
[[ "$1" != *=* ]] && { input="$1"; shift; }
|
|
|
|
local context="${DEFAULTS[genfile_context]}"
|
|
local sed="${DEFAULTS[genfile_sed]}"
|
|
while [ $# -gt 0 ]; do
|
|
case "$1" in
|
|
context=*) context="${1#context=}";;
|
|
sed=*) sed="${1#sed=}";;
|
|
*) ewarn "genfile: $1: argument ignoré";;
|
|
esac
|
|
shift
|
|
done
|
|
|
|
[ -n "${DEFAULTS[build_build]-1}" ] || return 0
|
|
[ -n "$output" ] || die "genfile: Vous devez spécifier le fichier en sortie"
|
|
if [ -n "$context" ]; then
|
|
mkdir -p "$context" || die
|
|
output="$context/$output"
|
|
fi
|
|
|
|
if [ -n "$input" ]; then
|
|
cat "$input" >"$output" || die
|
|
elif ! tty -s; then
|
|
cat >"$output"
|
|
else
|
|
die "genfile: Vous devez spécifier une source pour le fichier $output"
|
|
fi
|
|
if [ -n "$sed" ]; then
|
|
sed -i "$sed" "$output"
|
|
fi
|
|
}
|
|
function dockerfile() {
|
|
edebug "dockerfile $(qvals "$@")"
|
|
|
|
local input
|
|
[[ "$1" != *=* ]] && { DOCKERFILE="$1"; shift; }
|
|
[[ "$1" != *=* ]] && { input="$1"; shift; }
|
|
|
|
local context="${DEFAULTS[dockerfile_context]}"
|
|
local sed="${DEFAULTS[dockerfile_sed]}"
|
|
while [ $# -gt 0 ]; do
|
|
case "$1" in
|
|
context=*) context="${1#context=}";;
|
|
sed=*) sed="${1#sed=}";;
|
|
*) ewarn "dockerfile: $1: argument ignoré";;
|
|
esac
|
|
shift
|
|
done
|
|
|
|
[ -n "${DEFAULTS[build_build]-1}" ] || return 0
|
|
[ -n "$DOCKERFILE" ] || DOCKERFILE=Dockerfile
|
|
DOCKERCONTEXT=.
|
|
if [ -n "$context" ]; then
|
|
mkdir -p "$context" || die
|
|
DOCKERCONTEXT="$context"
|
|
DOCKERFILE="$context/$DOCKERFILE"
|
|
fi
|
|
|
|
setx DOCKERFILE=abspath "$DOCKERFILE"
|
|
if [ -n "$input" ]; then
|
|
cat "$input" >"$DOCKERFILE" || die
|
|
elif ! tty -s; then
|
|
cat >"$DOCKERFILE" || die
|
|
else
|
|
echo "# -*- coding: utf-8 mode: dockerfile -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8" >"$DOCKERFILE"
|
|
fi
|
|
if [ -n "$sed" ]; then
|
|
sed -i "$sed" "$DOCKERFILE"
|
|
fi
|
|
}
|
|
function add2dockerfile() {
|
|
edebug "$(qvals "$@")"
|
|
|
|
[ -n "${DEFAULTS[build_build]-1}" ] || return 0
|
|
[ -n "$DOCKERFILE" ] || return
|
|
echo "$*" >>"$DOCKERFILE"
|
|
}
|
|
function FROM() { add2dockerfile FROM "$@"; }
|
|
function RUN() { add2dockerfile RUN "$@"; }
|
|
function CMD() { add2dockerfile CMD "$@"; }
|
|
function LABEL() { add2dockerfile LABEL "$@"; }
|
|
function MAINTAINER() { add2dockerfile MAINTAINER "$@"; }
|
|
function EXPOSE() { add2dockerfile EXPOSE "$@"; }
|
|
function ENV() { add2dockerfile ENV "$@"; }
|
|
function ADD() { add2dockerfile ADD "$@"; }
|
|
function COPY() { add2dockerfile COPY "$@"; }
|
|
function ENTRYPOINT() { add2dockerfile ENTRYPOINT "$@"; }
|
|
function VOLUME() { add2dockerfile VOLUME "$@"; }
|
|
function USER() { add2dockerfile USER "$@"; }
|
|
function WORKDIR() { add2dockerfile WORKDIR "$@"; }
|
|
function ARG() { add2dockerfile ARG "$@"; }
|
|
function ONBUILD() { add2dockerfile ONBUILD "$@"; }
|
|
function STOPSIGNAL() { add2dockerfile STOPSIGNAL "$@"; }
|
|
function HEALTHCHECK() { add2dockerfile HEALTHCHECK "$@"; }
|
|
function SHELL() { add2dockerfile SHELL "$@"; }
|
|
function build() {
|
|
edebug "build $(qvals "$@")"
|
|
|
|
local build="${DEFAULTS[build_build]-1}"
|
|
local no_cache="${DEFAULTS[build_no-cache]}"
|
|
local pull="${DEFAULTS[build_pull]}"
|
|
local host_mappings="${DEFAULTS[build_host-mappings]-__UNDEFINED__}"
|
|
[ "$host_mappings" == __UNDEFINED__ ] && host_mappings="${DEFAULTS[docker_host-mappings]}"
|
|
local set_tags="${DEFAULTS[build_set-tags]}"
|
|
local add_tags="${DEFAULTS[build_add-tags]}"
|
|
local images="${DEFAULTS[build_images]}"
|
|
local push="${DEFAULTS[build_push]}"
|
|
while [ $# -gt 0 ]; do
|
|
case "$1" in
|
|
build) build=1;;
|
|
build=*) build="${1#build=}";;
|
|
context=*) DOCKERCONTEXT="${1#context=}";;
|
|
dockerfile=*) DOCKERFILE="${1#dockerfile=}";;
|
|
no-cache) no_cache=1;;
|
|
no-cache=*) no_cache="${1#no-cache=}";;
|
|
pull) pull=1;;
|
|
pull=*) pull="${1#pull=}";;
|
|
host-mappings=*) host_mappings="${1#host-mappings=}";;
|
|
set-tag=*) set_tags="${1#set-tag=}";;
|
|
set-tags=*) set_tags="${1#set-tags=}";;
|
|
add-tag=*) add_tags="${1#add-tag=}";;
|
|
add-tags=*) add_tags="${1#add-tags=}";;
|
|
image=*) images="${1#image=}";;
|
|
images=*) images="${1#images=}";;
|
|
push) push=1;;
|
|
push=*) push="${1#push=}";;
|
|
*) ewarn "build: $1: argument ignoré";;
|
|
esac
|
|
shift
|
|
done
|
|
|
|
estep "build options:" ${build:+build} ${no_cache:+no-cache} ${pull:+pull} ${push:+push}
|
|
|
|
[ -n "$images" ] || images="$IMAGE"
|
|
eval "set_tags=($set_tags)"
|
|
eval "add_tags=($add_tags)"
|
|
eval "images=($images)"
|
|
local tag imagetag autotag=1
|
|
local -a imagetags
|
|
if [ ${#set_tags[*]} -gt 0 ]; then
|
|
autotag=
|
|
for imagetag in "${images[@]}"; do
|
|
if [[ "$imagetag" == *:* ]]; then
|
|
# le tag est déjà spécifié
|
|
imagetags+=("$imagetag")
|
|
else
|
|
for tag in "${set_tags[@]}" "${add_tags[@]}"; do
|
|
imagetags+=("$imagetag:$tag")
|
|
done
|
|
fi
|
|
done
|
|
else
|
|
for imagetag in "${images[@]}"; do
|
|
if [[ "$imagetag" == *:* ]]; then
|
|
# le tag est déjà spécifié
|
|
autotag=
|
|
imagetags+=("$imagetag")
|
|
else
|
|
for tag in "${add_tags[@]}"; do
|
|
imagetags+=("$imagetag:$tag")
|
|
done
|
|
[ -n "$VERSION" ] && imagetags+=("$imagetag:$VERSION-$DIST")
|
|
[ -n "$DIST" -a -z "$HAVE_VERSION" ] && imagetags+=("$imagetag:$DIST")
|
|
fi
|
|
done
|
|
fi
|
|
if [ -n "$autotag" ]; then
|
|
if [ -n "$DIST" ]; then
|
|
if [ -z "$HAVE_VERSION" ]; then
|
|
dist LATEST && imagetags+=("$imagetag:latest")
|
|
elif [ "$VERSION" == "$LAST_VERSION" ]; then
|
|
imagetags+=("$imagetag:$DIST")
|
|
dist LATEST && imagetags+=("$imagetag:latest")
|
|
fi
|
|
elif [ -n "$PROFILE" ]; then
|
|
profile DEFAULT && imagetags+=("$imagetag:latest")
|
|
else
|
|
imagetags+=("$imagetag:latest")
|
|
fi
|
|
fi
|
|
|
|
local avar
|
|
local -a args; args=(
|
|
${no_cache:+--no-cache}
|
|
${progress:+--progress "$progress"}
|
|
${pull:+--pull}
|
|
)
|
|
eval "host_mappings=($host_mappings)"
|
|
for host_mapping in "${host_mappings[@]}"; do
|
|
args+=(--add-host "$host_mapping")
|
|
done
|
|
for avar in "${!ARGS[@]}"; do
|
|
args+=(--build-arg "$avar=${ARGS[$avar]}")
|
|
done
|
|
for imagetag in "${imagetags[@]}"; do
|
|
args+=(-t "$imagetag")
|
|
estep "tag $imagetag"
|
|
done
|
|
|
|
[ -n "$DOCKERCONTEXT" ] || DOCKERCONTEXT="${DEFAULTS[build_context]:-.}"
|
|
[ -n "$DOCKERFILE" ] || DOCKERFILE="${DEFAULTS[build_dockerfile]:-Dockerfile}"
|
|
if [ -n "$build" ]; then
|
|
etitle build
|
|
_runcmd docker build "${args[@]}" -f "$DOCKERFILE" "$DOCKERCONTEXT" || die
|
|
eend
|
|
fi
|
|
|
|
if [ -n "$push" ]; then
|
|
etitle push
|
|
for imagetag in "${imagetags[@]}"; do
|
|
_runcmd docker push "$imagetag" || die
|
|
done
|
|
eend
|
|
fi
|
|
|
|
DOCKERCONTEXT=
|
|
DOCKERFILE=
|
|
[ -n "$build" -o -n "$push" ]
|
|
}
|
|
function cbuild() {
|
|
edebug "cbuild $(qvals "$@")"
|
|
|
|
local build="${DEFAULTS[build_build]-1}"
|
|
local files="${DEFAULTS[cbuild_files]}"
|
|
local project_name="${DEFAULTS[cbuild_project-name]}"
|
|
local no_cache="${DEFAULTS[cbuild_no-cache]}"
|
|
local pull="${DEFAULTS[cbuild_pull]}"
|
|
while [ $# -gt 0 ]; do
|
|
case "$1" in
|
|
files=*) files="${1#files=}";;
|
|
project-name=*) project_name="${1#project-name=}";;
|
|
no-cache) no_cache=1;;
|
|
no-cache=*) no_cache="${1#no-cache=}";;
|
|
pull) pull=1;;
|
|
pull=*) pull="${1#pull=}";;
|
|
*=*) ewarn "cbuild: $1: argument ignoré";;
|
|
*) break;;
|
|
esac
|
|
shift
|
|
done
|
|
|
|
[ -n "$build" ] || return
|
|
if [ -n "$files" ]; then
|
|
eval "files=($files)"
|
|
else
|
|
files=(docker-compose.yml)
|
|
if [ -f "docker-compose.override.yml" ]; then
|
|
files+=("docker-compose.override.yml")
|
|
fi
|
|
if [ -n "$PROFILE" -a -f "docker-compose.$PROFILE.yml" ]; then
|
|
files+=("docker-compose.$PROFILE.yml")
|
|
fi
|
|
fi
|
|
[ -n "$project_name" ] || setx project_name=get_project_name
|
|
|
|
estep "cbuild files:" ${files[@]}
|
|
estep "cbuild options:" project_name="$project_name" ${no_cache:+no-cache} ${pull:+pull}
|
|
|
|
local file; local -a args
|
|
args=(
|
|
-p "$project_name"
|
|
)
|
|
for file in "${files[@]}"; do
|
|
args+=(-f "$file")
|
|
done
|
|
local avar evar; local -a bargs
|
|
bargs=(
|
|
${no_cache:+--no-cache}
|
|
${progress:+--progress "$progress"}
|
|
${pull:+--pull}
|
|
)
|
|
for avar in "${!ARGS[@]}"; do
|
|
bargs+=(--build-arg "$avar=${ARGS[$avar]}")
|
|
done
|
|
|
|
if [ -f .shared_env -o -f ".${MACHINE}_env" -o ${#ENVIRON[*]} -gt 0 ]; then
|
|
echo >.env "## fichier auto-généré. ne pas modifier ##"
|
|
fi
|
|
[ -f .shared_env ] && cat .shared_env >>.env
|
|
[ -f ".${MACHINE}_env" ] && cat ".${MACHINE}_env" >>.env
|
|
for evar in "${!ENVIRON[@]}"; do
|
|
echo_setv "$evar=${ENVIRON[$evar]}" >>.env
|
|
done
|
|
|
|
_runcmd "${DOCKER_COMPOSE[@]}" "${args[@]}" build "${bargs[@]}" "$@" || die
|
|
}
|
|
function _local_composer() {
|
|
case "$action" in
|
|
rootshell|rshell|rootbash|rbash)
|
|
shift
|
|
estep "Lancement d'un shell root"
|
|
sudo bash "$@"
|
|
return $?
|
|
;;
|
|
usershell|shell|userbash|bash)
|
|
shift
|
|
estep "Lancement d'un shell utilisateur"
|
|
bash "$@"
|
|
return $?
|
|
;;
|
|
*)
|
|
estep "composer $action"
|
|
if [ -n "$composer" ]; then :
|
|
elif [ -x composer.phar ]; then composer=./composer.phar
|
|
elif [ -x /usr/bin/composer ]; then composer=/usr/bin/composer
|
|
else die "Impossible de trouver composer"
|
|
fi
|
|
"$composer" "$action" $args "$@"
|
|
esac
|
|
}
|
|
function _docker_composer() {
|
|
local user group projdir actualcmd
|
|
setx user=id -un; setx user=getent passwd "$user"
|
|
setx group=id -gn; setx group=getent group "$group"
|
|
setx projdir=pwd
|
|
case "$action" in
|
|
rootshell|rshell|rootbash|rbash)
|
|
action=rshell
|
|
shift
|
|
actualcmd='eval "bash $args"'
|
|
;;
|
|
usershell|shell|userbash|bash)
|
|
action=shell
|
|
shift
|
|
actualcmd='eval "su-exec \"$user\" bash $args"'
|
|
;;
|
|
*)
|
|
actualcmd='eval "su-exec \"$user\" \"$composer\" $args"'
|
|
args="$action${args:+ $args}"
|
|
;;
|
|
esac
|
|
setx args=qvals $args "$@"
|
|
|
|
local -a basecmd setupscript runscript cmd
|
|
basecmd=(
|
|
-e user="$user"
|
|
-e group="$group"
|
|
-e projdir="$projdir"
|
|
-e setup="$setup"
|
|
-e setup_image="$setup_image"
|
|
-e composer="$composer"
|
|
-e args="$args"
|
|
)
|
|
eval "host_mappings=($host_mappings)"
|
|
for host_mapping in "${host_mappings[@]}"; do
|
|
basecmd+=(--add-host "$host_mapping")
|
|
done
|
|
basecmd+=(-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 "$setup" ]; then
|
|
local project_name container_name ctid
|
|
local setup_image="$setup_image"
|
|
|
|
# lancement dans un container docker à préparer
|
|
[ -n "$project_name" ] || setx project_name=get_project_name
|
|
setx container_name=get_container_name "$project_name"
|
|
[ -n "$setup_image" ] || setup_image="dkbuild_composer_${container_name}_image"
|
|
|
|
# vérifier l'existence de l'image
|
|
setx ctid=docker image ls --format '{{.ID}}' "$setup_image"
|
|
|
|
# créer le container le cas échéant
|
|
if [ -z "$ctid" ]; then
|
|
estep "Création de l'image $setup_image à partir de $image"
|
|
cmd=(
|
|
docker create -it --name "${setup_image}_tmpct"
|
|
"${basecmd[@]}"
|
|
"$image"
|
|
bash -c "$setupscript"
|
|
)
|
|
setx ctid="${cmd[@]}" &&
|
|
docker container start -ai "$ctid" &&
|
|
docker container commit "$ctid" "$setup_image" &&
|
|
docker container rm "$ctid" || die
|
|
fi
|
|
|
|
# prendre comme image le container créé
|
|
image="$setup_image"
|
|
fi
|
|
|
|
case "$action" in
|
|
rshell) estep "Lancement d'un shell root (avec l'image $image)";;
|
|
shell) estep "Lancement d'un shell utilisateur (avec l'image $image)";;
|
|
*) estep "composer $action (avec l'image $image)";;
|
|
esac
|
|
cmd=(
|
|
docker run -it --rm
|
|
"${basecmd[@]}"
|
|
"$image"
|
|
bash -c "$runscript"
|
|
)
|
|
"${cmd[@]}"
|
|
}
|
|
function composer() {
|
|
edebug "composer $(qvals "$@")"
|
|
[ $# -eq 0 ] && return 0
|
|
|
|
local action destdir
|
|
[[ "$1" != *=* ]] && { destdir="$1"; shift; }
|
|
[[ "$1" != *=* ]] && { action="$1"; shift; }
|
|
|
|
[ -n "$destdir" ] || destdir=.
|
|
[ -d "$destdir" ] || die "composer: $destdir: répertoire introuvable"
|
|
local cwd="$(pwd)"
|
|
cd "$destdir" || die
|
|
|
|
[ -n "$action" ] || action=install
|
|
if [ "$action" == none ]; then
|
|
cd "$cwd"
|
|
return
|
|
fi
|
|
|
|
local build="${DEFAULTS[build_build]-1}"
|
|
local args
|
|
case "$PROFILE" in
|
|
prod|test) args="${DEFAULTS[composer_args]---no-dev -o}";;
|
|
*) args="${DEFAULTS[composer_args]}";;
|
|
esac
|
|
local php="${DEFAULTS[composer_php]}"
|
|
local php_max="${DEFAULTS[composer_php-max]}"
|
|
local image="${DEFAULTS[composer_image]}"
|
|
local machine="${DEFAULTS[composer_machine]}"
|
|
local host_mappings="${DEFAULTS[composer_host-mappings]-__UNDEFINED__}"
|
|
[ "$host_mappings" == __UNDEFINED__ ] && host_mappings="${DEFAULTS[docker_host-mappings]}"
|
|
local composer="${DEFAULTS[composer_composer]}"
|
|
local setup="${DEFAULTS[composer_setup]}"
|
|
local setup_image="${DEFAULTS[composer_setup-image]}"
|
|
local project_name="${DEFAULTS[composer_project-name]}"
|
|
if [ -f "$destdir/.composer.yaml" ]; then
|
|
eval "$(
|
|
COMPOSER_PHP=
|
|
COMPOSER_PHP_MAX=
|
|
COMPOSER_IMAGE="$COMPOSER_IMAGE"
|
|
COMPOSER_SETUP=
|
|
COMPOSER_SETUP_IMAGE=
|
|
eval "$(<"$destdir/.composer.yaml" grep ^composer_ |
|
|
sed 's/^composer_php_min: /COMPOSER_PHP=/
|
|
s/^composer_php_max: /COMPOSER_PHP_MAX=/
|
|
s/^composer_registry: /registry=/
|
|
s/^composer_image: \(.*\)/COMPOSER_IMAGE="${registry:-$REGISTRY}\/\1"/
|
|
s/^composer_setup: /COMPOSER_SETUP=/
|
|
s/^composer_setup_image: /COMPOSER_SETUP_IMAGE=/')"
|
|
[ -z "$php" ] && echo_setv php="$COMPOSER_PHP"
|
|
[ -z "$php_max" ] && echo_setv php_max="$COMPOSER_PHP_MAX"
|
|
[ -z "$image" ] && echo_setv image="$COMPOSER_IMAGE"
|
|
[ -z "$setup" ] && echo_setv setup="$COMPOSER_SETUP"
|
|
[ -z "$setup_image" ] && echo_setv setup_image="$COMPOSER_SETUP_IMAGE"
|
|
)"
|
|
elif [ -f "$destdir/.composer.conf" ]; then
|
|
eval "$(
|
|
COMPOSER_PHP=
|
|
COMPOSER_PHP_MAX=
|
|
COMPOSER_IMAGE="$COMPOSER_IMAGE"
|
|
COMPOSER_MACHINE=-u
|
|
COMPOSER_CMD=
|
|
COMPOSER_SETUP=
|
|
COMPOSER_SETUP_IMAGE=
|
|
source "$destdir/.composer.conf"
|
|
[ -z "$php" ] && echo_setv php="$COMPOSER_PHP"
|
|
[ -z "$php_max" ] && echo_setv php_max="$COMPOSER_PHP_MAX"
|
|
[ -z "$image" ] && echo_setv image="$COMPOSER_IMAGE"
|
|
[ -z "$machine" ] && echo_setv machine="$COMPOSER_MACHINE"
|
|
[ -z "$composer" ] && echo_setv composer="$COMPOSER_CMD"
|
|
[ -z "$setup" ] && echo_setv setup="$COMPOSER_SETUP"
|
|
[ -z "$setup_image" ] && echo_setv setup_image="$COMPOSER_SETUP_IMAGE"
|
|
)"
|
|
fi
|
|
|
|
while [ $# -gt 0 ]; do
|
|
case "$1" in
|
|
build) build=1;;
|
|
build=*) build="${1#build=}";;
|
|
args=*) args="${1#args=}";;
|
|
php=*) php="${1#php=}";;
|
|
php-max=*) php_max="${1#php-max=}";;
|
|
image=*) image="${1#image=}";;
|
|
machine=*) machine="${1#machine=}";;
|
|
host-mappings=*) host_mappings="${1#host-mappings=}";;
|
|
composer=*) composer="${1#composer=}";;
|
|
setup=*) setup="${1#setup=}";;
|
|
setup-image=*) setup_image="${1#setup-image=}";;
|
|
project-name=*) project_name="${1#project-name=}";;
|
|
*=*) ewarn "composer: $1: argument ignoré";;
|
|
*) break;;
|
|
esac
|
|
shift
|
|
done
|
|
|
|
if [ -z "$build" ]; then
|
|
cd "$cwd"
|
|
return
|
|
fi
|
|
|
|
if [ "$php" != force -a "$php" != any ]; then
|
|
# Si php n'est pas disponible dans le PATH, forcer l'utilisation de
|
|
# l'image
|
|
progexists php || php=force
|
|
fi
|
|
|
|
local use_image
|
|
if [ "$php" == force -o "$php" == any ]; then
|
|
use_image=1
|
|
elif [ "$php" == none -o "$php" == system ]; then
|
|
php=none
|
|
use_image=
|
|
elif [ -n "$php_max" -a "$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);
|
|
' -- "$php_max"
|
|
case $? in
|
|
0) use_image=1;;
|
|
1) use_image=;;
|
|
*) ewarn "Erreur lors du lancement de PHP: est-il installé? Sinon, utilisez php=any";;
|
|
esac
|
|
fi
|
|
if [ -n "$use_image" -o "$php" == none ]; then
|
|
: # ok, on a déjà décidé
|
|
elif [ -z "$php" ]; then
|
|
# pas de version minimum, tester simplement la valeur de image
|
|
[ "$image" != none ] && 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);
|
|
' -- "$php"
|
|
case $? in
|
|
0) use_image=1;;
|
|
1) use_image=;;
|
|
*) ewarn "Erreur lors du lancement de PHP: est-il installé? Sinon, utilisez php=any";;
|
|
esac
|
|
fi
|
|
|
|
if [ -n "$use_image" ]; then
|
|
if [ -z "$image" ]; then
|
|
# Si l'image n'est pas définie, calculer une valeur par défaut à
|
|
# partir REGISTRY et DIST
|
|
image="$(get_default_phpbuilder_image)"
|
|
fi
|
|
local orig_machine
|
|
[ "$image" != none ] || die "Vous devez spécifier l'image à utiliser pour composer"
|
|
if [ -n "$machine" -a "$machine" != current -a "$DOCKER_MACHINE_NAME" != "$machine" ]; then
|
|
orig_machine="$DOCKER_MACHINE_NAME"
|
|
set_machine "$machine"
|
|
fi
|
|
_docker_composer "$@"
|
|
if [ -n "$_orig_machine" ]; then
|
|
set_machine "$orig_machine"
|
|
fi
|
|
else
|
|
_local_composer "$@"
|
|
fi
|
|
|
|
# restaurer le répertoire courant
|
|
cd "$cwd"
|
|
}
|
|
function _local_mvn() {
|
|
if [ -n "$java" ]; then
|
|
urequire java
|
|
select_java_exact "$java" || die "mvn: Java $java introuvable"
|
|
export MVN_JAVA_VERSION="$java"
|
|
fi
|
|
|
|
case "$action" in
|
|
rootshell|rshell|rootbash|rbash)
|
|
shift
|
|
estep "Lancement d'un shell root"
|
|
sudo bash "$@"
|
|
return $?
|
|
;;
|
|
usershell|shell|userbash|bash)
|
|
shift
|
|
estep "Lancement d'un shell utilisateur"
|
|
bash "$@"
|
|
return $?
|
|
;;
|
|
java)
|
|
shift
|
|
estep "java"
|
|
java "$@"
|
|
;;
|
|
*)
|
|
estep "mvn $action"
|
|
|
|
[ -n "$mvn" ] || setx mvn=which mvn 2>/dev/null
|
|
[ -n "$mvn" ] || die "mvn: commande introuvable"
|
|
|
|
set -- "$action" $args "$@"
|
|
case "$1" in
|
|
install) set clean package install "${@:2}";;
|
|
package) set clean package "${@:2}";;
|
|
package_only) set package "${@:2}";;
|
|
esac
|
|
"$mvn" "$@"
|
|
esac
|
|
}
|
|
function _docker_mvn() {
|
|
local user group projdir actualcmd
|
|
setx user=id -un; setx user=getent passwd "$user"
|
|
setx group=id -gn; setx group=getent group "$group"
|
|
setx projdir=pwd
|
|
case "$action" in
|
|
rootshell|rshell|rootbash|rbash)
|
|
action=rshell
|
|
shift
|
|
actualcmd='eval "bash $args"'
|
|
;;
|
|
usershell|shell|userbash|bash)
|
|
action=shell
|
|
shift
|
|
actualcmd='eval "su-exec \"$user\" bash $args"'
|
|
;;
|
|
java)
|
|
shift
|
|
actualcmd='eval "su-exec \"$user\" java $args"'
|
|
;;
|
|
*)
|
|
actualcmd='eval "su-exec \"$user\" \"$mvn\" $args"'
|
|
|
|
set -- "$action" $args "$@"
|
|
case "$1" in
|
|
install) set clean package install "${@:2}";;
|
|
package) set clean package "${@:2}";;
|
|
package_only) set package "${@:2}";;
|
|
esac
|
|
args=
|
|
;;
|
|
esac
|
|
setx args=qvals $args "$@"
|
|
|
|
local -a basecmd setupscript runscript cmd
|
|
basecmd=(
|
|
-e user="$user"
|
|
-e group="$group"
|
|
-e projdir="$projdir"
|
|
-e setup="$setup"
|
|
-e setup_image="$setup_image"
|
|
-e mvn="$mvn"
|
|
-e args="$args"
|
|
${java:+-e JAVA="$java"}
|
|
)
|
|
eval "host_mappings=($host_mappings)"
|
|
for host_mapping in "${host_mappings[@]}"; do
|
|
basecmd+=(--add-host "$host_mapping")
|
|
done
|
|
basecmd+=(-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%%:*}"
|
|
|
|
[ -n "$mvn" ] || mvn=mvn
|
|
|
|
cd "$projdir"
|
|
'"$actualcmd"
|
|
|
|
if [ -n "$setup" ]; then
|
|
local project_name container_name ctid
|
|
local setup_image="$setup_image"
|
|
|
|
# lancement dans un container docker à préparer
|
|
[ -n "$project_name" ] || setx project_name=get_project_name
|
|
setx container_name=get_container_name "$project_name"
|
|
[ -n "$setup_image" ] || setup_image="dkbuild_maven_${container_name}_image"
|
|
|
|
# vérifier l'existence de l'image
|
|
setx ctid=docker image ls --format '{{.ID}}' "$setup_image"
|
|
|
|
# créer le container le cas échéant
|
|
if [ -z "$ctid" ]; then
|
|
estep "Création de l'image $setup_image à partir de $image"
|
|
cmd=(
|
|
docker create -it --name "${setup_image}_tmpct"
|
|
"${basecmd[@]}"
|
|
"$image"
|
|
bash -c "$setupscript"
|
|
)
|
|
setx ctid="${cmd[@]}" &&
|
|
docker container start -ai "$ctid" &&
|
|
docker container commit "$ctid" "$setup_image" &&
|
|
docker container rm "$ctid" || die
|
|
fi
|
|
|
|
# prendre comme image le container créé
|
|
image="$setup_image"
|
|
fi
|
|
|
|
case "$action" in
|
|
rshell) estep "Lancement d'un shell root (avec l'image $image)";;
|
|
shell) estep "Lancement d'un shell utilisateur (avec l'image $image)";;
|
|
java) estep "java (avec l'image $image)";;
|
|
*) estep "mvn $action (avec l'image $image)";;
|
|
esac
|
|
cmd=(
|
|
docker run -it --rm
|
|
"${basecmd[@]}"
|
|
"$image"
|
|
bash -c "$runscript"
|
|
)
|
|
"${cmd[@]}"
|
|
}
|
|
function mvn() {
|
|
edebug "mvn $(qvals "$@")"
|
|
[ $# -eq 0 ] && return 0
|
|
|
|
local action destdir
|
|
[[ "$1" != *=* ]] && { destdir="$1"; shift; }
|
|
[[ "$1" != *=* ]] && { action="$1"; shift; }
|
|
|
|
[ -n "$destdir" ] || destdir=.
|
|
[ -d "$destdir" ] || die "mvn: $destdir: répertoire introuvable"
|
|
local cwd="$(pwd)"
|
|
cd "$destdir" || die
|
|
|
|
[ -n "$action" ] || action=package
|
|
if [ "$action" == none ]; then
|
|
cd "$cwd"
|
|
return
|
|
fi
|
|
|
|
local build="${DEFAULTS[build_build]-1}"
|
|
local args="${DEFAULTS[mvn_args]}"
|
|
local java="${DEFAULTS[mvn_java]}"
|
|
local image="${DEFAULTS[mvn_image]}"
|
|
local machine="${DEFAULTS[mvn_machine]}"
|
|
local host_mappings="${DEFAULTS[mvn_host-mappings]-__UNDEFINED__}"
|
|
[ "$host_mappings" == __UNDEFINED__ ] && host_mappings="${DEFAULTS[docker_host-mappings]}"
|
|
local mvn="${DEFAULTS[mvn_mvn]}"
|
|
local setup="${DEFAULTS[mvn_setup]}"
|
|
local setup_image="${DEFAULTS[mvn_setup-image]}"
|
|
local project_name="${DEFAULTS[mvn_project-name]}"
|
|
if [ -f "$destdir/.maven.conf" ]; then
|
|
eval "$(
|
|
MAVEN_JAVA=
|
|
MAVEN_IMAGE="$MAVEN_IMAGE"
|
|
MAVEN_MACHINE=-u
|
|
MAVEN_CMD=
|
|
MAVEN_SETUP=
|
|
MAVEN_SETUP_IMAGE=
|
|
source "$destdir/.maven.conf"
|
|
[ -z "$java" ] && echo_setv java="$MAVEN_JAVA"
|
|
[ -z "$image" ] && echo_setv image="$MAVEN_IMAGE"
|
|
[ -z "$machine" ] && echo_setv machine="$MAVEN_MACHINE"
|
|
[ -z "$mvn" ] && echo_setv mvn="$MAVEN_CMD"
|
|
[ -z "$setup" ] && echo_setv setup="$MAVEN_SETUP"
|
|
[ -z "$setup_image" ] && echo_setv setup_image="$MAVEN_SETUP_IMAGE"
|
|
)"
|
|
fi
|
|
|
|
while [ $# -gt 0 ]; do
|
|
case "$1" in
|
|
build) build=1;;
|
|
build=*) build="${1#build=}";;
|
|
args=*) args="${1#args=}";;
|
|
java=*) java="${1#java=}";;
|
|
image=*) image="${1#image=}";;
|
|
machine=*) machine="${1#machine=}";;
|
|
host-mappings=*) host_mappings="${1#host-mappings=}";;
|
|
mvn=*) mvn="${1#mvn=}";;
|
|
setup=*) setup="${1#setup=}";;
|
|
setup-image=*) setup_image="${1#setup-image=}";;
|
|
project-name=*) project_name="${1#project-name=}";;
|
|
*=*) ewarn "mvn: $1: argument ignoré";;
|
|
*) break;;
|
|
esac
|
|
shift
|
|
done
|
|
|
|
if [ -z "$build" ]; then
|
|
cd "$cwd"
|
|
return
|
|
fi
|
|
|
|
local version
|
|
case "$action" in
|
|
java*)
|
|
version="${action#java}"
|
|
[ -n "$version" ] && java="$version"
|
|
set java "${@:2}"
|
|
;;
|
|
esac
|
|
|
|
if [ "$java" != force -a "$java" != any ]; then
|
|
# Si Java et mvn ne sont pas disponibles dans le PATH, forcer
|
|
# l'utilisation de l'image
|
|
progexists java || java=force
|
|
progexists mvn || java=force
|
|
fi
|
|
|
|
local use_image
|
|
if [ "$java" == force -o "$java" == any ]; then
|
|
java=
|
|
use_image=1
|
|
elif [ "$java" == none -o "$java" == system ]; then
|
|
java=
|
|
use_image=
|
|
elif [ -n "$image" -a "$image" != none ]; then
|
|
use_image=1
|
|
fi
|
|
|
|
if [ -n "$use_image" ]; then
|
|
if [ -z "$image" ]; then
|
|
# Si l'image n'est pas définie, calculer une valeur par défaut à
|
|
# partir REGISTRY et DIST
|
|
image="$(get_default_javabuilder_image)"
|
|
fi
|
|
local orig_machine
|
|
[ "$image" != none ] || die "Vous devez spécifier l'image à utiliser pour mvn"
|
|
if [ -n "$machine" -a "$machine" != current -a "$DOCKER_MACHINE_NAME" != "$machine" ]; then
|
|
orig_machine="$DOCKER_MACHINE_NAME"
|
|
set_machine "$machine"
|
|
fi
|
|
_docker_mvn "$@"
|
|
if [ -n "$_orig_machine" ]; then
|
|
set_machine "$orig_machine"
|
|
fi
|
|
else
|
|
_local_mvn "$@"
|
|
fi
|
|
|
|
# restaurer le répertoire courant
|
|
cd "$cwd"
|
|
}
|
|
function run() {
|
|
edebug "run $(qvals "$@")"
|
|
[ $# -eq 0 ] && return 0
|
|
|
|
local cmd="$1"; shift
|
|
if [ "${cmd#/}" != "$cmd" ]; then :
|
|
elif [ "${cmd#./}" != "$cmd" ]; then :
|
|
elif [ "${cmd#../}" != "$cmd" ]; then :
|
|
else
|
|
local abscmd
|
|
setx abscmd=which "$cmd" 2>/dev/null
|
|
[ -n "$abscmd" ] || die "run: $cmd: commande introuvable"
|
|
edebug "'$cmd' resolved as '$abscmd'"
|
|
cmd="$abscmd"
|
|
fi
|
|
"$cmd" "$@" || die
|
|
}
|
|
function runb() {
|
|
local build="${DEFAULTS[build_build]-1}"
|
|
if [ -z "$build" ]; then
|
|
[ $# -eq 0 ] && return 1 || return 0
|
|
fi
|
|
run "$@"
|
|
}
|
|
function call() {
|
|
edebug "call $(qvals "$@")"
|
|
[ $# -eq 0 ] && return 0
|
|
|
|
"$@"
|
|
}
|
|
function callb() {
|
|
local build="${DEFAULTS[build_build]-1}"
|
|
if [ -z "$build" ]; then
|
|
[ $# -eq 0 ] && return 1 || return 0
|
|
fi
|
|
call "$@"
|
|
}
|
|
function dkbuild() {
|
|
edebug "dkbuild $(qvals "$@")"
|
|
|
|
"$SELF" "$@" || die
|
|
}
|
|
}
|
|
|
|
##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
## init
|
|
|
|
function templates_action() {
|
|
declare -A TEMPLATES
|
|
[ -f "$TEMPLATEDIR/templates.conf" ] && source "$TEMPLATEDIR/templates.conf"
|
|
|
|
etitle "Templates valides"
|
|
local -a templates
|
|
setx -a templates=list_dirs "$TEMPLATEDIR"
|
|
for template in "${templates[@]}"; do
|
|
[ "$template" == default ] && continue
|
|
desc="${TEMPLATES[$template]}"
|
|
estep "$template${desc:+ - "$desc"}"
|
|
done
|
|
eend
|
|
}
|
|
|
|
##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
## init
|
|
|
|
function init_action() {
|
|
eval "$SHARED_LOCALS1"
|
|
local template; local -a defaultvars addvars
|
|
local -a args; args=(
|
|
"${SHARED_ARGS1[@]}"
|
|
-t:,--template: template=
|
|
-v:,--var: '$addvars+=("$value_")'
|
|
-n:,--name: '$addvars+=(name="$value_")'
|
|
-g:,--group: '$addvars+=(group="$value_")'
|
|
)
|
|
parse_args "$@"; set -- "${args[@]}"
|
|
|
|
defaultvars=(name=name group=group)
|
|
[ $# -gt 0 ] && { [ -n "$1" ] && PROJDIR="$1"; shift; }
|
|
[ $# -gt 0 ] && { [ -n "$1" ] && addvars+=(name="$1"); shift; }
|
|
[ $# -gt 0 ] && { [ -n "$1" ] && addvars+=(group="$1"); shift; }
|
|
|
|
declare -A vars
|
|
local name value
|
|
for name in "${defaultvars[@]}" "${addvars[@]}"; do
|
|
if [[ "$name" == *=* ]]; then
|
|
value="${name#*=}"
|
|
name="${name%%=*}"
|
|
else
|
|
value=
|
|
fi
|
|
name="${name^^}"
|
|
vars[$name]="$value"
|
|
done
|
|
|
|
[ -n "$template" ] || template=default
|
|
[ -d "$TEMPLATEDIR/$template" ] || die "$template: template introuvable"
|
|
|
|
[ -n "$PROJDIR" ] || PROJDIR=.
|
|
setx PROJDIR=abspath "$PROJDIR"
|
|
if [ ! -d "$PROJDIR" ]; then
|
|
ask_yesno "Voulez-vous créer le nouveau projet $(ppath "$PROJDIR")?" O || die
|
|
fi
|
|
mkdir -p "$PROJDIR"
|
|
|
|
local sedscript
|
|
for name in "${!vars[@]}"; do
|
|
value="${vars[$name]}"
|
|
[ -n "$sedscript" ] && sedscript="$sedscript; "
|
|
sedscript="${sedscript}s/${name//\//\\\/}/${value//\//\\\/}/g"
|
|
done
|
|
|
|
local src mode dest link
|
|
template="$TEMPLATEDIR/$template"
|
|
enote "Initialisation de $(ppath "$PROJDIR")"
|
|
find "$template/" -type f -o -type l | while read src; do
|
|
dest="$PROJDIR/${src#$template/}"
|
|
if [ -L "$src" ]; then
|
|
setx link=readlink "$src"
|
|
if [ -L "$dest" ]; then
|
|
if [ "$(readlink "$dest")" != "$link" ]; then
|
|
estep "${src#$template/} [link, updated]"
|
|
ln -sf "$link" "$dest"
|
|
else
|
|
edebug "${src#$template/} [exists, ignored]"
|
|
fi
|
|
elif [ -e "$dest" ]; then
|
|
estepe "${src#$template/} [destination is not a link]"
|
|
else
|
|
estep "${src#$template/} [link]"
|
|
ln -s "$link" "$dest"
|
|
fi
|
|
elif [ -f "$dest" ]; then
|
|
edebug "${src#$template/} [exists, ignored]"
|
|
else
|
|
estep "${src#$template/}"
|
|
mkdirof "$dest"
|
|
sed <"$src" >"$dest" "$sedscript"
|
|
setx mode=stat -c %a "$src"
|
|
chmod "$mode" "$dest"
|
|
fi
|
|
done
|
|
}
|
|
|
|
##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
## build
|
|
|
|
function build_action() {
|
|
eval "$SHARED_LOCALS1; $SHARED_LOCALS2"
|
|
local action=build
|
|
local machine
|
|
local clean_update clean_opt=-X
|
|
local clone_src_only update_src_only update_src sync_src
|
|
local build no_cache progress pull_image
|
|
local push_image
|
|
local -a args; args=(
|
|
"${SHARED_ARGS1[@]}" "${SHARED_ARGS2[@]}"
|
|
-m:,--machine: machine=
|
|
-u,--clean-update clean_update=1
|
|
-X,--clean-ignored clean_opt=-X
|
|
-x,--clean-untracked clean_opt=-x
|
|
--clone-src-only clone_src_only=1
|
|
--update-src-only update_src_only=1
|
|
--update-src update_src=1
|
|
--no-update-src update_src=no
|
|
-w,--update-devel-src update_src=devel
|
|
-s,--sync-src sync_src=1
|
|
--no-sync-src sync_src=no
|
|
-b,--build build=1
|
|
--no-cache no_cache=1
|
|
--plain-output progress=plain
|
|
-U,--pull-image pull_image=1
|
|
-p,--push-image push_image=1
|
|
)
|
|
parse_args "$@"; set -- "${args[@]}"
|
|
|
|
if [ -n "$clone_src_only" ]; then
|
|
action=clone_src
|
|
elif [ -n "$update_src_only" ]; then
|
|
action=update_src
|
|
else
|
|
action=build
|
|
if [ -z "$clean_update" -a -z "$sync_src" -a -z "$build" -a -z "$push_image" ]; then
|
|
sync_src=1
|
|
build=1
|
|
fi
|
|
if [ -n "$build" ]; then
|
|
[ -n "$update_src" ] || update_src=1
|
|
[ "$update_src" == no ] && update_src=
|
|
else
|
|
update_src=
|
|
fi
|
|
[ "$sync_src" == no ] && sync_src=
|
|
fi
|
|
|
|
edebug "build_action"
|
|
set_machine "$machine"
|
|
|
|
ensure_projdir
|
|
resolve_dists_profiles
|
|
setenv "${TMPENVIRON[@]}"
|
|
setarg "${TMPARGS[@]}"
|
|
setarg "$@"
|
|
|
|
if [ -n "$clean_update" ]; then
|
|
edebug "clean"
|
|
_clean_git_clean -f || die
|
|
|
|
edebug "update"
|
|
git pull || die
|
|
|
|
edebug "sync"
|
|
[ -n "$build" ] && sync_src=1
|
|
fi
|
|
|
|
case "$action" in
|
|
clone_src)
|
|
die "Pas encore implémenté" #XXX
|
|
;;
|
|
update_src)
|
|
die "Pas encore implémenté" #XXX
|
|
;;
|
|
build)
|
|
default checkout checkout="$update_src"
|
|
default copy copy="$sync_src"
|
|
default build build="$build" ${no_cache:+no-cache} ${pull_image:+pull} ${push_image:+push}
|
|
[ $# -gt 0 ] && default build "$@"
|
|
define_functions_cmd
|
|
|
|
foreach_dists_profiles _build_each _build_before _build_after
|
|
;;
|
|
esac
|
|
}
|
|
|
|
function _build_before() {
|
|
PREV_DIST=
|
|
PREV_PROFILE=
|
|
}
|
|
function _build_each() {
|
|
if [ -n "$DIST" -a "$DIST-$DVERSION" != "$PREV_DIST" ]; then
|
|
[ -n "$PREV_PROFILE" ] && eend
|
|
PREV_PROFILE=
|
|
|
|
[ -n "$PREV_DIST" ] && eend
|
|
PREV_DIST="$DIST-$DVERSION"
|
|
etitle "Distribution ${DVERSION:+$DVERSION-}$DIST"
|
|
fi
|
|
if [ -n "$PROFILE" -a "$PROFILE-$PVERSION" != "$PREV_PROFILE" ]; then
|
|
PREV_PROFILE="$PROFILE-$PVERSION"
|
|
etitle "Profil ${PVERSION:+$PVERSION-}$PROFILE"
|
|
fi
|
|
|
|
load_dkbuild
|
|
if [ -n "$AUTOBUILD" ]; then
|
|
if [ -f docker-compose.yml ]; then
|
|
cbuild
|
|
else
|
|
build
|
|
fi
|
|
fi
|
|
}
|
|
function _build_after() {
|
|
if [ -n "$PREV_PROFILE" ]; then eend; fi
|
|
if [ -n "$PREV_DIST" ]; then eend; fi
|
|
}
|
|
|
|
##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
## clean
|
|
|
|
function _clean_git_clean() {
|
|
LANG=C git clean -d $clean_opt "$@" |
|
|
grep -vE '^(Would skip|Skipping) ' |
|
|
sed -r 's/^Would remove //'
|
|
}
|
|
function _clean_git_status() {
|
|
git status --porcelain --ignored |
|
|
grep '^!! ' |
|
|
sed 's/^...//'
|
|
}
|
|
|
|
function clean_action() {
|
|
eval "$SHARED_LOCALS1"
|
|
local clean_opt=-X all=
|
|
local -a args; args=(
|
|
"${SHARED_ARGS1[@]}"
|
|
-X,--ignored clean_opt=-X
|
|
-x,--untracked clean_opt=-x
|
|
-a,--all all=1
|
|
)
|
|
parse_args "$@"; set -- "${args[@]}"
|
|
|
|
[ -n "$all" ] && clean_opt=-x
|
|
|
|
edebug "clean_action"
|
|
ensure_projdir
|
|
|
|
local cleans
|
|
setx cleans=_clean_git_clean -n "$@"
|
|
if [ -n "$cleans" ]; then
|
|
if check_interaction -c; then
|
|
einfo "via git clean"
|
|
eecho "$cleans"
|
|
ask_yesno "Voulez-vous supprimer ces fichiers?" O || die
|
|
fi
|
|
|
|
_clean_git_clean -f "$@" || die
|
|
fi
|
|
|
|
if [ -n "$all" ]; then
|
|
setx cleans=_clean_git_status
|
|
if [ -n "$cleans" ]; then
|
|
if check_interaction -c; then
|
|
einfo "via git status"
|
|
eecho "$cleans"
|
|
ask_yesno "Voulez-vous supprimer ces fichiers supplémentaires?" O || die
|
|
fi
|
|
|
|
sed 's/^/Removing /' <<<"$cleans"
|
|
eval "cleans=($cleans);"' rm -rf "${cleans[@]}"' || die
|
|
fi
|
|
fi
|
|
}
|
|
|
|
##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
## composer
|
|
|
|
function composer_action() {
|
|
local -a args; args=(
|
|
)
|
|
parse_args "$@"; set -- "${args[@]}"
|
|
|
|
[ $# -gt 0 ] || set .
|
|
|
|
edebug "composer_action"
|
|
|
|
define_functions_cmd
|
|
composer "$@"
|
|
}
|
|
|
|
##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
## mvn
|
|
|
|
function mvn_action() {
|
|
local -a args; args=(
|
|
)
|
|
parse_args "$@"; set -- "${args[@]}"
|
|
|
|
[ $# -gt 0 ] || set .
|
|
|
|
edebug "mvn_action"
|
|
|
|
define_functions_cmd
|
|
mvn "$@"
|
|
}
|
|
|
|
##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
## dump
|
|
|
|
function dump_action() {
|
|
eval "$SHARED_LOCALS1; $SHARED_LOCALS2"
|
|
local machine
|
|
local -a args; args=(
|
|
"${SHARED_ARGS1[@]}" "${SHARED_ARGS2[@]}"
|
|
-m:,--machine: machine=
|
|
)
|
|
parse_args "$@"; set -- "${args[@]}"
|
|
|
|
edebug "dump_action"
|
|
set_machine "$machine"
|
|
|
|
ensure_projdir
|
|
resolve_dists_profiles
|
|
setenv "${TMPENVIRON[@]}"
|
|
setarg "${TMPARGS[@]}"
|
|
setarg "$@"
|
|
|
|
foreach_dists_profiles _dump_each _dump_before _dump_after
|
|
}
|
|
|
|
function _dump_before() {
|
|
PREV_DIST=
|
|
PREV_PROFILE=
|
|
}
|
|
function _dump_each() {
|
|
if [ -n "$DIST" -a "$DIST-$DVERSION" != "$PREV_DIST" ]; then
|
|
[ -n "$PREV_PROFILE" ] && eend
|
|
PREV_PROFILE=
|
|
|
|
[ -n "$PREV_DIST" ] && eend
|
|
PREV_DIST="$DIST-$DVERSION"
|
|
etitle "Distribution ${DVERSION:+$DVERSION-}$DIST"
|
|
fi
|
|
if [ -n "$PROFILE" -a "$PROFILE-$PVERSION" != "$PREV_PROFILE" ]; then
|
|
PREV_PROFILE="$PROFILE-$PVERSION"
|
|
etitle "Profil ${PVERSION:+$PVERSION-}$PROFILE"
|
|
fi
|
|
|
|
load_dkbuild
|
|
|
|
etitle "Variables d'environnement"
|
|
for name in "${!ENVIRON[@]}"; do
|
|
estep "$name=${ENVIRON[$name]}"
|
|
done
|
|
eend
|
|
|
|
etitle "Variables de build"
|
|
for name in "${!ARGS[@]}"; do
|
|
estep "$name=${ARGS[$name]}"
|
|
done
|
|
eend
|
|
|
|
etitle "Valeurs par défaut"
|
|
for name in "${!DEFAULTS[@]}"; do
|
|
estep "$name=${DEFAULTS[$name]}"
|
|
done
|
|
eend
|
|
}
|
|
function _dump_after() {
|
|
if [ -n "$PREV_PROFILE" ]; then eend; fi
|
|
if [ -n "$PREV_DIST" ]; then eend; fi
|
|
}
|
|
|
|
##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
##
|
|
|
|
# faire une copie de l'environnement original
|
|
load_environ
|
|
|
|
# si aucune action n'est spécifiée, il faut inférer build pour que ses options
|
|
# soient reconnues
|
|
args=()
|
|
while [ $# -gt 0 ]; do
|
|
case "$1" in
|
|
--help) args+=("$1"); shift; continue;;
|
|
--hdk|--help-dkbuild) args+=("$1"); shift; continue;;
|
|
--href|--help-reference) args+=("$1"); shift; continue;;
|
|
--compose-v1) args+=("$1"); shift; continue;;
|
|
-*|*=*) # option quelconque: inférer build
|
|
args+=(build)
|
|
break
|
|
;;
|
|
*) # argument quelconque: on s'arrête ici
|
|
break
|
|
;;
|
|
esac
|
|
done
|
|
set -- "${args[@]}" "$@"
|
|
|
|
args=(+
|
|
--help '$exit_with display_help'
|
|
--hdk,--help-dkbuild '$exit_with display_help_dkbuild'
|
|
--href,--help-reference '$exit_with display_help_reference'
|
|
--compose-v1 '$DOCKER_COMPOSE=(docker-compose)'
|
|
)
|
|
parse_args "$@"; set -- "${args[@]}"
|
|
|
|
# aliases
|
|
case "$1" in
|
|
ci) set composer "$2" install "${@:3}";;
|
|
cu) set composer "$2" update "${@:3}";;
|
|
cr) set composer "$2" rshell "${@:3}";;
|
|
cs) set composer "$2" shell "${@:3}";;
|
|
mvr) set mvn "$2" rshell "${@:3}";;
|
|
mvs) set mvn "$2" shell "${@:3}";;
|
|
java) set mvn "$2" java "${@:3}";;
|
|
esac
|
|
|
|
# actions
|
|
action="${1:-build}"; shift
|
|
case "$action" in
|
|
templates|t) templates_action "$@";;
|
|
init|i|0) init_action "$@";;
|
|
build|b) build_action "$@";;
|
|
clean|k) clean_action "$@";;
|
|
composer|c) composer_action "$@";;
|
|
maven|mvn|m) mvn_action "$@";;
|
|
dump|d) dump_action "$@";;
|
|
*) die "$action: action invalide";;
|
|
esac
|