924 lines
		
	
	
		
			29 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			924 lines
		
	
	
		
			29 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
 | |
| 
 | |
| function display_help() {
 | |
|     uecho "$scriptname: outil pour faciliter l'utilisation de docker
 | |
| 
 | |
| USAGE
 | |
|     $scriptname CMDs...
 | |
| 
 | |
| COMMANDES
 | |
|     build [SERVICE]
 | |
|         Construire les images
 | |
|     push
 | |
|         Pousser les images vers le serveur
 | |
|     start, run [SERVICE]
 | |
|         Démarrer le(s) service(s)
 | |
|     stop [SERVICE]
 | |
|         Arrêter le(s) service(s)
 | |
|     up
 | |
|         Créer l'environnement, démarrer les services et suivre les logs de façon
 | |
|         interactive.
 | |
|     logs [SERVICE]
 | |
|         Afficher les logs
 | |
|     down
 | |
|         Arrêter les services et supprimer l'environnement
 | |
|     brd
 | |
|         Construire les images (comme avec build), démarrer les services et
 | |
|         suivre les logs de façon interactive (comme avec up). Dès que l'on
 | |
|         arrête l'affichage des logs avec Ctrl+C, arrêter les services et
 | |
|         supprimer l'environnement (comme avec down)
 | |
|     bs
 | |
|         Construire les images (comme avec build) puis démarrer les services
 | |
|         (comme avec start)
 | |
|     ip [SERVICE]
 | |
|         Afficher l'adresse IP interne du service
 | |
|     exec SERVICE COMMAND
 | |
|         Lancer la commande dans le container spécifié
 | |
|     systemd-unit
 | |
|         Générer une unité systemd qui démarre les services. A priori, ce n'est
 | |
|         nécessaire que si aucune politique de redémarrage n'a été définie.
 | |
|     ps
 | |
|         Afficher les containers en cours d'exécution
 | |
|     ls
 | |
|         Lister les images actuellement présentes
 | |
|     rm
 | |
|         Supprimer une image
 | |
|     prune
 | |
|         Supprimer les containers et les images inutilisées
 | |
| 
 | |
| OPTIONS générales
 | |
|     (ces options sont communes à toutes les commandes)
 | |
|     -d, --chdir PROJDIR
 | |
|     -p, --profile PROFILE
 | |
|     -P, --prod
 | |
|     -T, --test
 | |
|     -n, --fake
 | |
|     -j, --no-cache
 | |
|     -h, --host HOST
 | |
| 
 | |
| OPTIONS build
 | |
|     (ces options ne sont valides que pour les commandes build, brd, bs)
 | |
|     -g, --ug, --no-update-apps
 | |
|         ne pas mettre à jour les dépôts dépendants. ces dépôts sont définis dans
 | |
|         le fichier update-apps.conf qui a le format suivant:
 | |
|             DEFAULT_BRANCH=
 | |
|             APPS=()             # liste d'applications à mettre à jour
 | |
|             app_URL=            # url du dépôt
 | |
|             app_DEST=           # répertoire dans lequel faire le checkout
 | |
|             app_PROFILE_ORIGIN= # origine spécifique à un profil
 | |
|             app_PROFILE_BRANCH= # branche spécifique à un profil
 | |
|             app_ORIGIN=         # ou... origine par défaut de la branche
 | |
|             app_BRANCH=         # ou... branche par défaut
 | |
|             app_TYPE=           # type de projet (composer par défaut)
 | |
|             app_AFTER_UPDATE=() # liste de commandes à lancer après le checkout
 | |
|     -u, --uu, --update-apps-only
 | |
|         Ne faire que la mise à jour depuis les dépôts dépendants.
 | |
|     --uo, --update-apps-origin ORIGIN
 | |
|         Spécifier l'origine par défaut pour update-apps
 | |
|     --ub, --update-apps-branch BRANCH
 | |
|         Spécifier la branche par défaut pour update-apps
 | |
| 
 | |
| VARIABLES de update-apps.conf
 | |
|     ORIGIN
 | |
|         vaut 'origin' par défaut
 | |
|     BRANCH
 | |
|         vaut 'develop' par défaut
 | |
|     TYPE
 | |
|         vaut 'composer' par défaut si le fichier composer.json existe à la
 | |
|         racine du projet. sinon vaut 'inconnu' par défaut
 | |
|     AFTER_UPDATE
 | |
|         Cette variable est une liste de commandes à lancer après la maj du dépôt
 | |
|         - si le chemin est absolu ou relatif, lancer la commande telle quelle
 | |
|         - s'il n'y a pas de chemin, alors ce doit être le nom d'une fonction
 | |
|           existante auquel on enlève le préfixe update_apps_func_
 | |
| FONCTIONS de update-apps.conf
 | |
|     sqlmig [DESTDIR [SRCDIR]]
 | |
|         Copier les définitions des bases de données au format sqlmig de
 | |
|         SRCDIR/config/sqlmig vers DESTDIR/config/mariadb/sqlmig"
 | |
| }
 | |
| 
 | |
| function get_version() {
 | |
|     local GIT_DIR; unset GIT_DIR
 | |
|     if git rev-parse --git-dir >/dev/null 2>&1; then
 | |
|         local head commit tag
 | |
|         commit="$(git rev-list --tags --max-count=1 2>/dev/null)"
 | |
|         if [ -n "$commit" ]; then
 | |
|             tag="$(git describe --tags "$commit" 2>/dev/null)"
 | |
|             if [ -n "$tag" ]; then
 | |
|                 head="$(git rev-parse HEAD)"
 | |
|                 if [ "$commit" != "$head" ]; then
 | |
|                     echo "$tag-develop"
 | |
|                 else
 | |
|                     echo "$tag"
 | |
|                 fi
 | |
|                 return
 | |
|             fi
 | |
|         fi
 | |
|     elif [ -f VERSION.txt ]; then
 | |
|         cat VERSION.txt
 | |
|     fi
 | |
|     echo develop
 | |
| }
 | |
