Intégration de la branche release-9.7.0
This commit is contained in:
commit
05fd86acc7
20
CHANGES.md
20
CHANGES.md
|
@ -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
14
TODO.md
|
@ -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
|
|
@ -1 +1 @@
|
|||
9.6.0
|
||||
9.7.0
|
||||
|
|
368
dk
368
dk
|
@ -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)")"
|
||||
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"
|
||||
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
|
||||
|
|
80
dmctl
80
dmctl
|
@ -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,12 +70,17 @@ load)
|
|||
machinedir="$destdir/$name"
|
||||
origdir="$HOME/${name}-machine.orig"
|
||||
if [ -d "$machinedir" ]; then
|
||||
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"
|
||||
fi
|
||||
fi
|
||||
|
||||
ac_set_tmpdir workdir
|
||||
srcdir="$workdir/$name"
|
||||
|
@ -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
|
||||
|
|
|
@ -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 }'
|
|
@ -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" "$@"
|
||||
}
|
||||
|
|
|
@ -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 {
|
|
@ -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
12
pff
|
@ -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
12
repoctl
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue