Intégration de la branche release-9.7.0

This commit is contained in:
Jephté Clain 2020-04-17 10:20:37 +04:00
commit 05fd86acc7
12 changed files with 470 additions and 109 deletions

View File

@ -1,3 +1,23 @@
## Version 9.7.0 du 17/04/2020-10:20
* `f4f9b69` dk: bug avec la synchro d'un fichier
* `74190f7` dk: par défaut, les suffixes courants sont supprimés
* `9fad992` dk: support répertoire/fichier source
* `1d7e2d0` bug
* `7268cec` pff: workaround pour certaines erreurs de packaging
* `aa26966` dk: support build args avec la syntaxe NAME=VALUE
* `f7b3f90` dk: augmenter la largeur de la colonne node
* `1c4c1c3` dmctl: l'option -a supporte les répertoires
* `ccf3c67` dk: aliases de filtres
* `1b12cee` dk: afficher un warning si le profil n'est pas défini pour une machine
* `45976f4` dk: sta affiche le statut pour tous les services
* `1960c0c` dk: implémenter status
* `4f206d7` dk: frontend plus 'transparent'
* `d666859` dk: supprimer avec image:tag si possible
* `4ee346b` maj chemin ip
* `c9796b2` ipaddr: frontend pour ip addr
* `668eec1` dmctl: possibilité d'importer toutes les machines d'un répertoire
## Version 9.6.0 du 24/02/2020-09:13
* `b7492fc` dk: ajout de l'option -e

14
TODO.md
View File

@ -1,17 +1,3 @@
# TODO
## dk
Ajouter le support du déploiement de services dans un swarm
Les nouvelles actions suivantes sont disponibles:
* deploy -- déployer un service
* bpd -- équivalent à build, push, deploy
* update -- mettre à jour un service déployé
* bpu -- équivalent à build, push, update
* rollback -- annuler la mise à jour d'un service
Pour toutes ces actions, utiliser par défaut docker-stack.yml s'il existe,
sinon utiliser docker-compose.yml (en tenant compte des paramètres des profils)
-*- coding: utf-8 mode: markdown -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8:noeol:binary

View File

@ -1 +1 @@
9.6.0
9.7.0

372
dk
View File