| 
 | |
| function docker_add_build_arg() {
 | |
|     eval "replace_build_args+=(--build-arg $1=\"$2\"); $1=\"$2\""
 | |
| }
 | |
| function docker_parse_build_args() {
 | |
|     cat "$1" |
 | |
|     grep -v '^#' |
 | |
|     grep -v '^$' |
 | |
|     sed -r 's/([^=]+)=(.*)/replace_build_args+=(--build-arg \1="\2"); \1="\2"/'
 | |
| }
 | |
| function docker_parse_env_args() {
 | |
|     [ -f .build.env ] && eval "$(docker_parse_build_args .build.env)"
 | |
|     [ -f build.env ] && eval "$(docker_parse_build_args build.env)"
 | |
|     [ -n "$PROFILE" -a -f ".build.$PROFILE.env" ] && eval "$(docker_parse_build_args ".build.$PROFILE.env")"
 | |
| }
 | |
| function docker_set_env_args() {
 | |
|     [ -f .build.env ] && source ./.build.env
 | |
|     [ -f build.env ] && source ./build.env
 | |
|     [ -n "$PROFILE" -a -f ".build.$PROFILE.env" ] && source "./.build.$PROFILE.env"
 | |
| }
 | |
| function docker_set_run_args() {
 | |
|     replace_run_args+=(--env-file "$1")
 | |
|     source "$1"
 | |
| }
 | |
| function docker_check_name() {
 | |
|     [ -n "$NAME" ] || die "Vous devez définir NAME dans .build.env"
 | |
| 
 | |
|     if [ "$1" == set_container_name ]; then
 | |
|         project_name="$NAME"
 | |
|         container_name="${project_name//[^a-zA-Z0-9_-]/}"
 | |
|         [ -n "$PROFILE" ] && container_name="${container_name}_$PROFILE"
 | |
|     fi
 | |
| }
 | |
| 
 | |
| function compose_set_env_args() {
 | |
|     replace_env_args+=(-f docker-compose.yml)
 | |
|     if [ -f docker-compose.override.yml ]; then
 | |
|         replace_env_args+=(-f docker-compose.override.yml)
 | |
|     fi
 | |
| 
 | |
|     local PROJECT_NAME= PROJECT_NAME_REMOVE_SUFFIX=.service PROJECT_NAME_ADD_PROFILE=1
 | |
|     [ -f .compose.env ] && source ./.compose.env
 | |
| 
 | |
|     [ -n "$PROJECT_NAME" ] || PROJECT_NAME="$(basename -- "$(pwd)")"
 | |
|     PROJECT_NAME="${PROJECT_NAME%$PROJECT_NAME_REMOVE_SUFFIX}"
 | |
| 
 | |
|     if [ -n "$PROFILE" ]; then
 | |
|         if [ -f "docker-compose.$PROFILE.yml" ]; then
 | |
|             replace_env_args+=(-f "docker-compose.$PROFILE.yml")
 | |
|         fi
 | |
|         [ -n "$COMPOSE_PROJECT_NAME" ] || COMPOSE_PROJECT_NAME="$PROJECT_NAME${PROJECT_NAME_ADD_PROFILE:+_${PROFILE}}"
 | |
|     else
 | |
|         [ -n "$COMPOSE_PROJECT_NAME" ] || COMPOSE_PROJECT_NAME="$PROJECT_NAME"
 | |
|     fi
 | |
|     export COMPOSE_PROJECT_NAME
 | |
| 
 | |
|     if [ "$1" == set_container_name ]; then
 | |
|         project_name="$PROJECT_NAME"
 | |
|         container_name="${project_name//[^a-zA-Z0-9_-]/}"
 | |
|         [ -n "$PROFILE" -a -n "$PROJECT_NAME_ADD_PROFILE" ] && container_name="${container_name}_$PROFILE"
 | |
|     fi
 | |
| }
 | |
| 
 | |
| function host_run() {
 | |
|     # lancer le script $2..@ sur l'hôte $1
 | |
|     # si $1 n'est pas défini ou est le nom de l'hôte local ou vaut 'localhost',
 | |
|     # lancer le script en local avec les droits root
 | |
|     # sinon, si docker-machine existe, l'hôte doit correspondre à la machine active
 | |
|     # sinon, lancer inconditionnellement le script sur l'hôte distant
 | |
|     local host="$1" script="$2"; shift; shift
 | |
|     if [ -n "$host" -a "$host" != localhost ]; then
 | |
|         if check_hostname "$host"; then
 | |
|             estep "Lancement de $script localement"
 | |
|             runscript_as_root "$script" "$@"
 | |
|         elif progexists docker-machine; then
 | |
|             local dm; setx dm=docker-machine active 2>/dev/null
 | |
|             if [ "${host%%.*}" == "$dm" ]; then
 | |
|                 estep "Copie du script vers root@$host"
 | |
|                 scp "$script" "root@$host:/tmp/tmp-dk-service-script" || die
 | |
|                 estep "Lancement du script à distance"
 | |
|                 local -a args; args=(/tmp/tmp-dk-service-script "$@")
 | |
|                 ssh -qt "root@$host" "$(qvals "${args[@]}"); rm -f /tmp/tmp-dk-service-script"
 | |
|             else
 | |
|                 ewarn "La machine active ($dm) n'est pas la destination ($host)"
 | |
|             fi
 | |
|         else
 | |
|             estep "Copie du script vers root@$host"
 | |
|             scp "$script" "root@$host:/tmp/tmp-dk-service-script" || die
 | |
|             estep "Lancement du script à distance"
 | |
|             local -a args; args=(/tmp/tmp-dk-service-script "$@")
 | |
|             ssh -qt "root@$host" "$(qvals "${args[@]}"); rm -f /tmp/tmp-dk-service-script"
 | |
|         fi
 | |
|     else
 | |
|         estep "Lancement de $script localement"
 | |
|         runscript_as_root "$script" "$@"
 | |
|     fi
 | |
| }
 | |
