nutools/rwoinst

276 lines
9.4 KiB
Plaintext
Raw Normal View History

2013-08-27 15:14:44 +04:00
#!/bin/bash
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
2014-07-07 22:06:38 +04:00
source "$(dirname "$0")/lib/ulib/ulib" || exit 1
urequire DEFAULTS woinst
2013-08-27 15:14:44 +04:00
function display_help() {
uecho "$scriptname: Déploiement distant avec woinst
USAGE
$scriptname [-H host] [-T tmproot] <file|archive|dir>... [-- options de woinst]
OPTIONS
-C, --configure-user
--configure USER [--uses-su]
Ne pas faire le déploiement. Configurer uniquement la connexion par clé
2013-08-27 15:14:44 +04:00
sur les hôtes distants spécifiés pour le user spécifié. Il faut pouvoir
se connecter par mot de passe pour configurer la connexion par clé.
Si l'on veut configurer la connexion par clé pour le user root, mais que
ce n'est pas possible de se connecter par mot de passe avec le user root
sur l'hôte distant, et qu'il existe un user sudoer sur l'hôte distant,
il est possible de faire la configuration avec '--configure root'. La
commande serait alors
$scriptname -H user@host --configure root
Si l'hôte distant n'a pas sudo ou si sudo n'est pas configuré, il faut
rajouter l'option --uses-su, e.g:
$scriptname -h user@host --configure root --uses-su
-T, --tmproot TMPROOT
2013-08-27 15:14:44 +04:00
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
2013-08-27 15:14:44 +04:00
Spécifier le programme à utiliser pour la connection par ssh.
-h, --host hosts
-h, --host @hostsfile
2013-08-27 15:14:44 +04:00
-H host
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'
2013-08-27 15:14:44 +04:00
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.
--deploy
--no-deploy
Autoriser (respectivement interdire) l'utilisation de la configuration
locale de déploiement pour identifier la destination si aucun hôte n'est
spécifié.
Par défaut, si aucun hôte n'est spécifié, la configuration locale de
déploiement est interrogée pour avoir cette information.
-c, --deploy-config CONFNAME
Cette option permet de spécifier le nom de la configuration à utiliser
pour effectuer la requête. Par défaut, utiliser le nom 'rwoinst'"
2013-08-27 15:14:44 +04:00
}
set_defaults pubkeys
action=deploy
confuser=
uses_su=
2013-08-27 15:14:44 +04:00
tmproot=
SSH=
hosts=()
deploy_enable=1
deploy_confname=rwoinst
2013-08-27 15:14:44 +04:00
parse_opts "${PRETTYOPTS[@]}" \
--help '$exit_with display_help' \
-C,--configure-user action=configure \
2013-08-27 15:14:44 +04:00
--configure: '$set@ confuser;action=configure' \
--uses-su uses_su=1 \
2013-08-27 15:14:44 +04:00
-T:,--tmproot: tmproot= \
-S:,--ssh: SSH= \
2013-08-27 15:14:44 +04:00
-h:,-H:,--host: hosts \
--deploy deploy_enable=1 \
--no-deploy deploy_enable= \
-c:,--deploy-config deploy_confname= \
2013-08-27 15:14:44 +04:00
@ args -- "$@" && set -- "${args[@]}" || die "$args"
SSH="${SSH:-ssh}"
__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
2013-08-27 15:14:44 +04:00
}
function __dot_is_localhost() { [ "$1" == "." ] && echo "localhost" || echo "$1"; }
2013-08-27 15:14:44 +04:00
function fix_hosts() {
# Si hosts contient des éléments multiple, comme a:b, séparer ces
2013-08-27 15:14:44 +04:00
# é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
2013-08-27 15:14:44 +04:00
}
################################################################################
# Configuration de l'accès par clé aux hôtes
if [ "$action" == "configure" ]; then
args=(${confuser:+--configure "$confuser"} ${uses_su:+--uses-su} -S "$SSH")
2013-08-27 15:14:44 +04:00
for host in "${hosts[@]}"; do
args=("${args[@]}" -H "$host")
done
exec "$scriptdir/ruinst" -C "${args[@]}"
fi
################################################################################
# Déploiement
## Bundle à déployer
if [ -z "$1" ] || [[ "$1" == -* ]] || [[ "$1" == *=* ]]; then
# pas d'argument, ou c'est une option (qui fait donc partie des arguments de
# woinst)
die "Vous devez spécifier le bundle à déployer"
fi
## Hôtes sur lesquels faire le déploiement
if array_isempty hosts && [ -n "$deploy_enable" ]; then
urequire deploy
deploy_setconf "$deploy_confname"
if deploy_loadconf; then
setxx wobundle=abspath "$1" // basename --
if eval "$(deploy_query -v host DEST wobundle rwoinst_bundle "" shell "$wobundle")"; then
check_interaction -c && einfo "Ce bundle sera déployé vers les hôtes suivants:
$(array_to_lines host "" " ")"
ask_any "Voulez-vous continuer?" Oq || die
array_copy hosts host
fi
fi
fi
2013-08-27 15:14:44 +04:00
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 -s "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
2015-08-20 07:58:17 +04:00
break
2013-08-27 15:14:44 +04:00
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")"
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 "$(ppath "$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"
2014-07-09 11:03:23 +04:00
ulibsync "$workdir"
2013-08-27 15:14:44 +04:00
echo '#!/bin/sh
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
if . `dirname "$0"`/ulib/ulibsh; then
urequire DEFAULTS woinst
else
exit 1
fi
OENC="$UTF8"
woinst "$@"' >"$workdir/woinst"
chmod +x "$workdir/woinst"
eend
ac_set_tmpfile archive
archivename="$(basename "$archive")"
etitle "Création de l'archive pour le déploiement" \
"$scriptdir/mkusfx" --bare --tmp-archive -o "$archive" "$workdir" -- ./woinst --is-tmpdir "${bundles[@]}" || die
## Déploiement
# sur l'hôte distant, ne rendre interactif qu'à partir de -yy
rinteraction=$__interaction
[ $rinteraction -lt 2 ] && rinteraction=$(($rinteraction + 1))
2013-08-27 15:14:44 +04:00
for host in "${hosts[@]}"; do
if [ "$host" == "localhost" ]; then
etitle "Déploiement sur l'hôte local" \
"$archive" ${tmproot:+--tmproot "$tmproot"} -- "$@"
else
if [[ "$host" == *@* ]]; then
user="${host%%@*}"
host="${host#*@}"
else
user=root
fi
etitle -s "Déploiement sur $user@$host"
estep "Copie de l'archive"
scp -S "$SSH" "$archive" "$user@$host:" || die
estep "Lancement du script de déploiement"
"$SSH" -qt "$user@$host" "\
__interaction=$rinteraction
__estack=$(qval "$__estack")
__tlevel=$(qval "$__tlevel")
export __interaction __estack __tlevel
2013-08-27 15:14:44 +04:00
${UTOOLS_LANG:+UTOOLS_LANG='$UTOOLS_LANG'; export UTOOLS_LANG
}$(qvals "./$archivename" ${tmproot:+--tmproot "$tmproot"} -- MYHOST="$host" "$@")"
2013-08-27 15:14:44 +04:00
eend
fi
done