@ -1,7 +1,7 @@
#!/bin/bash
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
source "$(dirname "$0")/lib/ulib/auto" || exit 1
urequire pff
urequire pff json
function display_help() {
uecho "$scriptname: outil pour faciliter l'utilisation de docker
@ -9,11 +9,22 @@ function display_help() {
USAGE
$scriptname CMDs...
Si une commande commence ou se termine par un underscore, e.g '_ls', elle est
passée telle quelle à docker (en enlevant l'underscore d'abord, bien sûr). Si
une commande ne figure pas dans la liste ci-dessous, elle est passée telle
quelle à docker.
Certaines commandes ci-dessous ont le même nom que des commandes docker, et
nécessitent un projet docker ou docker-compose. Si ces commandes sont lancées
alors qu'on n'est pas dans un projet docker, alors elles sont passées telle
quelles à docker. ATTENTION: comme la commande est exécutée par docker, cela
veut dire qu'elle n'aura pas la même sématique.
COMMANDES
get-profile
Afficher le profil courant
b|build [SERVICE]
Construire les images
b|build [NAME=VALUE...] [SERVICE]
Construire les images. Les variables NAME=VALUE sont des 'build args'
p|push
p|push [SERVICES...]
La première syntaxe est utilisable avec un projet docker. Elle permet de
@ -45,32 +56,32 @@ COMMANDES
x|exec SERVICE COMMAND
Lancer une commande dans le container correspondant au service spécifié,
qui doit être en fonctionnement
d|brd
d|brd [NAME=VALUE...]
Construire les images (comme avec build), démarrer les services et
suivre les logs de façon interactive (comme avec up). Dès que l'on
arrête l'affichage des logs avec Ctrl+C, arrêter les services et
supprimer l'environnement (comme avec down)
Vaguement équivalent à -- build -- start [args] -- logs
suivi de -- down
bs
bs [NAME=VALUE...]
Construire les images (comme avec build) puis démarrer les services
(comme avec start)
Equivalent à -- build -- start [args]
br SERVICE [COMMAND]
br [NAME=VALUE...] SERVICE [COMMAND]
Construire les images (comme avec build) puis démarrer le service avec
la commande spécifiée (comme avec run)
Equivalent à -- build -- run [args]
Equivalent à -- build [NAME=VALUE...] -- run [args]
y|deploy [args...]
(Re)déployer un stack. Cette commande ne fonctionne qu'en mode swarm.
Implique --stack
by|bd [args...]
Equivalent à --stack -- build -- deploy args...
by|bd [NAME=VALUE...] [args...]
Equivalent à --stack -- build [NAME=VALUE...] -- deploy args...
Utilisable notamment en développement
bp [args...]
Equivalent à --stack -- build -- push args...
bpy|bpd [args...]
Equivalent à --stack -- build -- push -- deploy args...
service COMMAND SERVICE [args...]
bp [NAME=VALUE...] [args...]
Equivalent à --stack -- build [NAME=VALUE...] -- push args...
bpy|bpd [NAME=VALUE...] [args...]
Equivalent à --stack -- build [NAME=VALUE...] -- push -- deploy args...
ser|service COMMAND SERVICE [args...]
Frontend pour 'docker service COMMAND args... SERVICE'
Cette commande ne fonctionne qu'en mode swarm. Il n'est pas nécessaire
de préfixer le nom du service avec le nom du stack, pour être cohérent
@ -81,6 +92,23 @@ COMMANDES
$scriptname -- service logs web -f
Pour des cas d'utilisation plus complexe, il faut lancer directement
docker service
sta|status [SERVICE] [num]
Afficher le status du service spécifié: pour chaque occurence, sur quel
noeud il tourne (ou tournait), quel est le statut actuel ainsi que le
message associé. Si le service n'est pas spécifié, prendre la liste des
services affichée par docker service ls
'num' est le numéro de l'instance de service. Si ce numéro est précisé,
afficher les informations uniquement pour cette instance là, ainsi que
les logs
Il est possible de spécifier un filtre docker name=value avant 'num'. Ce
filtre est utilisé pour sélectionner certaines instances du service.
- id=<ID> a task's ID ou prefix
- name=<string> a task's name or prefix
- node=<string> a node's name or ID
- desired-state=(running|shutdown|accepted)
Pour faciliter l'utilisation des filtres, certains aliases sont définis.
'=r', '=k' et '=a' sont des aliases pour desired-state=running,
desired-state=shutdown et desired-state=accepted respectivement
u|update SERVICE [args...]
Mettre à jour un service, équivalent à 'service update SERVICE'
scale SERVICE=REPLICAS [args...]
@ -94,7 +122,7 @@ COMMANDES
ps [filter|name=value]
Afficher les containers en cours d'exécution
Le filtre est une expression régulière de type awk qui est mise en
correspondace avec les noms de l'image et de la tâche.
correspondance avec les noms de l'image et de la tâche.
Il est aussi possible d'utiliser un filtre docker de la forme name=value
- ancestor=(<image-name>[:tag]|<image-id>| <image@digest>)
containers created from an image or a descendant.
@ -244,7 +272,8 @@ OPTIONS build
APPS=() # applications à mettre à jour par défaut
PROFILE_APPS=() # ou... spécifique au profil 'PROFILE'
app_URL= # url du dépôt
app_DEVEL_SRCDIR= # répertoire source en mode devel
app_DEVEL_SRCDIR= # répertoire source du dépôt en mode devel
app_SRC= # répertoire/fichier source (si URL pas renseigné)
app_DEST= # répertoire dans lequel faire le checkout
app_PROFILE_ORIGIN= # origine spécifique au profil 'PROFILE'
app_ORIGIN= # ou... origine par défaut de la branche
@ -270,6 +299,11 @@ OPTIONS deploy
(c'est à dire ne pas utiliser l'option --with-registry-auth)
VARIABLES de update-apps.conf
SRC
répertoire/fichier source, si URL n'est pas défini. si ce chemin est
relatif, il doit être exprimé par rapport au répertoire du projet.
IMPORTANT: dans ce cas, DEST n'est pas le répertoire de base du
checkout, mais le répertoire destination pour la synchro
DEVEL_SRCDIR
répertoire source pour le mode devel. attention, il s'agit du répertoire
du projet, alors que DEFAULT_DEVEL_SRCDIR est le répertoire de base par
@ -290,6 +324,7 @@ VARIABLES de update-apps.conf
projet. Les variables suivantes sont disponibles:
URL= # url du dépôt
DEVEL_SRCDIR= # répertoire source en mode devel
SRC= # répertoire/fichier source (si URL pas renseigné)
DEST= # répertoire dans lequel faire le checkout
ORIGIN= # origine de la branche
BRANCH= # branche sélectionnée dans le dépôt
@ -385,11 +420,18 @@ function docker_check_name() {
}
function compose_set_project_name() {
local PROJECT_NAME= PROJECT_NAME_REMOVE_SUFFIX=.service PROJECT_NAME_ADD_PROFILE=
local PROJECT_NAME= PROJECT_NAME_REMOVE_SUFFIX=--defaults-- PROJECT_NAME_ADD_PROFILE=
[ -f .compose.env ] && source ./.compose.env
[ -n "$PROJECT_NAME" ] || PROJECT_NAME="$(basename -- "$(pwd)")"
PROJECT_NAME="${PROJECT_NAME%$PROJECT_NAME_REMOVE_SUFFIX}"
if [ "$PROJECT_NAME_REMOVE_SUFFIX" == --defaults-- ]; then
if [ "${PROJECT_NAME%.service}" != "$PROJECT_NAME" ]; then PROJECT_NAME="${PROJECT_NAME%.service}"
elif [ "${PROJECT_NAME%.stack}" != "$PROJECT_NAME" ]; then PROJECT_NAME="${PROJECT_NAME%.stack}"
elif [ "${PROJECT_NAME%.network}" != "$PROJECT_NAME" ]; then PROJECT_NAME="${PROJECT_NAME%.network}"
fi
else
PROJECT_NAME="${PROJECT_NAME%$PROJECT_NAME_REMOVE_SUFFIX}"
fi
if [ -n "$PROFILE" ]; then
[ -n "$COMPOSE_PROJECT_NAME" ] || COMPOSE_PROJECT_NAME="$PROJECT_NAME${PROJECT_NAME_ADD_PROFILE:+_${PROFILE}}"
@ -626,8 +668,8 @@ function build_update_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
#XXX à terme, ne déployer en prod que la branche master
[ -z "$DEFAULT_BRANCH" -a "$PROFILE" == prod ] && DEFAULT_BRANCH=develop #XXX master
[ -z "$DEFAULT_BRANCH" ] && DEFAULT_BRANCH=develop
DEFAULT_DEVEL_SRCDIR="$HOME/wop/php"
DEFAULT_COMPOSER_ACTION=install
@ -657,24 +699,26 @@ function build_update_apps() {
fi
etitle "Mise à jour des dépendances"
local app var URL DEVEL_SRCDIR DEST ORIGIN BRANCH TYPE after_update after_updates composer_action
local app var URL SRC DEVEL_SRCDIR DEST ORIGIN BRANCH TYPE after_update after_updates composer_action
for app in "${APPS[@]}"; do
etitle "$app"
var="${app//-/_}"
URL="${var}_URL"; URL="${!URL}"
[ -n "$URL" ] || {
ewarn "$app: vous devez définir l'url"
eend; return 1
}
if [ -z "$URL" ]; then
SRC="${var}_SRC"; SRC="${!SRC}"
if [ -z "$SRC" ]; then
ewarn "$app: vous devez définir ${var}_URL ou ${var}_SRC"
eend; return 1
fi
fi
DEVEL_SRCDIR="${var}_DEVEL_SRCDIR"; DEVEL_SRCDIR="${!DEVEL_SRCDIR}"
[ -n "$DEVEL_SRCDIR" ] || DEVEL_SRCDIR="$DEFAULT_DEVEL_SRCDIR/${URL##*/}"
DEST="${var}_DEST"; DEST="${!DEST}"
[ -n "$DEST" ] || DEST="$app/b"
mkdir -p "$DEST" || { eend; return 1; }
ORIGIN="${var}_${PROFILE}_ORIGIN"; ORIGIN="${!ORIGIN}"
[ -n "$ORIGIN" ] || { ORIGIN="${var}_ORIGIN"; ORIGIN="${!ORIGIN}"; }
@ -687,8 +731,10 @@ function build_update_apps() {
# calculer le type maintenant, on en a besoin pour le mode devel
TYPE="${var}_TYPE"; TYPE="${!TYPE}"
DEST="$DEST/$app"
if [ -n "$BUILD_UPDATE_DEVEL" ]; then
mkdir -p "$DEST" || { eend; return 1; }
DEST="$DEST/$app"
# synchronisation en mode devel
local -a rsync_opts; rsync_opts=(-a --delete --exclude .git/ --delete-excluded)
estep "Synchro $DEVEL_SRCDIR --> $DEST"
@ -713,7 +759,10 @@ function build_update_apps() {
rsync "${rsync_opts[@]}" --exclude /vendor/ "$DEFAULT_DEVEL_SRCDIR/$pname/" "$depdir"
done
fi
else
elif [ -n "$URL" ]; then
mkdir -p "$DEST" || { eend; return 1; }
DEST="$DEST/$app"
if [ -d "$DEST" -a -d "$DEST/.git" ]; then
# mise à jour
estep "Maj dépôt $URL:$BRANCH --> $DEST"
@ -730,6 +779,36 @@ function build_update_apps() {
git clone -o "$ORIGIN" -b "$BRANCH" "$URL" "$DEST" || { eend; return 1; }
fi
if [ -z "$TYPE" ]; then
# possible de détecter le type quand on a le projet
# en cas de maj ici, mettre à jour aussi le code ci-dessus et ci-dessous
if [ -f "$DEST/composer.json" ]; then TYPE=composer
else TYPE=none
fi
fi
elif [ -n "$SRC" ]; then
if [ -d "$SRC" ]; then
local -a rsync_opts; rsync_opts=(-a --delete --exclude .git/ --delete-excluded)
SRC="${SRC%/}/"
DEST="${DEST%/}/"
estep "Synchro $SRC --> $DEST"
rsync "${rsync_opts[@]}" "$SRC" "$DEST" || { eend; return 1; }
elif [ -f "$SRC" ]; then
local -a rsync_opts; rsync_opts=(-a)
if [ "${DEST%/}" != "$DEST" -o -d "$DEST" ]; then
DEST="${DEST%/}/"
estep "Synchro $SRC --> $DEST"
rsync "${rsync_opts[@]}" "$SRC" "$DEST" || { eend; return 1; }
else
estep "Synchro $SRC --> $DEST"
rsync "${rsync_opts[@]}" "$SRC" "$DEST" || { eend; return 1; }
fi
else
eerror "$app: $SRC: répertoire/fichier introuvable"
eend; return 1
fi
if [ -z "$TYPE" ]; then
# possible de détecter le type quand on a le projet
# en cas de maj ici, mettre à jour aussi le code ci-dessus
@ -737,6 +816,10 @@ function build_update_apps() {
else TYPE=none
fi
fi
else
# ne devrait pas se produire
die "ni URL ni SRC ne sont définis"
fi
after_updates="${var}_AFTER_UPDATE"
@ -812,11 +895,11 @@ function default_update_build_env() {
[ -n "$VERSION" ] || docker_add_build_arg VERSION "$(get_version)"
[ -n "$VERSION" ] && TAGS+=("$VERSION")
# Variables en ligne de commande
for var in "${VARS[@]}"; do
for var in "${VARS[@]}" "$@"; do
docker_add_build_arg "${var%%=*}" "${var#*=}"
done
}
function update_build_env() { default_update_build_env; }
function update_build_env() { default_update_build_env "$@"; }
function default_compose_build() {
${FAKE:+qvals} docker-compose \
@ -845,22 +928,42 @@ function docker_build() {
[ -n "$BUILD_BUILD" ] || return 0
default_docker_build "$@"
}
function __parse_bargs() {
bargs=()
args=()
while [ $# -gt 0 ]; do
[[ "$1" == *=* ]] && bargs+=("$1") || args+=("$1")
shift
done
}
function auto_build() {
local -a replace_env_args env_args
local -a replace_build_args build_args
initialize_build_env
local -a args bargs; local barg
__parse_bargs "$@"
set -- "${args[@]}"
if [ -f docker-compose.yml ]; then
compose_set_env_args
update_build_env
update_build_env "${bargs[@]}"
build_update_apps || return 1
compose_build "$@"
else
elif [ -f Dockerfile ]; then
docker_parse_env_args
docker_check_name
docker_add_build_arg build_date "$(date +%y%m%d)"
update_build_env
update_build_env "${bargs[@]}"
build_update_apps || return 1
docker_build "$@"
else
for barg in "${bargs[@]}"; do
replace_build_args+=(--build-arg "$barg")
done
${FAKE:+qvals} "$DOCKER" build \
${NO_CACHE:+--no-cache} \
"${replace_build_args[@]}" "$@"
fi
}
@ -892,11 +995,13 @@ function auto_push() {
compose_set_env_args
update_build_env
compose_push "$@"
else
elif [ -f Dockerfile ]; then
docker_parse_env_args
docker_check_name
update_build_env
docker_push "$@"
else
${FAKE:+qvals} "$DOCKER" push "$@"
fi
}
@ -924,11 +1029,13 @@ function auto_up() {
compose_set_env_args
replace_run_args=(-d)
compose_up "$@"
else
elif [ -f Dockerfile ]; then
docker_set_env_args
docker_check_name set_container_name
replace_run_args=(-d --name "$container_name")
docker_up "$@"
else
${FAKE:+qvals} "$DOCKER" run "$@"
fi
}
@ -952,10 +1059,12 @@ function auto_stop() {
if [ -f docker-compose.yml ]; then
compose_set_env_args
compose_stop "$@"
else
elif [ -f Dockerfile ]; then
docker_set_env_args
docker_check_name set_container_name
docker_stop "$@"
else
${FAKE:+qvals} "$DOCKER" stop "$@"
fi
}
@ -980,11 +1089,13 @@ function auto_logs() {
compose_set_env_args
replace_logs_args=(-f)
compose_logs "$@"
else
elif [ -f Dockerfile ]; then
docker_set_env_args
docker_check_name set_container_name
replace_logs_args=(-f)
docker_logs "$@"
else
${FAKE:+qvals} "$DOCKER" logs "$@"
fi
}
@ -1014,10 +1125,12 @@ function auto_down() {
if [ -f docker-compose.yml ]; then
compose_set_env_args
compose_down "$@"
else
elif [ -f Dockerfile ]; then
docker_set_env_args
docker_check_name set_container_name
docker_down "$@"
else
${FAKE:+qvals} "$DOCKER" stop "$@"
fi
}
@ -1038,7 +1151,7 @@ function compose_run() { default_compose_run "$@"; }
function docker_run() { default_docker_run "$@"; }
function auto_run() {
eval "$(utools_local parse_opts)"
local detach no_deps rm=1 service_ports use_aliases volume
local detach no_deps rm=1 service_ports use_aliases volume disable_tty
local -a envs labels
local var
for var in "${VARS[@]}"; do
@ -1056,6 +1169,7 @@ function auto_run() {
--service-ports service_ports=1
--use-aliases use_aliases=1
-v:,--volume: volume=
-T disable_tty=1
@ args -- "$@"
)
parse_opts "${args[@]}" && set -- "${args[@]}" || { eerror "$args"; return 1; }
@ -1074,9 +1188,10 @@ function auto_run() {
${service_ports:+--service-ports}
${use_aliases:+--use-aliases}
${volume:+-v "$volume"}
${disable_tty:+-T}
)
compose_run "$@"
else
elif [ -f Dockerfile ]; then
docker_set_env_args
docker_check_name set_container_name
replace_run_args=(
@ -1085,6 +1200,8 @@ function auto_run() {
${volume:+-v "$volume"}
)
docker_run "$@"
else
${FAKE:+qvals} "$DOCKER" run ${rm:+--rm} ${volume:+-v "$volume"} "$@"
fi
}
@ -1108,10 +1225,12 @@ function auto_exec() {
if [ -f docker-compose.yml ]; then
compose_set_env_args
compose_exec "$@"
else
elif [ -f Dockerfile ]; then
docker_set_env_args
docker_check_name set_container_name
docker_exec "$@"
else
${FAKE:+qvals} "$DOCKER" exec "$@"
fi
}
@ -1167,10 +1286,121 @@ function auto_service() {
;;
esac
else
die "Impossible de trouver ni docker-compose.yml ni docker-stack.yml"
${FAKE:+qvals} "$DOCKER" service "$@"
fi
}
function __format() {
# formatter une liste de valeur. chaque argument est de la forme [SIZE:]VALUE
# il ne faudrait utiliser la forme VALUE que pour le dernier argument
local size value
for value in "$@"; do
if [[ "$value" == *:* ]]; then
size="${value%%:*}"
value="${value#*:}"
else
size=
fi
if [ -n "$size" ]; then
while [ "${#value}" -lt "$size" ]; do
value="$value "
done
if [ "${#value}" -gt "$size" ]; then
[ "$size" -gt 1 ] && value="${value:0:$(($size - 1))}"
value="$value"$'\xe2\x80\xa6'
fi
fi
echo -n "${value} "
done
echo
}
function __status_query_task() {
setx taskData="$DOCKER" inspect "$taskID"
setx taskSlot=json_get 0.Slot <<<"$taskData"
setx taskStatus=json_get 0.Status.Err <<<"$taskData"
setx serviceID=json_get 0.ServiceID <<<"$taskData"
}
function __status_query_service() {
[ "$serviceID" == "$pServiceID" ] && return
setx serviceData="$DOCKER" inspect "$serviceID"
setx serviceName=json_get 0.Spec.Name <<<"$serviceData"
setx serviceUpdateStatus=json_get 0.UpdateStatus.Message <<<"$serviceData"
pServiceID="$serviceID"
}
function __status_process_data() {
__status_query_task
__status_query_service
if [ -n "$serviceUpdateStatus" ]; then
echo "\
================
$serviceName: $serviceUpdateStatus
================"
serviceUpdateStatus=
fi
if [ "$num" -eq 0 ]; then
# afficher les en-têtes
__format 3:num 32:taskName 32:node 8:dState 20:cState :error
fi
if [ -z "$fnum" -o "$num" == "$fnum" ]; then
taskName="$serviceName.$taskSlot"
__format 3:"$num" 32:"$taskName.$taskID" 32:"$node" 8:"$desiredState" 20:"$currentState" :"$taskStatus"
fi
if [ "$num" == "$fnum" ]; then
"$DOCKER" service logs -f "$taskID"
fi
let num=num+1
}
function auto_status() {
local -a services
local service
if [[ "$1" == *=* ]]; then
: # le premier argument est un filtre
elif [ -n "$1" -a -z "${1//[0-9]/}" ]; then
: # le premier argument est un numéro d'instance
else
# le premier argument est un nom de service
service="$1"; shift
fi
if [ -n "$service" ]; then
if [ -f docker-compose.yml -o -f docker-stack.yml ]; then
# si on est dans répertoire de projet, il est possible de spécifier
# le service sans préfixe
local -a replace_env_args env_args
local -a replace_deploy_args deploy_args
local project_name container_name
docker_set_deploy_args set_container_name
service="${container_name}_${service#${container_name}_}"
fi
services=("$service")
else
# lister les services qui tournent actuellement
setx -a services=docker service ls --format "{{.Name}}"
fi
local -a psargs
local filter fnum
psargs=(
--format "taskID={{.ID}};node={{.Node}};desiredState='{{.DesiredState}}';currentState='{{.CurrentState}}';__status_process_data"
)
while [[ "$1" == *=* ]]; do
filter="$1"
case "$filter" in
=r) filter="desired-state=running";;
=k) filter="desired-state=shutdown";;
=a) filter="desired-state=accepted";;
esac
psargs+=(--filter "$filter")
shift
done
fnum="$1"; shift
local num=0 taskData taskStatus taskSlot pServiceID serviceID serviceData serviceName serviceUpdateStatus
for service in "${services[@]}"; do
eval "$("$DOCKER" service ps "$service" "${psargs[@]}")"
done
}
function default_compose_show_ip() {
local -a cmd cids; local cid
cmd=(
@ -1554,15 +1784,25 @@ if [ -n "$DM_SET_MACHINE" ]; then
[ "$DM_SET_MACHINE" == - ] && DM_SET_MACHINE=-u
setx dm_env=docker-machine env "$DM_SET_MACHINE" || die
eval "$dm_env"
# pour warning ci-dessous
[ "$DM_SET_MACHINE" == -u ] && DM_SET_MACHINE=
fi
if [ -n "$DM_AVAILABLE" ]; then
found=
for dm_profile in "${DM_PROFILES[@]}"; do
splitpair "$dm_profile" dm profile
if [ "$dm" == "$DOCKER_MACHINE_NAME" ]; then
DEFAULT_PROFILE="$profile"
found=1
break
fi
done
if [ -n "$DM_SET_MACHINE" -a -z "$PROFILE" -a -z "$found" ]; then
ewarn "\
Aucun profil n'a été défini pour $DM_SET_MACHINE dans ~/etc/default/dk
== Le profil $DEFAULT_PROFILE sera utilisé =="
sleep 3
fi
fi
# construire par défaut
@ -1675,7 +1915,8 @@ while [ $# -gt 0 ]; do
args+=("$1"); shift
done
enote "Profil $PROFILE"
if auto_build; then
__parse_bargs "${args[@]}"
if auto_build "${bargs[@]}"; then
auto_up "${args[@]}" && auto_logs || die
else
do_auto_down=
@ -1691,7 +1932,8 @@ while [ $# -gt 0 ]; do
args+=("$1"); shift
done
enote "Profil $PROFILE"
auto_build && auto_up "${args[@]}"
__parse_bargs "${args[@]}"
auto_build "${bargs[@]}" && auto_up "${args[@]}" || die
;;
br)
build_set_options "$update_apps_mode" "$update_apps_origin" "$update_apps_branch"
@ -1703,7 +1945,8 @@ while [ $# -gt 0 ]; do
args+=("$1"); shift
done
enote "Profil $PROFILE"
auto_build && auto_run "${args[@]}"
__parse_bargs "${args[@]}"
auto_build "${bargs[@]}" && auto_run "${args[@]}" || die
;;
y|deploy)
USE_STACK=1
@ -1724,7 +1967,8 @@ while [ $# -gt 0 ]; do
args+=("$1"); shift
done
enote "Profil $PROFILE"
auto_build && auto_deploy "${args[@]}"
__parse_bargs "${args[@]}"
auto_build "${bargs[@]}" && auto_deploy "${args[@]}" || die
;;
bp)
build_set_options "$update_apps_mode" "$update_apps_origin" "$update_apps_branch"
@ -1735,7 +1979,8 @@ while [ $# -gt 0 ]; do
args+=("$1"); shift
done
enote "Profil $PROFILE"
auto_build && auto_push "${args[@]}"
__parse_bargs "${args[@]}"
auto_build "${bargs[@]}" && auto_push "${args[@]}" || die
;;
bpy|bpd)
build_set_options "$update_apps_mode" "$update_apps_origin" "$update_apps_branch"
@ -1746,9 +1991,10 @@ while [ $# -gt 0 ]; do
args+=("$1"); shift
done
enote "Profil $PROFILE"
auto_build && auto_push && auto_deploy "${args[@]}"
__parse_bargs "${args[@]}"
auto_build "${bargs[@]}" && auto_push && auto_deploy "${args[@]}" || die
;;
service)
ser|service)
args=()
while [ $# -gt 0 -a "$1" != -- ]; do
args+=("$1"); shift
@ -1756,6 +2002,14 @@ while [ $# -gt 0 ]; do
enote "Profil $PROFILE"
auto_service "${args[@]}" || die
;;
sta|status)
args=()
while [ $# -gt 0 -a "$1" != -- ]; do
args+=("$1"); shift
done
enote "Profil $PROFILE"
auto_status "${args[@]}" || die
;;
u|update)
args=()
while [ $# -gt 0 -a "$1" != -- ]; do
@ -1916,7 +2170,7 @@ NR == 1 { print; next }
shift
fi
all="$("${lscmd[@]}" | "${filtercmd[@]}")"
setx -a images awk 'NR == 1 { next } { print $3 }' <<<"$all"
setx -a images awk 'NR == 1 { next } { if ($1 == "<none>" || $2 == "<none>") { print $3 } else { print $1 ":" $2 } }' <<<"$all"
if [ ${#images[*]} -gt 0 ]; then
echo "$all"
ask_yesno "Etes-vous sûr de vouloir supprimer ces images?" || die
@ -1942,8 +2196,22 @@ NR == 1 { print; next }
done
auto_composer "${args[@]}"
;;
_*|*_)
# transmettre directement à docker
cmd="${cmd#_}"
cmd="${cmd%_}"
args=()
while [ $# -gt 0 -a "$1" != -- ]; do
args+=("$1"); shift
done
"$DOCKER" "$cmd" "${args[@]}"
;;
*)
# transmettre directement à docker pour les autres commandes
exec "$DOCKER" "$cmd" "$@"
# transmettre directement à docker
args=()
while [ $# -gt 0 -a "$1" != -- ]; do
args+=("$1"); shift
done
"$DOCKER" "$cmd" "${args[@]}"
esac
done

88
dmctl
View File

@ -8,33 +8,20 @@ function display_help() {
USAGE
$scriptname -d NAME
$scriptname -l ARCHIVE
$scriptname -a ARCHIVEs...
OPTIONS
-d, --dump
Exporter la machine
-l, --load
Import la machine"
Import la machine
-a, --load-all
Importer toutes les machines"
}
action=
args=(
--help '$exit_with display_help'
-d,--dump,-x,--export,-s,--save action=dump
-l,--load,-i,--import action=load
)
parse_args "$@"; set -- "${args[@]}"
function dump_machine() {
local name srcdir workdir destdir archive i
if [ -z "$action" ]; then
case "$1" in
d|dump|x|export|s|save) action=dump; shift;;
l|load|i|import) action=load; shift;;
*) die "Vous devez spécifier l'action à effectuer";;
esac
fi
case "$action" in
dump)
############################################################################
name="$1"
[ -n "$name" ] || die "Vous devez spécifier le nom de la machine"
@ -64,10 +51,11 @@ s|DOCKER_MACHINE_HOME/certs/|DOCKER_MACHINE_HOME/machines/$name/|g
tar czf "$archive" -C "$workdir" "$name" || die
ac_clean "$workdir"
;;
}
function load_machine() {
local archive archivename destdir machinedir origdir workdir srcdir
load)
############################################################################
archive="$1"
[ -n "$archive" ] || die "Vous devez spécifier l'archive à importer"
@ -82,11 +70,16 @@ load)
machinedir="$destdir/$name"
origdir="$HOME/${name}-machine.orig"
if [ -d "$machinedir" ]; then
ewarn "$name: une machine du même nom existe déjà"
ask_yesno "Voulez-vous l'écraser?" N || die
if [ -n "$NOCLOBBER" ]; then
ewarn "$name: cette machine existe déjà"
return
else
ewarn "$name: une machine du même nom existe déjà"
ask_yesno "Voulez-vous l'écraser?" N || die
[ -d "$origdir" ] && rm -rf "$origdir"
mv "$machinedir" "$origdir"
[ -d "$origdir" ] && rm -rf "$origdir"
mv "$machinedir" "$origdir"
fi
fi
ac_set_tmpdir workdir
@ -112,5 +105,48 @@ s|DOCKER_MACHINE_HOME|$HOME/.docker/machine|g
fi
ac_clean "$workdir"
}
# faut-il ignorer les machines existantes
NOCLOBBER=
action=
args=(
--help '$exit_with display_help'
-d,--dump,-x,--export,-s,--save action=dump
-l,--load,-i,--import action=load
-a,--all,--load-all,--import-all action=loadall
)
parse_args "$@"; set -- "${args[@]}"
if [ -z "$action" ]; then
case "$1" in
d|dump|x|export|s|save) action=dump; shift;;
l|load|i|import) action=load; shift;;
a|all|loadall|importall) action=loadall; shift;;
*) die "Vous devez spécifier l'action à effectuer";;
esac
fi
case "$action" in
dump) dump_machine "$1";;
load) load_machine "$1";;
loadall)
[ $# -gt 0 ] || set -- .
archives=()
for file in "$@"; do
if [ -d "$file" ]; then
NOCLOBBER=1
array_lsfiles files "$file" "*-machine.tar.gz"
array_extend archives files
else
archives+=("$file")
fi
done
for archive in "${archives[@]}"; do
etitle "$archive"
load_machine "$archive"
eend
done
;;
esac

26
ipaddr Executable file
View File

@ -0,0 +1,26 @@
#!/bin/bash
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
# frontend pour 'ip addr' qui formatte l'affichage pour prendre moins de place
if [ -x /usr/bin/ip ]; then IP=/usr/bin/ip
elif [ -x /bin/ip ]; then IP=/bin/ip
else IP=ip
fi
tty -s <&1 && isatty=1 || isatty=
"$IP" addr "$@" | awk -v isatty="$isatty" '
isatty && $0 ~ /^[0-9]/ {
$0 = gensub(/: ([^:]+):/, ": \x1B[32m\\1\x1B[0m:", 1)
}
isatty && $1 == "inet" {
$0 = gensub(/inet ([^ ]+) /, "inet \x1B[34m\\1\x1B[0m ", 1)
}
{
if ($1 == "inet" || $1 == "inet6") {
printf "%s -- ", $0
getline
sub(/^ +/, "")
}
}
{ print }'

View File

@ -29,3 +29,17 @@ function json_get(line) {
function awkjson() {
json_filter | awkrun -f "$JSONFUNCS" "$@"
}
function json_get() { php_json_get "$@"; }
function json_each() { php_json_each "$@"; }
function json_build() { php_json_build "$@"; }
function php_json_get() {
"$ULIBDIR/support/php/json_get.php" "$@"
}
function php_json_each() {
"$ULIBDIR/support/php/json_each.php" "$@"
}
function php_json_build() {
"$ULIBDIR/support/php/json_build.php" "$@"
}

View File

@ -11,7 +11,7 @@ foreach ($data as $datum) {
$keys = explode(".", trim($argv[$i]));
foreach ($keys as $key) {
if ($result === null) break;
if (!$key) continue;
if ($key === "") continue;
if (isset($result[$key])) {
$result = $result[$key];
} else {

View File

@ -3,15 +3,26 @@
if ($argc <= 1) die("ERROR: Vous devez spécifier le nom de la clé\n");
$argindex = 1;
$arg = $argv[1];
$sep = "\t";
if ($arg == "-s") {
$sep = $argv[2];
$argindex += 2;
} elseif (substr($arg, 0, 2) == "-s") {
$sep = substr($arg, 2);
$argindex++;
}
$datum = json_decode(stream_get_contents(STDIN), true);
$first = true;
for ($i = 1; $i < $argc; $i++) {
for ($i = $argindex; $i < $argc; $i++) {
$result = $datum;
$keys = explode(".", trim($argv[$i]));
foreach ($keys as $key) {
if ($result === null) break;
if (!$key) continue;
if ($key === "") continue;
if (isset($result[$key])) {
$result = $result[$key];
} else {
@ -20,7 +31,7 @@ for ($i = 1; $i < $argc; $i++) {
}
if ($first) $first = false;
else echo "\t";
else echo $sep;
if (is_array($result)) var_export($result);
else echo $result;
}

12
pff
View File

@ -777,7 +777,17 @@ function new__prepare_archive() {
# nom de l'archive sans la version
local ban="${banv%$(get_archive_versionsuffix "$archive")}"
local filename="$(basename "$file")"
[ "$filename" == "$banv" -o "$filename" == "$ban" ] || unwrap=
if [ "$filename" == "$banv" -o "$filename" == "$ban" ]; then
# le nom du répertoire correspond au nom de l'archive. cool!
unwrap=1
elif [ "${filename%-$version}" == "$ban" ]; then
# le nom du répertoire n'est pas contruit correctement
# mais ce n'est pas grave (e.g ban-VERSION au lieu de
# banVERSION comme l'archive)
unwrap=1
else
unwrap=
fi
fi
[ -n "$unwrap" -a -d "$file" ] && srcdir="$file"
fi

12
repoctl
View File

@ -1,7 +1,7 @@
#!/bin/bash
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
source "$(dirname "$0")/lib/ulib/ulib" || exit 1
urequire DEFAULTS
urequire DEFAULTS json
function display_help() {
uecho "$scriptname: piloter un serveur git (gitolite, gogs, gitea, etc.)
@ -39,16 +39,6 @@ ACTIONS
Supprimer le dépôt spécifié"
}
function json_build() {
"$scriptdir/lib/repoctl/json_build.php" "$@"
}
function json_get() {
"$scriptdir/lib/repoctl/json_get.php" "$@"
}
function json_each() {
"$scriptdir/lib/repoctl/json_each.php" "$@"
}
function repoctl_init() {
repourl="${1%.git}"
[ -n "$repourl" ] || return