| function local_run() {
 | |
|     # lancer le script $2..@ sur l'hôte $1 uniquement si c'est l'hôte courant
 | |
|     local host="$1" script="$2"; shift; shift
 | |
|     if [ -n "$host" ]; then
 | |
|         if ! check_hostname "$host"; then
 | |
|             eerror "Cette commande doit obligatoirement être lancée depuis l'hôte $host"
 | |
|             return 1
 | |
|         fi
 | |
|     fi
 | |
|     estep "Lancement de $script localement"
 | |
|     runscript_as_root "$script" "$@"
 | |
| }
 | |
| 
 | |
| BUILD_UPDATE_APPS=
 | |
| BUILD_BUILD=
 | |
| UPDATE_APPS_ORIGIN=
 | |
| UPDATE_APPS_BRANCH=
 | |
| function build_set_options() {
 | |
|     case "$1" in
 | |
|     u) BUILD_UPDATE_APPS=1; BUILD_BUILD=;;
 | |
|     b) BUILD_UPDATE_APPS=; BUILD_BUILD=1;;
 | |
|     *) BUILD_UPDATE_APPS=1; BUILD_BUILD=1;;
 | |
|     esac
 | |
|     UPDATE_APPS_ORIGIN="$2"
 | |
|     UPDATE_APPS_BRANCH="$3"
 | |
| }
 | |
| 
 | |
| function update_apps_func_sqlmig() {
 | |
|     local destdir="$1" srcdir="$2"
 | |
|     [ -n "$destdir" ] || destdir=db
 | |
|     [ "${destdir%/config/mariadb/sqlmig}" != "$destdir" ] || destdir="$destdir/config/mariadb/sqlmig"
 | |
| 
 | |
|     [ -n "$srcdir" ] || srcdir="$dest"
 | |
|     [ "${srcdir%/config/sqlmig}" != "$srcdir" ] || srcdir="$srcdir/config/sqlmig"
 | |
| 
 | |
|     if [ ! -d "$srcdir" ]; then
 | |
|         eerror "$srcdir: répertoire introuvable"
 | |
|         return 1
 | |
|     fi
 | |
| 
 | |
|     local -a sqlmigs; local sqlmig name
 | |
|     array_lsall sqlmigs "$srcdir"
 | |
|     mkdir -p "$destdir" || return 1
 | |
|     for sqlmig in "${sqlmigs[@]}"; do
 | |
|         if [ -d "$sqlmig" ]; then
 | |
|             setx name=basename -- "$sqlmig"
 | |
|             rsync -av --delete-after "$sqlmig/" "$destdir/$name"
 | |
|         else
 | |
|             rsync -av "$sqlmig" "$destdir"
 | |
|         fi
 | |
|     done
 | |
|     return 0
 | |
| }
 | |
| 
 | |
| function build_update_apps() {
 | |
|     [ -n "$BUILD_UPDATE_APPS" ] || return 0
 | |
|     [ -f update-apps.conf ] || return 0
 | |
| 
 | |
|     # charger le fichier de configuration
 | |
|     local DEFAULT_ORIGIN DEFAULT_BRANCH APPS
 | |
|     DEFAULT_ORIGIN="$UPDATE_APPS_ORIGIN"
 | |
|     [ -z "$DEFAULT_ORIGIN" ] && DEFAULT_ORIGIN=origin
 | |
|     DEFAULT_BRANCH="$UPDATE_APPS_BRANCH"
 | |
|     #XXX à terme, on déploiera la branche master en prod
 | |
|     [ -z "$DEFAULT_BRANCH" -a "$PROFILE" == prod ] && DEFAULT_BRANCH=develop #master
 | |
|     [ -z "$DEFAULT_BRANCH" ] && DEFAULT_BRANCH=develop
 | |
|     APPS=()
 | |
|     [ -f update-apps.conf ] && source ./update-apps.conf
 | |
|     [ ${#APPS[*]} -gt 0 ] || return 0
 | |
| 
 | |
|     local PRODUCTION DEVELOPMENT
 | |
|     case "$PROFILE" in
 | |
|     prod) PRODUCTION=1; DEVELOPMENT=;;
 | |
|     test) PRODUCTION=1; DEVELOPMENT=1;;
 | |
|     devel) PRODUCTION=; DEVELOPMENT=;;
 | |
|     esac
 | |
| 
 | |
|     etitle "Mise à jour des dépendances"
 | |
|     local app var type url dest branch after_update after_updates
 | |
|     for app in "${APPS[@]}"; do
 | |
|         etitle "$app"
 | |
| 
 | |
|         var="${app//-/_}"
 | |
| 
 | |
|         url="${var}_URL"; url="${!url}"
 | |
|         [ -n "$url" ] || {
 | |
|             ewarn "$app: vous devez définir l'url"
 | |
|             eend; return 1
 | |
|         }
 | |
| 
 | |
