380 lines
13 KiB
Bash
Executable File
380 lines
13 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/ulib" || exit 1
|
|
urequire DEFAULTS woinst
|
|
|
|
function display_help() {
|
|
uecho "$scriptname: Déploiement distant avec woinst
|
|
|
|
USAGE
|
|
$scriptname [-H host] [-G tmproot] <archive|dir>... [-- options de woinst]
|
|
|
|
note: à cause d'une limitation de makeself, les options de toinst ne devraient
|
|
pas contenir d'espaces ni de caractères spéciaux. L'échappement de ces
|
|
caractères n'est pas garanti.
|
|
|
|
OPTIONS
|
|
-G, --tmproot TMPROOT
|
|
Spécifier le répertoire temporaire sur l'hôte distant, comme par exemple
|
|
/var/tmp. Cette option est utile pour les vservers, qui ont par défaut
|
|
un /tmp minuscule de 16 Mo.
|
|
-S, --ssh SSH
|
|
Spécifier le programme à utiliser pour la connection par ssh.
|
|
-h, --host hosts
|
|
-h, --host @hostsfile
|
|
Spécifier un ou plusieurs hôtes sur lequels faire le déploiement. Pour
|
|
spécifier plusieurs hôtes, il est possible d'utiliser plusieurs fois
|
|
l'option -h, ou spécifier en une seule fois plusieurs hôtes en les
|
|
séparant par un espace ou le caractère ':', e.g. 'host1 host2' ou
|
|
'host1:host2'. Si la spécification contient les caractères { et },
|
|
l'expansion est effectuée, e.g
|
|
-h 'root@{host1,host2}.univ.run'
|
|
Par défaut, la connexion sur l'hôte distant se fait avec l'utilisateur
|
|
root. Il est possible de spécifier un autre utilisateur avec la syntaxe
|
|
user@host, e.g -h user@host
|
|
La forme @hostsfile permet de lire la liste des hôtes depuis le fichier
|
|
hostsfile, à raison d'un hôte par ligne.
|
|
-w, -W, --whost host[:htdocs]
|
|
Comme --host, mais pour le déploiement des resources web. Contrairement
|
|
à --host, un seul hôte peut être spécifié par occurence de l'option,
|
|
pour permettre de spécifier éventuellement le répertoire vers lequel
|
|
copier les resources web. Ainsi, les deux commandes suivantes sont
|
|
équivalentes:
|
|
rwoinst -h host.tld -- -W HTDOCSDIR=HTDOCSBASE/wo
|
|
rwoinst -w host.tld:HTDOCSBASE/wo
|
|
Il est possible de spécifier en une seule invocation --host et --whost
|
|
pour déployer l'application sur un hôte et les resources web sur un
|
|
autre.
|
|
--deploydb
|
|
--nd, --no-deploydb
|
|
Autoriser (respectivement interdire) l'utilisation de la configuration
|
|
locale de déploiement pour identifier la source et/ou la destination
|
|
s'ils ne sont pas spécifiés. Par défaut, la configuration locale de
|
|
déploiement est utilisée.
|
|
-p, --dp, --deploydb-profile PROFILENAME
|
|
Spécifier un ou plusieurs profils séparés par des virgules pour le
|
|
déploiement avec la configuration locale de déploiement. NONE est la
|
|
valeur par défaut et signifie de ne sélectionner que les définitions
|
|
sans profil. ALL signifie de ne pas tenir compte des profils dans les
|
|
définitions.
|
|
-A, --all-profiles
|
|
-P, --prod
|
|
-T, --test
|
|
Raccourcis respectivement pour -pALL, -pprod et -ptest
|
|
-c, --dc, --deploydb-config CONFNAME
|
|
Cette option permet de spécifier un fichier de configuration ou le nom
|
|
de la configuration locale de déploiement à utiliser pour effectuer la
|
|
requête. Par défaut, utiliser le nom 'woinst.conf'"
|
|
}
|
|
|
|
__PARSED_HOSTS=()
|
|
__PARSED_FILES=()
|
|
function parse_hostsfile() {
|
|
# Lire chacun des fichiers $* et initialiser __PARSED_HOSTS avec la liste
|
|
# des hôtes mentionnés dans les fichiers.
|
|
local inputfile basedir inputs input
|
|
for inputfile in "$@"; do
|
|
inputfile="$(abspath "$inputfile")"
|
|
array_contains __PARSED_FILES "$inputfile" && {
|
|
ewarn "$(ppath "$inputfile"): inclusion récursive"
|
|
continue
|
|
}
|
|
array_add __PARSED_FILES "$inputfile"
|
|
basedir="$(dirname "$inputfile")"
|
|
|
|
array_from_lines inputs "$(<"$inputfile" filter_conf)" || {
|
|
ewarn "$inputfile: fichier ingnoré"
|
|
continue
|
|
}
|
|
for input in "${inputs[@]}"; do
|
|
if [ "${input#@}" != "$input" ]; then
|
|
# fichier inclus
|
|
parse_hostsfile "$(abspath "${input#@}" "$basedir")"
|
|
else
|
|
array_addu __PARSED_HOSTS "$input"
|
|
fi
|
|
done
|
|
done
|
|
}
|
|
function __expand_braces() {
|
|
if [[ "$1" == *{* ]] && [[ "$1" == *}* ]]; then
|
|
eval "echo $1"
|
|
else
|
|
echo "$1"
|
|
fi
|
|
}
|
|
function __dot_is_localhost() { [ "$1" == "." ] && echo "localhost" || echo "$1"; }
|
|
function fix_hosts() {
|
|
# Si hosts contient des éléments multiple, comme a:b, séparer ces
|
|
# éléments. i.e (a b:c) --> (a b c)
|
|
# Supporter la syntaxe @hostsfile qui permet de charger la liste des hôtes
|
|
# depuis un fichier.
|
|
# Remplacer aussi les '.' par 'localhost'
|
|
array_map hosts __expand_braces
|
|
array_fix_paths hosts ":"
|
|
array_fix_paths hosts " "
|
|
|
|
local -a _hosts _tmphosts host
|
|
for host in "${hosts[@]}"; do
|
|
host="${host%/}"
|
|
if [ "${host#@}" != "$host" ]; then
|
|
__PARSED_HOSTS=()
|
|
parse_hostsfile "${host#@}"
|
|
array_fix_paths __PARSED_HOSTS
|
|
array_extendu _hosts __PARSED_HOSTS
|
|
else
|
|
array_addu _hosts "$host"
|
|
fi
|
|
done
|
|
array_copy hosts _hosts
|
|
array_map hosts __dot_is_localhost
|
|
}
|
|
|
|
function deploy_to() {
|
|
local archive="$1" host="$2" tmproot="$3"
|
|
shift; shift; shift
|
|
|
|
local r=
|
|
if [ "$host" == "localhost" ]; then
|
|
etitle "Sur l'hôte local"
|
|
"$archive" ${tmproot:+--tmproot "$tmproot"} -- "$@" || r=1
|
|
eend
|
|
else
|
|
local user
|
|
local archivename="$(basename "$archive")"
|
|
|
|
splituserhost "$host" user host
|
|
[ -n "$user" ] || user=root
|
|
|
|
# sur l'hôte distant, ne rendre non interactif qu'à partir de -yy
|
|
rinteraction=$__interaction
|
|
[ $rinteraction -lt 2 ] && rinteraction=$(($rinteraction + 1))
|
|
|
|
etitle "Vers $user@$host"
|
|
|
|
estep "Copie de l'archive"
|
|
scp -S "$SSH" "$archive" "$user@$host:" || r=1
|
|
|
|
if [ -z "$r" ]; then
|
|
estep "Lancement du script de déploiement"
|
|
"$SSH" -qt "$user@$host" "\
|
|
__interaction=$rinteraction
|
|
__estack=$(qval "$__estack")
|
|
__tlevel=$(qval "$__tlevel")
|
|
export __interaction __estack __tlevel
|
|
${UTOOLS_LANG:+UTOOLS_LANG='$UTOOLS_LANG'; export UTOOLS_LANG
|
|
}$(qvals "./$archivename" ${tmproot:+--tmproot "$tmproot"} -- MYHOST="$host" "$@")" || r=1
|
|
fi
|
|
|
|
eend
|
|
fi
|
|
return ${r:-0}
|
|
}
|
|
|
|
action=deploy
|
|
tmproot=
|
|
SSH=
|
|
hosts=()
|
|
whosts=()
|
|
ddb_enable=1
|
|
ddb_profile=NONE
|
|
ddb_conf=woinst.conf
|
|
parse_opts "${PRETTYOPTS[@]}" \
|
|
--help '$exit_with display_help' \
|
|
-G:,--tmproot: tmproot= \
|
|
-S:,--ssh: SSH= \
|
|
-h:,-H:,--host: hosts \
|
|
-w:,-W:,--whost: whosts \
|
|
--deploydb ddb_enable=1 \
|
|
--nd,--no-deploydb ddb_enable= \
|
|
-p:,--dp:,--deploydb-profile ddb_profile= \
|
|
-A,--all-profiles ddb_profile=ALL \
|
|
-P,--prod ddb_profile=prod \
|
|
-T,--test ddb_profile=test \
|
|
-c:,--dc:,--deploydb-config ddb_conf= \
|
|
@ args -- "$@" && set -- "${args[@]}" || die "$args"
|
|
|
|
: "${SSH:=ssh}"
|
|
|
|
## Bundle à déployer et hôtes sur lesquels faire le déploiement
|
|
|
|
# quels informations avons-nous?
|
|
array_isempty hosts && has_hosts= || has_hosts=1
|
|
|
|
if [ $# -eq 0 ] || [[ "$1" == -* ]] || [[ "$1" == *=* ]]; then
|
|
# pas d'argument, ou c'est une option (qui fait donc partie des arguments de woinst)
|
|
has_bundle=
|
|
else
|
|
bundle="$1"
|
|
has_bundle=1
|
|
shift
|
|
fi
|
|
|
|
# configuration locale de déploiement
|
|
ddb_enable= #XXX 05/04/2021 désactiver deploydb pour le moment
|
|
if [ -n "$ddb_enable" ]; then
|
|
# filtrer les options... elles seront ignorées si on passe finalement par
|
|
# deploydb
|
|
vars=()
|
|
options=()
|
|
for arg in "$@"; do
|
|
if [[ "$arg" == *=* ]]; then
|
|
array_add vars "$arg"
|
|
else
|
|
array_add options "$arg"
|
|
fi
|
|
done
|
|
|
|
deploydb=(
|
|
"$scriptdir/lib/nulib/deploydb"
|
|
--missing-ok
|
|
${ddb_conf:+-c "$ddb_conf"}
|
|
-m woinst
|
|
--run -r woinst.query_rwoinst "$script"
|
|
)
|
|
cmds=()
|
|
myname="$(basename "$(pwd)")"
|
|
if [ -n "$has_hosts" ]; then
|
|
fix_hosts
|
|
for host in "${hosts[@]}"; do
|
|
array_from_lines tmpcmds "$("${deploydb[@]}" "$bundle" "$host" "$ddb_profile" "${vars[@]}")"
|
|
array_extend cmds tmpcmds
|
|
done
|
|
elif [ -n "$has_bundle" ]; then
|
|
array_from_lines tmpcmds "$("${deploydb[@]}" "$bundle" "" "$ddb_profile" "${vars[@]}")"
|
|
array_extend cmds tmpcmds
|
|
elif [[ "$myname" == *.woa ]] || [[ "$myname" == *.framework ]]; then
|
|
read_value "Veuillez entrer le chemin du bundle à déployer" bundle . O
|
|
has_bundle=1
|
|
array_from_lines tmpcmds "$("${deploydb[@]}" "$bundle" "" "$ddb_profile" "${vars[@]}")"
|
|
array_extend cmds tmpcmds
|
|
fi
|
|
if [ ${#cmds[*]} -gt 0 ]; then
|
|
[ ${#options[*]} -gt 0 ] && ewarn "Les options supplémentaires '${options[*]}' seront ignorées"
|
|
if check_interaction -c; then
|
|
if [ ${#cmds[*]} -eq 1 ]; then
|
|
einfo "La commande suivante va être lancée:"
|
|
eecho "\$ $script --no-deploydb \\"
|
|
for cmd in "${cmds[0]}"; do
|
|
eecho " ${cmd#$script --no-deploydb }"
|
|
done
|
|
else
|
|
einfo "Les commandes suivantes seront lancées:"
|
|
eecho "\$ $script --no-deploydb \\"
|
|
for cmd in "${cmds[@]}"; do
|
|
eecho " ... ${cmd#$script --no-deploydb }"
|
|
done
|
|
fi
|
|
read -p "Confirmez ou attendez 4 secondes [On] " -t 4 r
|
|
if [ $? -gt 128 ]; then
|
|
echo # cosmetic
|
|
elif [ $? -le 128 -a -n "$r" ]; then
|
|
is_yes "$r" || die
|
|
fi
|
|
fi
|
|
r=0
|
|
for cmd in "${cmds[@]}"; do
|
|
einfo "$cmd"
|
|
eval "$cmd" || r=1
|
|
done
|
|
exit $r
|
|
elif [ "$ddb_profile" != "ALL" ]; then
|
|
ewarn "Aucune configuration locale de déploiement n'a été trouvée pour le profil $ddb_profile"
|
|
fi
|
|
fi
|
|
|
|
if [ -z "$has_bundle" ]; then
|
|
# pas d'argument, ou c'est une option (qui fait donc partie des arguments de woinst)
|
|
read_value "Veuillez entrer le chemin du bundle à déployer" bundle "$bundle" O
|
|
has_bundle=1
|
|
fi
|
|
[ -n "$has_bundle" ] && set -- "$bundle" "$@"
|
|
|
|
array_isempty hosts && read_value "Entrez une liste d'hôtes séparés par ':'" hosts "localhost"
|
|
fix_hosts
|
|
|
|
## Création de l'archive
|
|
|
|
etitle "Création du répertoire de travail"
|
|
ac_set_tmpdir workdir
|
|
|
|
bundles=()
|
|
while [ -n "$1" ]; do
|
|
if [ "$1" == "--" ]; then
|
|
# début des options de woinst
|
|
shift
|
|
break
|
|
elif [[ "$1" == -* ]] || [[ "$1" == *=* ]]; then
|
|
# début des options de woinst
|
|
break
|
|
fi
|
|
|
|
src="$1"; shift
|
|
if [ -f "$src" ] && is_archive "$src"; then
|
|
estep "$(ppath "$src")"
|
|
cp_R "$src" "$workdir" || die
|
|
elif [ -d "$src" ]; then
|
|
src="$(abspath "$src")"
|
|
setx srcname=basename -- "$src"
|
|
case "$src" in
|
|
*.woa|*.framework) ;;
|
|
*) # support projet maven
|
|
if [ ! -f "$src/pom.xml" ]; then
|
|
: # non, pas un projet maven
|
|
elif [ -d "$src/target/$srcname.woa" ]; then
|
|
src="$src/target/$srcname.woa"
|
|
elif [ -d "$src/target/$srcname.framework" ]; then
|
|
src="$src/target/$srcname.framework"
|
|
fi
|
|
;;
|
|
esac
|
|
if endswith "$src" .framework; then
|
|
is_wofwkdir "$src" || die "Framework invalide: $(ppath "$src")"
|
|
elif endswith "$src" .woa; then
|
|
is_woappdir "$src" || die "Application invalide: $(ppath "$src")"
|
|
else
|
|
die "N'est pas un bundle valide: $(ppath "$src")"
|
|
fi
|
|
estep "$(ppath2 "$src")"
|
|
cp_R "$src" "$workdir" || die
|
|
else
|
|
die "Fichier ou répertoire introuvable: $src"
|
|
fi
|
|
|
|
src="$(abspath "$src")"
|
|
array_add bundles "$(basename "$src")"
|
|
done
|
|
|
|
estep "Copie de l'environnement de déploiement"
|
|
mkdir "$workdir/lib"
|
|
ulibsync "$workdir/lib"
|
|
cp "$scriptdir/woinst.sh" "$workdir"
|
|
chmod +x "$workdir/woinst.sh"
|
|
|
|
eend
|
|
|
|
etitle "Création de l'archive pour le déploiement"
|
|
ac_set_tmpfile archive
|
|
|
|
"$scriptdir/mkusfx" --bare --tmp-archive -o "$archive" "$workdir" -- ./woinst.sh --is-tmpdir "${bundles[@]}" || die
|
|
|
|
eend
|
|
|
|
## Déploiement
|
|
|
|
etitle "Déploiement des bundles"
|
|
for host in "${hosts[@]}"; do
|
|
deploy_to "$archive" "$host" "$tmproot" "$@" "${woinst_options[@]}" || die
|
|
done
|
|
eend
|
|
|
|
if [ ${#whosts[*]} -gt 0 ]; then
|
|
etitle "Déploiement des resources web"
|
|
for hostdestdir in "${whosts[@]}"; do
|
|
splitpair "$hostdestdir" host destdir
|
|
deploy_to "$archive" "$host" "$tmproot" \
|
|
-y -W ${destdir:+HTDOCSDIR="$destdir"} "$@" "${woinst_options[@]}" || die
|
|
done
|
|
eend
|
|
fi
|