|         dest="${var}_DEST"; dest="${!dest}"
 | |
|         [ -n "$dest" ] || dest="$app/b"
 | |
|         mkdir -p "$dest" || { eend; return 1; }
 | |
| 
 | |
|         origin="${var}_${PROFILE}_ORIGIN"; origin="${!origin}"
 | |
|         [ -n "$origin" ] || { origin="${var}_ORIGIN"; origin="${!origin}"; }
 | |
|         [ -n "$origin" ] || origin="$DEFAULT_ORIGIN"
 | |
| 
 | |
|         branch="${var}_${PROFILE}_BRANCH"; branch="${!branch}"
 | |
|         [ -n "$branch" ] || { branch="${var}_BRANCH"; branch="${!branch}"; }
 | |
|         [ -n "$branch" ] || branch="$DEFAULT_BRANCH"
 | |
| 
 | |
|         dest="$dest/$app"
 | |
|         if [ ! -d "$dest" ]; then
 | |
|             # clonage initial
 | |
|             estep "Clonage $url:$branch --> $dest"
 | |
|             git clone -o "$origin" -b "$branch" "$url" "$dest" || { eend; return 1; }
 | |
|         else
 | |
|             # mise à jour
 | |
|             estep "Maj dépôt $url:$branch --> $dest"
 | |
|             setx cwd=pwd
 | |
|             cd "$dest"
 | |
|             git fetch --all -p -f || { eend; return 1; }
 | |
|             git reset --hard "$origin/$branch" || { eend; return 1; }
 | |
|             cd "$cwd"
 | |
|         fi
 | |
| 
 | |
|         type="${var}_TYPE"; type="${!type}"
 | |
|         if [ -z "$type" ]; then
 | |
|             if [ -f "$dest/composer.json" ]; then
 | |
|                 type=composer
 | |
|             else
 | |
|                 type=inconnu
 | |
|             fi
 | |
|         fi
 | |
| 
 | |
|         after_updates="${var}_AFTER_UPDATE"
 | |
|         if is_defined "$after_updates"; then
 | |
|             after_updates="$after_updates[@]"; after_updates=("${!after_updates}")
 | |
|         elif [ "$type" == composer ]; then
 | |
|             after_updates=(sqlmig)
 | |
|         else
 | |
|             after_updates=()
 | |
|         fi
 | |
| 
 | |
|         estep "Type de dépôt: $type"
 | |
|         if [ "$type" == composer ]; then
 | |
|             composer=/usr/bin/composer
 | |
|             [ -x "$dest/composer.phar" ] && composer="$dest/composer.phar"
 | |
| 
 | |
|             estep "Installation des dépendances composer"
 | |
|             "$composer" -d"$dest" install ${PRODUCTION:+--no-dev -o} || { eend; return 1; }
 | |
|         fi
 | |
| 
 | |
|         for after_update in "${after_updates[@]}"; do
 | |
|             if [ "${after_update#/}" != "$after_update" ]; then
 | |
|                 # commande absolue, la lancer telle quelle
 | |
|                 estep "$after_update"
 | |
|                 eval "$after_update" || { eend; return 1; }
 | |
|             elif [ "${after_update#./}" != "$after_update" ]; then
 | |
|                 # commande relative, la lancer telle quelle
 | |
|                 estep "$after_update"
 | |
|                 eval "$after_update" || { eend; return 1; }
 | |
|             else
 | |
|                 # c'est une fonction update_apps_func_*
 | |
|                 estep "$after_update"
 | |
|                 eval "update_apps_func_$after_update" || { eend; return 1; }
 | |
|             fi
 | |
|         done
 | |
| 
 | |
|         eend
 | |
|     done
 | |
|     eend
 | |
| }
 | |
| 
 | |
| function initialize_build_env() {
 | |
|     CTXDIR=.
 | |
|     NAME=
 | |
|     TAGS=(latest)
 | |
|     VERSION=
 | |
| }
 | |
| function default_update_build_env() {
 | |
|     [ -n "$VERSION" ] || docker_add_build_arg VERSION "$(get_version)"
 | |
|     [ -n "$VERSION" ] && TAGS+=("$VERSION")
 | |
| }
 | |
| function update_build_env() { default_update_build_env; }
 | |
| 
 | |
| function default_compose_build() {
 | |
|     ${FAKE:+qvals} docker-compose \
 | |
|         "${replace_env_args[@]}" "${env_args[@]}" \
 | |
|         build \
 | |
|         ${NO_CACHE:+--no-cache} \
 | |
|         "${replace_build_args[@]}" "${build_args[@]}" \
 | |
|         "$@"
 | |
| }
 | |
| function default_docker_build() {
 | |
|     local tag
 | |
|     for tag in "${TAGS[@]}"; do
 | |
|         replace_build_args+=(-t "$NAME:$tag")
 | |
|     done
 | |
|     ${FAKE:+qvals} docker build \
 | |
|         ${NO_CACHE:+--no-cache} \
 | |
|         "${replace_env_args[@]}" "${env_args[@]}" \
 | |
|         "${replace_build_args[@]}" "${build_args[@]}" \
 | |
|         "$@" "$CTXDIR"
 | |
| }
 | |
| function compose_build() {
 | |
|     [ -n "$BUILD_BUILD" ] || return 0
 | |
|     default_compose_build "$@"
 | |
| }
 | |
| function docker_build() {
 | |
|     [ -n "$BUILD_BUILD" ] || return 0
 | |
|     default_docker_build "$@"
 | |
| }
 | |
| function auto_build() {
 | |
|     local -a replace_env_args env_args
 | |
|     local -a replace_build_args build_args
 | |
|     initialize_build_env
 | |
|     if [ -f docker-compose.yml ]; then
 | |
|         compose_set_env_args
 | |
|         update_build_env
 | |
|         build_update_apps || return 1
 | |
|         compose_build "$@"
 | |
|     else
 | |
|         docker_parse_env_args
 | |
|         docker_check_name
 | |
|         docker_add_build_arg build_date "$(date +%y%m%d)"
 | |
|         update_build_env
 | |
|         build_update_apps || return 1
 | |
|         docker_build "$@"
 | |
|     fi
 | |
| }
 | |
| 
 | |
| function auto_push() {
 | |
|     local -a replace_env_args env_args
 | |
|     local -a replace_build_args build_args
 | |
|     local tag
 | |
|     initialize_build_env
 | |
|     if [ -f docker-compose.yml ]; then
 | |
|         compose_set_env_args
 | |
|         update_build_env
 | |
|     else
 | |
|         docker_parse_env_args
 | |
|         docker_check_name
 | |
|         update_build_env
 | |
|     fi
 | |
|     for tag in "${TAGS[@]}"; do
 | |
|         ${FAKE:+qvals} docker push "$NAME:$tag"
 | |
|     done
 | |
| }
 | |
| 
 | |
| function default_compose_up() {
 | |
|     ${FAKE:+qvals} docker-compose \
 | |
|         "${replace_env_args[@]}" "${env_args[@]}" \
 | |
|         up "${replace_run_args[@]}" "${run_args[@]}" \
 | |
|         "${replace_user_args[@]}" "${user_args[@]}" "$@"
 | |
| }
 | |
| function default_docker_up() {
 | |
|     ${FAKE:+qvals} docker run \
 | |
|            "${replace_env_args[@]}" "${env_args[@]}" \
 | |
|            "${replace_run_args[@]}" "${run_args[@]}" \
 | |
|            "$NAME" \
 | |
|            "${replace_user_args[@]}" "${user_args[@]}" "$@"
 | |
| }
 | |
| function compose_up() { default_compose_up "$@"; }
 | |
| function docker_up() { default_docker_up "$@"; }
 | |
| function auto_up() {
 | |
|     local -a replace_env_args env_args
 | |
|     local -a replace_run_args run_args
 | |
|     local -a replace_user_args user_args
 | |
|     local project_name container_name
 | |
|     if [ -f docker-compose.yml ]; then
 | |
|         compose_set_env_args
 | |
|         replace_run_args=(-d)
 | |
|         compose_up "$@"
 | |
|     else
 | |
|         docker_set_env_args
 | |
|         docker_check_name set_container_name
 | |
|         replace_run_args=(-d --name "$container_name")
 | |
|         docker_up "$@"
 | |
|     fi
 | |
| }
 | |
| 
 | |
| function default_compose_stop() {
 | |
|     ${FAKE:+qvals} docker-compose \
 | |
|         "${replace_env_args[@]}" "${env_args[@]}" \
 | |
|         stop "${replace_stop_args[@]}" "${stop_args[@]}" \
 | |
|         "$@"
 | |
| }
 | |
| function default_docker_stop() {
 | |
|     ${FAKE:+qvals} docker container stop \
 | |
|            "${replace_stop_args[@]}" "${stop_args[@]}" \
 | |
|            "$container_name" "$@"
 | |
| }
 | |
| function compose_stop() { default_compose_stop "$@"; }
 | |
| function docker_stop() { default_docker_stop "$@"; }
 | |
| function auto_stop() {
 | |
|     local -a replace_env_args env_args
 | |
|     local -a replace_stop_args stop_args
 | |
|     local project_name container_name
 | |
|     if [ -f docker-compose.yml ]; then
 | |
|         compose_set_env_args
 | |
|         compose_stop "$@"
 | |
|     else
 | |
|         docker_set_env_args
 | |
|         docker_check_name set_container_name
 | |
|         docker_stop "$@"
 | |
|     fi
 | |
| }
 | |
| 
 | |
| function default_compose_logs() {
 | |
|     ${FAKE:+qvals} docker-compose \
 | |
|         "${replace_env_args[@]}" "${env_args[@]}" \
 | |
|         logs "${replace_logs_args[@]}" "${logs_args[@]}" \
 | |
|         "$@"
 | |
| }
 | |
| function default_docker_logs() {
 | |
|     ${FAKE:+qvals} docker logs \
 | |
|            "${replace_logs_args[@]}" "${logs_args[@]}" \
 | |
|            "$container_name" "$@"
 | |
| }
 | |
| function compose_logs() { default_compose_logs "$@"; }
 | |
| function docker_logs() { default_docker_logs "$@"; }
 | |
| function auto_logs() {
 | |
|     local -a replace_env_args env_args
 | |
|     local -a replace_logs_args logs_args
 | |
|     local project_name container_name
 | |
|     if [ -f docker-compose.yml ]; then
 | |
|         compose_set_env_args
 | |
|         replace_logs_args=(-f)
 | |
|         compose_logs "$@"
 | |
|     else
 | |
|         docker_set_env_args
 | |
|         docker_check_name set_container_name
 | |
|         replace_logs_args=(-f)
 | |
|         docker_logs "$@"
 | |
|     fi
 | |
| }
 | |
| 
 | |
| function default_compose_down() {
 | |
|     ${FAKE:+qvals} docker-compose \
 | |
|         "${replace_env_args[@]}" "${env_args[@]}" \
 | |
|         down "${replace_down_args[@]}" "${down_args[@]}" \
 | |
|         "$@"
 | |
| }
 | |
| function default_docker_down() {
 | |
|     estep "stop"
 | |
|     ${FAKE:+qvals} docker container stop \
 | |
|            "${replace_down_args[@]}" "${down_args[@]}" \
 | |
|            "$container_name" "$@"
 | |
|     estep "rm"
 | |
|     ${FAKE:+qvals} docker container rm \
 | |
|            "${replace_rm_args[@]}" "${rm_args[@]}" \
 | |
|            "$container_name"
 | |
| }
 | |
| function compose_down() { default_compose_down "$@"; }
 | |
| function docker_down() { default_docker_down "$@"; }
 | |
| function auto_down() {
 | |
|     local -a replace_env_args env_args
 | |
|     local -a replace_down_args down_args
 | |
|     local -a replace_rm_args rm_args
 | |
|     local project_name container_name
 | |
|     if [ -f docker-compose.yml ]; then
 | |
|         compose_set_env_args
 | |
|         compose_down "$@"
 | |
|     else
 | |
|         docker_set_env_args
 | |
|         docker_check_name set_container_name
 | |
|         docker_down "$@"
 | |
|     fi
 | |
| }
 | |
| 
 | |
| function default_compose_show_ip() {
 | |
|     local -a cmd cids; local cid
 | |
|     cmd=(
 | |
|         docker-compose
 | |
|         "${replace_env_args[@]}" "${env_args[@]}"
 | |
|         ps -q "${replace_show_ip_args[@]}" "${show_ip_args[@]}"
 | |
|         "$@"
 | |
|     )
 | |
|     if [ -n "$FAKE" ]; then
 | |
|         echo "docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' \"\$($(qvals "${cmd[@]}"))\""
 | |
|     else
 | |
|         setx -a cids="${cmd[@]}" 2>/dev/null
 | |
|         for cid in "${cids[@]}"; do
 | |
|             docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' "$cid"
 | |
|         done
 | |
|     fi
 | |
| }
 | |
| function default_docker_show_ip() {
 | |
|     ${FAKE:+qvals} docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' \
 | |
|            "${replace_show_ip_args[@]}" "${show_ip_args[@]}" \
 | |
|            "$container_name" "$@"
 | |
| }
 | |
| function compose_show_ip() { default_compose_show_ip "$@"; }
 | |
| function docker_show_ip() { default_docker_show_ip "$@"; }
 | |
| function auto_show_ip() {
 | |
|     local -a replace_env_args env_args
 | |
|     local -a replace_show_ip_args show_ip_args
 | |
|     local project_name container_name
 | |
|     if [ -f docker-compose.yml ]; then
 | |
|         compose_set_env_args
 | |
|         compose_show_ip "$@"
 | |
|     else
 | |
|         docker_set_env_args
 | |
|         docker_check_name set_container_name
 | |
|         docker_show_ip "$@"
 | |
|     fi
 | |
| }
 | |
| 
 | |
| function default_compose_exec() {
 | |
|     ${FAKE:+qvals} docker-compose \
 | |
|         "${replace_env_args[@]}" "${env_args[@]}" \
 | |
|         exec "${replace_exec_args[@]}" "${exec_args[@]}" \
 | |
|         "$@"
 | |
| }
 | |
| function default_docker_exec() {
 | |
|     ${FAKE:+qvals} docker container exec \
 | |
|            "${replace_exec_args[@]}" "${exec_args[@]}" \
 | |
|            "$container_name" "$@"
 | |
| }
 | |
| function compose_exec() { default_compose_exec "$@"; }
 | |
| function docker_exec() { default_docker_exec "$@"; }
 | |
| function auto_exec() {
 | |
|     local -a replace_env_args env_args
 | |
|     local -a replace_exec_args exec_args
 | |
|     local project_name container_name
 | |
|     if [ -f docker-compose.yml ]; then
 | |
|         compose_set_env_args
 | |
|         compose_exec "$@"
 | |
|     else
 | |
|         docker_set_env_args
 | |
|         docker_check_name set_container_name
 | |
|         docker_exec "$@"
 | |
|     fi
 | |
| }
 | |
| 
 | |
| function default_compose_systemd_unit() {
 | |
|     local docker_compose="$(which docker-compose 2>/dev/null)"
 | |
|     if [ -z "$docker_compose" ]; then
 | |
|         if [ -x /usr/bin/docker-compose ]; then
 | |
|             docker_compose=/usr/bin/docker-compose
 | |
|         elif [ -x /usr/local/bin/docker-compose ]; then
 | |
|             docker_compose=/usr/local/bin/docker-compose
 | |
|         else
 | |
|             die "Impossible de trouver docker-compose"
 | |
|         fi
 | |
|     fi
 | |
|     setx startcmd=qvals "$docker_compose" \
 | |
|         "${replace_env_args[@]}" "${env_args[@]}" \
 | |
|         up "${replace_run_args[@]}" "${run_args[@]}" \
 | |
|         "${replace_user_args[@]}" "${user_args[@]}" "$@"
 | |
|     setx stopcmd=qvals "$docker_compose" down
 | |
| }
 | |
| function default_docker_systemd_unit() {
 | |
|     local docker="$(which docker 2>/dev/null)"
 | |
|     if [ -z "$docker" ]; then
 | |
|         if [ -x /usr/bin/docker ]; then
 | |
|             docker=/usr/bin/docker
 | |
|         elif [ -x /usr/local/bin/docker ]; then
 | |
|             docker=/usr/local/bin/docker
 | |
|         else
 | |
|             die "Impossible de trouver docker"
 | |
|         fi
 | |
|     fi
 | |
|     setx startcmd=qvals "$docker" run \
 | |
|            "${replace_env_args[@]}" "${env_args[@]}" \
 | |
|            "${replace_run_args[@]}" "${run_args[@]}" \
 | |
|            "$NAME" \
 | |
|            "${replace_user_args[@]}" "${user_args[@]}" "$@"
 | |
|     setx stopcmd=qvals "$docker" stop "$container_name"
 | |
| }
 | |
| function compose_systemd_unit() { default_compose_systemd_unit "$@"; }
 | |
| function docker_systemd_unit() { default_docker_systemd_unit "$@"; }
 | |
| function auto_systemd_unit() {
 | |
|     local -a replace_env_args env_args
 | |
|     local -a replace_run_args run_args
 | |
|     local -a replace_user_args user_args
 | |
|     local project_name container_name startcmd stopcmd
 | |
|     local tmpscript; ac_set_tmpfile tmpscript
 | |
| 
 | |
|     estep "Génération de l'unité systemd"
 | |
|     export COMPOSE_PROJECT_NAME=
 | |
|     if [ -f docker-compose.yml ]; then
 | |
|         compose_set_env_args set_container_name
 | |
|         replace_run_args=(-d --no-color)
 | |
|         compose_systemd_unit "$@"
 | |
|         if [ -z "$HOST" -a -f .env ]; then
 | |
|             source ./.env
 | |
|             if [ -n "$PROFILE" ]; then
 | |
|                 HOST="${PROFILE^^}_HOST"; HOST="${!HOST}"
 | |
|             fi
 | |
|         fi
 | |
|     else
 | |
|         docker_set_env_args
 | |
|         docker_check_name set_container_name
 | |
|         replace_run_args=(-d --name "$container_name")
 | |
|         docker_systemd_unit "$@"
 | |
|     fi
 | |
|     [ -n "$COMPOSE_PROJECT_NAME" ] || COMPOSE_PROJECT_NAME="$project_name"
 | |
|     chmod 755 "$tmpscript"
 | |
|     cat >"$tmpscript" <<EOF
 | |
| #!/bin/bash
 | |
| # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
 | |
| cat >/etc/systemd/system/$container_name.service <<EOD
 | |
| [Unit]
 | |
| Description=$project_name stack ($PROFILE)
 | |
| Requires=docker.service
 | |
| After=docker.service
 | |
| 
 | |
| [Service]
 | |
| Type=oneshot
 | |
| RemainAfterExit=yes
 | |
| WorkingDirectory=$(pwd)
 | |
| Environment=$(qval "COMPOSE_PROJECT_NAME=$COMPOSE_PROJECT_NAME")
 | |
| ExecStart=$startcmd
 | |
| ExecStop=$stopcmd
 | |
| TimeoutStopSec=300
 | |
| 
 | |
| [Install]
 | |
| WantedBy=multi-user.target
 | |
| EOD
 | |
| systemctl daemon-reload
 | |
| systemctl enable $container_name.service
 | |
| EOF
 | |
| 
 | |
|     estep "Installation de l'unité systemd"
 | |
|     local_run "$HOST" "$tmpscript"
 | |
| }
 | |
| 
 | |
| DEFAULT_PROFILE=devel
 | |
| PROFILE=
 | |
| DM_PROFILES=()
 | |
| set_defaults dk
 | |
| export PROFILE
 | |
| 
 | |
| if progexists docker-machine; then
 | |
|     setx active_dm=docker-machine active 2>/dev/null
 | |
|     for dm_profile in "${DM_PROFILES[@]}"; do
 | |
|         splitpair "$dm_profile" dm profile
 | |
|         if [ "$dm" == "$active_dm" ]; then
 | |
|             DEFAULT_PROFILE="$profile"
 | |
|             break
 | |
|         fi
 | |
|     done
 | |
| fi
 | |
| 
 | |
| chdir=
 | |
| FAKE=
 | |
| NO_CACHE=
 | |
| HOST=
 | |
| update_apps_mode=ub
 | |
| update_apps_origin=
 | |
| update_apps_branch=
 | |
| args=(
 | |
|     --help '$exit_with display_help'
 | |
|     -d:,--chdir: chdir=
 | |
|     -p:,--profile: PROFILE=
 | |
|     -P,--prod PROFILE=prod
 | |
|     -T,--test PROFILE=test
 | |
|     -n,--fake FAKE=1
 | |
|     -j,--no-cache NO_CACHE=1
 | |
|     -h:,--host: HOST=
 | |
|     -g,--ug,--no-update-apps update_apps_mode=b
 | |
|     -u,--uu,--update-apps-only update_apps_mode=u
 | |
|     --uo:,--update-apps-origin: update_apps_origin=
 | |
|     --ub:,--update-apps-branch: update_apps_branch=
 | |
| )
 | |
| parse_args "$@"; set -- "${args[@]}"
 | |
| 
 | |
| # construire par défaut
 | |
| [ $# -eq 0 ] && set -- build
 | |
| [ -n "$PROFILE" ] || PROFILE="$DEFAULT_PROFILE"
 | |
| 
 | |
| [ -n "$chdir" ] && { cd "$chdir" || die; }
 | |
| 
 | |
| while [ $# -gt 0 ]; do
 | |
|     [ "$1" == -- ] && { shift; continue; }
 | |
|     cmd="$1"; shift
 | |
|     case "$cmd" in
 | |
|     b|build)
 | |
|         build_set_options "$update_apps_mode" "$update_apps_origin"  "$update_apps_branch"
 | |
|         [ -f .build.scripts.sh ] && source ./.build.scripts.sh
 | |
|         [ -f build.scripts.sh ] && source ./build.scripts.sh
 | |
|         args=()
 | |
|         while [ $# -gt 0 -a "$1" != -- ]; do
 | |
|             args+=("$1"); shift
 | |
|         done
 | |
|         enote "Profil $PROFILE"
 | |
|         auto_build "${args[@]}" || die
 | |
|         ;;
 | |
|     push)
 | |
|         [ -f .build.scripts.sh ] && source ./.build.scripts.sh
 | |
|         [ -f build.scripts.sh ] && source ./build.scripts.sh
 | |
|         args=()
 | |
|         while [ $# -gt 0 -a "$1" != -- ]; do
 | |
|             args+=("$1"); shift
 | |
|         done
 | |
|         enote "Profil $PROFILE"
 | |
|         auto_push "${args[@]}" || die
 | |
|         ;;
 | |
|     s|run|start)
 | |
|         args=()
 | |
|         while [ $# -gt 0 -a "$1" != -- ]; do
 | |
|             args+=("$1"); shift
 | |
|         done
 | |
|         enote "Profil $PROFILE"
 | |
|         auto_up "${args[@]}" || die
 | |
|         ;;
 | |
|     k|stop)
 | |
|         args=()
 | |
|         while [ $# -gt 0 -a "$1" != -- ]; do
 | |
|             args+=("$1"); shift
 | |
|         done
 | |
|         enote "Profil $PROFILE"
 | |
|         auto_stop "${args[@]}" || die
 | |
|         ;;
 | |
|     1|up)
 | |
|         args=()
 | |
|         while [ $# -gt 0 -a "$1" != -- ]; do
 | |
|             args+=("$1"); shift
 | |
|         done
 | |
|         enote "Profil $PROFILE"
 | |
|         auto_up "${args[@]}" && auto_logs || die
 | |
|         ;;
 | |
|     l|logs)
 | |
|         args=()
 | |
|         while [ $# -gt 0 -a "$1" != -- ]; do
 | |
|             args+=("$1"); shift
 | |
|         done
 | |
|         enote "Profil $PROFILE"
 | |
|         auto_logs "${args[@]}" || die
 | |
|         ;;
 | |
|     0|down)
 | |
|         args=()
 | |
|         while [ $# -gt 0 -a "$1" != -- ]; do
 | |
|             args+=("$1"); shift
 | |
|         done
 | |
|         enote "Profil $PROFILE"
 | |
|         auto_down "${args[@]}" || die
 | |
|         ;;
 | |
|     d|brd)
 | |
|         do_auto_down=1
 | |
|         function auto_down_trap() {
 | |
|             [ -n "$do_auto_down" ] && auto_down
 | |
|         }
 | |
|         trap auto_down_trap 1 3 15 EXIT
 | |
| 
 | |
|         build_set_options "$update_apps_mode" "$update_apps_origin"  "$update_apps_branch"
 | |
|         [ -f .build.scripts.sh ] && source ./.build.scripts.sh
 | |
|         [ -f build.scripts.sh ] && source ./build.scripts.sh
 | |
|         args=()
 | |
|         while [ $# -gt 0 -a "$1" != -- ]; do
 | |
|             args+=("$1"); shift
 | |
|         done
 | |
|         enote "Profil $PROFILE"
 | |
|         if auto_build; then
 | |
|             auto_up "${args[@]}" && auto_logs || die
 | |
|         else
 | |
|             do_auto_down=
 | |
|         fi
 | |
|         ;;
 | |
|     bs)
 | |
|         build_set_options "$update_apps_mode" "$update_apps_origin"  "$update_apps_branch"
 | |
|         [ -f .build.scripts.sh ] && source ./.build.scripts.sh
 | |
|         [ -f build.scripts.sh ] && source ./build.scripts.sh
 | |
|         args=()
 | |
|         while [ $# -gt 0 -a "$1" != -- ]; do
 | |
|             args+=("$1"); shift
 | |
|         done
 | |
|         enote "Profil $PROFILE"
 | |
|         auto_build && auto_up "${args[@]}"
 | |
|         ;;
 | |
|     ip|show-ip)
 | |
|         args=()
 | |
|         while [ $# -gt 0 -a "$1" != -- ]; do
 | |
|             args+=("$1"); shift
 | |
|         done
 | |
|         enote "Profil $PROFILE"
 | |
|         auto_show_ip "${args[@]}" || die
 | |
|         ;;
 | |
|     x|exec)
 | |
|         args=()
 | |
|         while [ $# -gt 0 -a "$1" != -- ]; do
 | |
|             args+=("$1"); shift
 | |
|         done
 | |
|         enote "Profil $PROFILE"
 | |
|         auto_exec "${args[@]}" || die
 | |
|         ;;
 | |
|     systemd-unit|systemd)
 | |
|         args=()
 | |
|         while [ $# -gt 0 -a "$1" != -- ]; do
 | |
|             args+=("$1"); shift
 | |
|         done
 | |
|         enote "Profil $PROFILE"
 | |
|         auto_systemd_unit "${args[@]}" || die
 | |
|         ;;
 | |
|     ps) docker container ps -a || die;;
 | |
|     ls) docker image ls || die;;
 | |
|     rm)
 | |
|         args=()
 | |
|         while [ $# -gt 0 -a "$1" != -- ]; do
 | |
|             args+=("$1"); shift
 | |
|         done
 | |
|         docker image rm "${args[@]}" || die
 | |
|         ;;
 | |
|     X|prune)
 | |
|         docker container prune -f || die
 | |
|         docker image prune -f || die
 | |
|         ;;
 | |
|     *) die "$cmd: commande inconnue";;
 | |
|     esac
 | |
| done
 |