Intégration de la branche release-6.4.0
This commit is contained in:
commit
4f5d3794fe
45
CHANGES.md
45
CHANGES.md
|
@ -1,3 +1,48 @@
|
|||
## Version 6.4.0 du 05/05/2017-16:50
|
||||
|
||||
* `c25160c` fndate: maj doc et améliorations ergonomiques
|
||||
* `d5f4ae2` pclone: filtrer les projets de type wildcard
|
||||
* `f8f731e` support de la complétion pour rwoinst -w
|
||||
* `e4b7714` tailor.py et chrono.py: améliorer l'affichage de l'aide
|
||||
* `6f1d5e5` Intégration de la branche rwoinst-updates
|
||||
* `4aaded5` support des répertoires source maven et de l'interrogation de deploy pour: profil, déploiement des resources web, variables bounce, notag, exec, dbconfig, dbconfigmap
|
||||
* `f20cc48` rwoinst: ajouter l'option -w qui peut être spécifiée en parallèle de -h pour déployer les resources web vers un serveur différent
|
||||
* `9e4ccae` woinst: support des préfixes dans les variables
|
||||
* `8f9ddb5` uinst.sh et woinst.sh: améliorer la comptabilité
|
||||
* `e01cabb` makeself: retourner le code d'erreur même avec un auto-extractible temporaire
|
||||
* `8482d61` pclone: ajouter l'option --master
|
||||
* `a264b3e` pclone: implémenter le clonage récursif avec -r ainsi que les options -n et -u
|
||||
* `262048f` ufile: possibilité de classer vers plusieurs destinations
|
||||
* `8c22012` ufile: copier en local sans utiliser scp si possible
|
||||
* `dec100b` ufile: support du classement par scp
|
||||
* `c82c908` ufile: support des inclusions, d'un fichier de configuration alternatif
|
||||
* `d535df3` ufile: le code de retour de renamef peut annuler une règle
|
||||
* `0365c54` améliorer l'ergonomie de ruinst, rwoinst, toinst: pas la peine de confirmer le répertoire courant s'il est déployé sur un hôte
|
||||
* `8ce9821` fndate: améliorer l'ergonomie de l'option -@
|
||||
* `5b0f13d` ufile: changer la sémantique de renamef
|
||||
* `fec6b2f` pu: support du scenario ou la branche de feature distante a été supprimée
|
||||
* `151433b` ufile: ajout des options --list et --edit
|
||||
* `a99f313` ufile: classement automatique de fichiers
|
||||
* `540e718` base.core: qwc supporte les classes de caractères
|
||||
* `78e0a8e` cosmetic
|
||||
* `027b416` ppath2() est plus approprié dans certaines circonstances
|
||||
* `c034115` revert 9d8b32bcd118ca9194b2d134e51a078d16b1c18d: la correction du bug était incorrecte
|
||||
* `1dbe02f` Intégration de la branche tomcat-deploy
|
||||
* `2394edf` toinst: implémenter la sauvegarde
|
||||
* `fc467cb` finaliser le support de .toinst.conf et traiter les options --exclude, --protect et --rsync-option
|
||||
* `9d8b32b` parse_args: bug avec la fonction reset
|
||||
* `9084e7e` début du support de .toinst.conf
|
||||
* `a84775c` support des options --wamap et --protect depuis la configuration locale de déploiement
|
||||
* `3bbabbf` deploy: support des options --of, --df, --lf
|
||||
* `c1a536b` deploy: support des options -old pour afficher des informations supplémentaires
|
||||
* `2daf190` quelques améliorations dont support du profil de déploiement
|
||||
* `0b46830` implémenter toinst et rtoinst
|
||||
* `836c933` maj doc ruinst et désactiver déploiement de clé par rwoinst
|
||||
* `2991e63` deploy: requête récursive par défaut
|
||||
* `52bb0d5` base.core: ajout de la fonction echo_setv2() pendant de echo_seta2()
|
||||
* `bab9c50` tailor.py: suivre un fichier est optionnel
|
||||
* `4593ad8` ajout de tailor.py: affichage d'un fichier en mettant en surbrillance certains patterns
|
||||
|
||||
## Version 6.3.1 du 06/04/2017-22:34
|
||||
|
||||
* `b3e6ff6` cgilsxml.py: maj doc
|
||||
|
|
|
@ -1 +1 @@
|
|||
6.3.1
|
||||
6.4.0
|
||||
|
|
55
chrono.py
55
chrono.py
|
@ -273,26 +273,55 @@ def run_chronometre(timeout=None, autostart=False):
|
|||
Application(timeout, autostart).mainloop()
|
||||
|
||||
if __name__ == '__main__':
|
||||
from argparse import ArgumentParser, RawTextHelpFormatter
|
||||
from argparse import ArgumentParser, HelpFormatter
|
||||
if sys.argv[1:2] == ['--compat']:
|
||||
# Avec l'argument --compat, désactiver la classe FancyHelpFormatter qui
|
||||
# se base sur une API non documentée
|
||||
sys.argv = sys.argv[0:1] + sys.argv[2:]
|
||||
FancyHelpFormatter = HelpFormatter
|
||||
else:
|
||||
class FancyHelpFormatter(HelpFormatter):
|
||||
"""Comme HelpFormatter, mais ne touche pas aux lignes qui commencent par les
|
||||
caractères '>>>'. Cela permet de mixer du texte formaté et du texte non
|
||||
formaté.
|
||||
"""
|
||||
def _fill_text(self, text, width, indent):
|
||||
return ''.join([indent + line for line in text.splitlines(True)])
|
||||
def _split_lines(self, text, width):
|
||||
lines = ['']
|
||||
for line in text.splitlines():
|
||||
if line.startswith('>>>'):
|
||||
lines.append(line)
|
||||
lines.append('')
|
||||
else:
|
||||
lines[-1] += '\n' + line
|
||||
lines = filter(None, lines)
|
||||
texts = []
|
||||
for line in lines:
|
||||
if line.startswith('>>>'):
|
||||
texts.append(line[3:])
|
||||
else:
|
||||
texts.extend(super(FancyHelpFormatter, self)._split_lines(line, width))
|
||||
return texts
|
||||
AP = ArgumentParser(
|
||||
formatter_class=RawTextHelpFormatter,
|
||||
usage=u"%(prog)s [options] [TIMEOUT]",
|
||||
description=u"Afficher un chronomètre",
|
||||
epilog=u"Si TIMEOUT est spécifié, par défaut le décompte démarre automatiquement."
|
||||
epilog=u"Si TIMEOUT est spécifié, par défaut le décompte démarre automatiquement.",
|
||||
formatter_class=FancyHelpFormatter,
|
||||
)
|
||||
AP.set_defaults(autostart=None, timeout=None)
|
||||
AP.add_argument('timeout', metavar='TIMEOUT', nargs='?',
|
||||
help=u"""\
|
||||
(valeur vide)
|
||||
chronomètre qui démarre à 0:00 et ne s'arrête pas
|
||||
H:M:S (heures:minutes:secondes)
|
||||
ou M:S (minutes:secondes)
|
||||
ou M (minutes)
|
||||
minuteur qui démarre à H:M:S et fait un décompte jusqu'à 0:00. A la fin
|
||||
du décompte, une sonnerie retentit.
|
||||
@H[:M[:S]]
|
||||
minuteur qui fonctionne comme précédemment, sauf qu'on spécifie l'heure
|
||||
d'arrivée, et que la durée est calculée automatiquement""")
|
||||
>>> (valeur vide)
|
||||
chronomètre qui démarre à 0:00 et ne s'arrête pas
|
||||
>>> H:M:S (heures:minutes:secondes)
|
||||
>>> ou M:S (minutes:secondes)
|
||||
>>> ou M (minutes)
|
||||
minuteur qui démarre à H:M:S et fait un décompte jusqu'à 0:00. A la fin
|
||||
du décompte, une sonnerie retentit.
|
||||
>>> @H[:M[:S]]
|
||||
minuteur qui fonctionne comme précédemment, sauf qu'on spécifie l'heure
|
||||
d'arrivée, et que la durée est calculée automatiquement""")
|
||||
AP.add_argument('-n', '--no-autostart', dest='autostart', action='store_false',
|
||||
help=u"Ne pas démarrer automatiquement le décompte même si TIMEOUT est spécifié.")
|
||||
AP.add_argument('-s', '--autostart', dest='autostart', action='store_true',
|
||||
|
|
57
fndate
57
fndate
|
@ -60,9 +60,17 @@ OPTIONS
|
|||
PLACEHOLDER vaut ~~. Si le nom spécifié ne contient pas le PLACEHOLDER,
|
||||
il est placé au début.
|
||||
-@, --force-date DATE
|
||||
Dans le nom spécifié, si la date est déjà présente, forcer son
|
||||
remplacement par la valeur spécifiée. Par défaut, le fichier n'est pas
|
||||
modifié si la date est déjà présente.
|
||||
Si une date du format attendu est déjà présente dans le nom du fichier,
|
||||
forcer son remplacement par la valeur spécifiée. Par défaut, le fichier
|
||||
n'est pas modifié si la date est déjà présente.
|
||||
Si le premier ou le dernier argument de ce script ressemblent à une date
|
||||
(ie. d/m[/y] ou @d[/m[/y]]) et qu'aucun fichier de ce nom n'existe dans
|
||||
le répertoire courant, activer automatiquement cette option, sauf si
|
||||
l'option --no-auto-force-date est spécifiée aussi. Ainsi, les commandes
|
||||
suivantes sont équivalentes:
|
||||
$scriptname -@ d/m/y file
|
||||
$scriptname d/m/y file
|
||||
$scriptname file @d/m/y
|
||||
-F, --format FORMAT
|
||||
Spécifier le format de la date à insérer dans le nom du fichier. Par
|
||||
défaut, FORMAT vaut 'YYMMDD-'
|
||||
|
@ -227,6 +235,7 @@ dmove) action=move;;
|
|||
dcmd) action=cmd;;
|
||||
esac
|
||||
placeholder=
|
||||
auto_force_date=1
|
||||
force_date=
|
||||
format=
|
||||
autof=
|
||||
|
@ -240,6 +249,7 @@ parse_opts "${PRETTYOPTS[@]}" \
|
|||
-c,--cmd action=cmd \
|
||||
--string action=string \
|
||||
-P:,--placeholder: placeholder= \
|
||||
--no-auto-force-date auto_force_date= \
|
||||
-@:,--force-date: force_date= \
|
||||
-F:,--format: format= \
|
||||
-s,--short '$format=YYMMDD; autof=1' \
|
||||
|
@ -247,6 +257,27 @@ parse_opts "${PRETTYOPTS[@]}" \
|
|||
--autof autof=1 \
|
||||
@ args -- "$@" && set -- "${args[@]}" || die "$args"
|
||||
|
||||
if [ -z "$force_date" -a -n "$auto_force_date" ]; then
|
||||
# si le premier ou le dernier argument ressemblent à une date
|
||||
f="$1"; f2="${f#@}"
|
||||
if [[ "$f" == */* ]] && [ -z "${f//[0-9\/]}" -a ! -e "$f" ]; then
|
||||
force_date="$f"
|
||||
shift
|
||||
elif [[ "$f" == @* ]] && [ -z "${f2//[0-9\/]}" -a ! -e "$f2" ]; then
|
||||
force_date="$f2"
|
||||
shift
|
||||
elif [ $# -gt 1 ]; then
|
||||
l="${@:$#}"; l2="${l#@}"
|
||||
if [[ "$l" == */* ]] && [ -z "${l//[0-9\/]}" -a ! -e "$l" ]; then
|
||||
force_date="$l"
|
||||
set -- "${@:1:$(($# - 1))}"
|
||||
elif [[ "$l" == @* ]] && [ -z "${l2//[0-9\/]}" -a ! -e "$l2" ]; then
|
||||
force_date="$l2"
|
||||
set -- "${@:1:$(($# - 1))}"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
[ -n "$create" ] || create=file
|
||||
[ -n "$placeholder" ] || placeholder="~~"
|
||||
[ -n "$force_date" ] && setx force_date=parse_date "$force_date"
|
||||
|
@ -329,14 +360,24 @@ elif [ "$action" == create ]; then
|
|||
setx dir=dirname -- "$src"
|
||||
setx srcname=basename -- "$src"
|
||||
if [ -e "$src" ]; then
|
||||
estep "Renommage de $(ppath "$src")"
|
||||
setx destname=replace_ph "$srcname" "$force_date"
|
||||
setx dest=abspath "$dir/$destname"
|
||||
[ "$src" != "$dest" ] || ewarn "La source et la destination sont identiques"
|
||||
read_value "Veuillez confirmer le nom" destname "$destname"
|
||||
confirm_do=1
|
||||
if [ "$src" == "$dest" ]; then
|
||||
if [ -n "$force_date" ]; then
|
||||
ewarn "La source et la destination sont identiques"
|
||||
else
|
||||
estepi "$(ppath "$src"): aucun renommage nécessaire"
|
||||
confirm_do=
|
||||
fi
|
||||
fi
|
||||
if [ -n "$confirm_do" ]; then
|
||||
estep "Renommage de $(ppath "$src")"
|
||||
read_value "Veuillez confirmer le nom" destname "$destname"
|
||||
|
||||
setx dest=abspath "$dir/$destname"
|
||||
[ "$src" != "$dest" ] && mv -i "$src" "$dir/$destname"
|
||||
setx dest=abspath "$dir/$destname"
|
||||
[ "$src" != "$dest" ] && mv -i "$src" "$dir/$destname"
|
||||
fi
|
||||
else
|
||||
setx destname=replace_ph "$srcname" "$force_date"
|
||||
setx dest=abspath "$dir/$destname"
|
||||
|
|
|
@ -1,13 +1,21 @@
|
|||
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
|
||||
|
||||
function __nutools_host_completion() {
|
||||
local cur prev
|
||||
_get_comp_words_by_ref cur prev
|
||||
if [ "$prev" == "-h" -o "$prev" == "-H" ]; then
|
||||
local cur prev; _get_comp_words_by_ref cur prev
|
||||
[ "$prev" == "-h" -o "$prev" == "-H" -o "$prev" == "--host" ] && _known_hosts_real "$cur"
|
||||
return 0
|
||||
}
|
||||
function __nutools_whost_completion() {
|
||||
local cur prev; _get_comp_words_by_ref cur prev
|
||||
if [ "$prev" == "-h" -o "$prev" == "-H" -o "$prev" == "--host" ]; then
|
||||
_known_hosts_real "$cur"
|
||||
elif [ "$prev" == "-w" -o "$prev" == "--whost" ]; then
|
||||
_known_hosts_real "$cur"
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
complete -F __nutools_host_completion -o default uinst ruinst runs rruns
|
||||
complete -F __nutools_host_completion -o default uinst ruinst runs rruns rwoinst rtoinst
|
||||
complete -F __nutools_whost_completion -o default rwoinst
|
||||
|
||||
if __bash_completion_module_enabled ssh; then
|
||||
shopt -u hostcomplete
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
|
||||
|
||||
# Fichiers externes à inclure. Chacun de ces fichiers peut contenir des
|
||||
# définitions de fonctions et de la variables RULES
|
||||
INCLUDES=()
|
||||
|
||||
# Règles pour le classement des fichiers. Chaque règle est de la forme
|
||||
# pattern:destdir[:renamef]
|
||||
RULES=()
|
|
@ -412,7 +412,7 @@ if test "\$keep" = n; then
|
|||
fi
|
||||
eval \$finish;
|
||||
if test x"\$tmp_archive" = xy; then
|
||||
exec /bin/rm -f "\$thisarch"
|
||||
/bin/rm -f "\$thisarch"; exit \$res
|
||||
else
|
||||
exit \$res
|
||||
fi
|
||||
|
|
|
@ -548,6 +548,19 @@ function ppath() {
|
|||
|
||||
recho "$path"
|
||||
}
|
||||
function ppath2() {
|
||||
# Comme ppath() mais afficher '.' comme '../$dirname'
|
||||
local path="$1" cwd="$2"
|
||||
|
||||
path="$(abspath "$path")" # essayer de normaliser le chemin
|
||||
[ -n "$cwd" ] || cwd="$(pwd)"
|
||||
|
||||
[ "$path" = "$cwd" ] && path="../$(basename -- "$path")"
|
||||
[ "$cwd" != "/" -a "$cwd" != "$HOME" ] && path="${path#$cwd/}"
|
||||
[ "${path#$HOME/}" != "$path" ] && path="~${path#$HOME}"
|
||||
|
||||
recho "$path"
|
||||
}
|
||||
function relpath() {
|
||||
# Afficher le chemin relatif de $1 par rapport à $2. Si $2 n'est pas spécifié,
|
||||
# on prend le répertoire courant. Si $1 ou $2 ne sont pas des chemins absolus,
|
||||
|
|
|
@ -86,9 +86,10 @@ function __po_parse_optdescs() {
|
|||
elif [[ "$optdesc_" == *:: ]]; then
|
||||
option_="${optdesc_%::}"
|
||||
if [[ "$2" == *=* ]]; then
|
||||
# la valeur mentionnée est toujours ignorée
|
||||
# la valeur mentionnée est toujours ignorée. le '=' à la
|
||||
# fin est utilisé par __po_process_options() ci-dessous.
|
||||
name_="${2%%=*}="
|
||||
[ -n "$reset_" ] && eval "$name_="
|
||||
[ -n "$reset_" ] && eval "$name_"
|
||||
else
|
||||
name_="$2"
|
||||
[ -n "$reset_" ] && eval "$name_=()"
|
||||
|
@ -97,9 +98,10 @@ function __po_parse_optdescs() {
|
|||
elif [[ "$optdesc_" == *: ]]; then
|
||||
option_="${optdesc_%:}"
|
||||
if [[ "$2" == *=* ]]; then
|
||||
# la valeur mentionnée est toujours ignorée
|
||||
# la valeur mentionnée est toujours ignorée. le '=' à la
|
||||
# fin est utilisé par __po_process_options() ci-dessous.
|
||||
name_="${2%%=*}="
|
||||
[ -n "$reset_" ] && eval "$name_="
|
||||
[ -n "$reset_" ] && eval "$name_"
|
||||
else
|
||||
name_="$2"
|
||||
[ -n "$reset_" ] && eval "$name_=()"
|
||||
|
@ -108,7 +110,7 @@ function __po_parse_optdescs() {
|
|||
else
|
||||
option_="$optdesc_"
|
||||
name_="$2"
|
||||
[ -n "$reset_" ] && eval "$name_="
|
||||
[ -n "$reset_" ] && eval "${2%%=*}="
|
||||
flag_=
|
||||
fi
|
||||
|
||||
|
|
|
@ -107,7 +107,7 @@ function qvals() {
|
|||
}
|
||||
function qwc() {
|
||||
# Dans la chaine $*, remplacer \ par \\, " par \", $ par \$, ` par \`, puis
|
||||
# quoter la chaine avec ", sauf les wildcards * et ?
|
||||
# quoter la chaine avec ", sauf les wildcards *, ? et [class]
|
||||
# Cela permet de quoter une chaine permettant de glober des fichiers, e.g
|
||||
# eval "ls $(qwc "$value")"
|
||||
# Note: la protection de ! n'est pas effectuée, parce que le comportement du
|
||||
|
@ -119,44 +119,45 @@ function qwc() {
|
|||
s="${s//\"/\\\"}"
|
||||
s="${s//\$/\\\$}"
|
||||
s="${s//\`/\\\`}"
|
||||
local r a b
|
||||
local r a b c
|
||||
while [ -n "$s" ]; do
|
||||
if [[ "$s" == *\** ]]; then
|
||||
if [[ "$s" == *\?* ]]; then
|
||||
a="${s%%\**}"
|
||||
b="${s%%\?*}"
|
||||
if [ ${#a} -lt ${#b} ]; then
|
||||
s="${s#*\*}"
|
||||
r="$r\"$a\"*"
|
||||
else
|
||||
s="${s#*\?}"
|
||||
r="$r\"$b\"?"
|
||||
fi
|
||||
else
|
||||
a="${s%%\**}"
|
||||
s="${s#*\*}"
|
||||
r="$r\"$a\"*"
|
||||
fi
|
||||
elif [[ "$s" == *\?* ]]; then
|
||||
if [[ "$s" == *\** ]]; then
|
||||
a="${s%%\**}"
|
||||
b="${s%%\?*}"
|
||||
if [ ${#a} -lt ${#b} ]; then
|
||||
s="${s#*\*}"
|
||||
r="$r\"$a\"*"
|
||||
else
|
||||
s="${s#*\?}"
|
||||
r="$r\"$b\"?"
|
||||
fi
|
||||
else
|
||||
a="${s%%\?*}"
|
||||
s="${s#*\?}"
|
||||
r="$r\"$a\"?"
|
||||
fi
|
||||
else
|
||||
a=; b=; c=
|
||||
a=; [[ "$s" == *\** ]] && { a="${s%%\**}"; a=${#a}; }
|
||||
b=; [[ "$s" == *\?* ]] && { b="${s%%\?*}"; b=${#b}; }
|
||||
c=; [[ "$s" == *\[* ]] && { c="${s%%\[*}"; c=${#c}; }
|
||||
if [ -z "$a" -a -z "$b" -a -z "$c" ]; then
|
||||
r="$r\"$s\""
|
||||
break
|
||||
fi
|
||||
if [ -n "$a" ]; then
|
||||
[ -n "$b" ] && [ $a -lt $b ] && b=
|
||||
[ -n "$c" ] && [ $a -lt $c ] && c=
|
||||
fi
|
||||
if [ -n "$b" ]; then
|
||||
[ -n "$a" ] && [ $b -lt $a ] && a=
|
||||
[ -n "$c" ] && [ $b -lt $c ] && c=
|
||||
fi
|
||||
if [ -n "$c" ]; then
|
||||
[ -n "$a" ] && [ $c -lt $a ] && a=
|
||||
[ -n "$b" ] && [ $c -lt $b ] && b=
|
||||
fi
|
||||
if [ -n "$a" ]; then # PREFIX*
|
||||
a="${s%%\**}"
|
||||
s="${s#*\*}"
|
||||
[ -n "$a" ] && r="$r\"$a\""
|
||||
r="$r*"
|
||||
elif [ -n "$b" ]; then # PREFIX?
|
||||
a="${s%%\?*}"
|
||||
s="${s#*\?}"
|
||||
[ -n "$a" ] && r="$r\"$a\""
|
||||
r="$r?"
|
||||
elif [ -n "$c" ]; then # PREFIX[class]
|
||||
a="${s%%\[*}"
|
||||
b="${s#*\[}"; b="${b%%\]*}"
|
||||
s="${s:$((${#a} + ${#b} + 2))}"
|
||||
[ -n "$a" ] && r="$r\"$a\""
|
||||
r="$r[$b]"
|
||||
fi
|
||||
done
|
||||
recho_ "$r"
|
||||
}
|
||||
|
@ -191,6 +192,22 @@ function echo_setv() {
|
|||
fi
|
||||
echo "$__s_var=$(qvalr "$*")"
|
||||
}
|
||||
function echo_setv2() {
|
||||
# Afficher la commande qui recrée la variable $1
|
||||
# Cette fonction est équivalente à echo_setv "$1=${!1}"
|
||||
# Si d'autres arguments que le nom de la variable sont spécifiés, cette fonction
|
||||
# se comporte comme echo_setv()
|
||||
local __s_var="$1"; shift
|
||||
if [[ "$__s_var" == *=* ]]; then
|
||||
set -- "${__s_var#*=}" "$@"
|
||||
__s_var="${__s_var%%=*}"
|
||||
fi
|
||||
if [ $# -eq 0 ]; then
|
||||
echo_setv "$__s_var" "${!__s_var}"
|
||||
else
|
||||
echo_setv "$__s_var" "$@"
|
||||
fi
|
||||
}
|
||||
function seta() {
|
||||
# initialiser le tableau $1 avec les valeurs $2..@
|
||||
# note: en principe, la syntaxe est 'seta array values...'. cependant, la
|
||||
|
@ -219,8 +236,8 @@ function echo_seta() {
|
|||
}
|
||||
function echo_seta2() {
|
||||
# Afficher la commande qui recrée le tableau $1
|
||||
# Si des arguments sont spécifiés, cette fonction se comporte comme
|
||||
# echo_seta()
|
||||
# Si d'autres arguments que le nom de tableau sont spécifiés, cette fonction se
|
||||
# comporte comme echo_seta()
|
||||
local __s_var="$1"; shift
|
||||
if [[ "$__s_var" == *=* ]]; then
|
||||
set -- "${__s_var#*=}" "$@"
|
||||
|
|
|
@ -6,15 +6,44 @@
|
|||
# API publique
|
||||
|
||||
function deploy_query() {
|
||||
deploy_query_once "$@" && return 0
|
||||
if [ -n "$QUERYVARS" ]; then
|
||||
deploy_query_recursive "$@" && return 0
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
function deploy_query_recursive() {
|
||||
local DFILE
|
||||
for DFILE in "${QUERYVARS[@]}"; do
|
||||
(
|
||||
deploy_loadconf --no-auto-update
|
||||
deploy_query_once "$@" && exit 0
|
||||
if [ -n "$QUERYVARS" ]; then
|
||||
deploy_query_recursive "$@" && exit 0
|
||||
fi
|
||||
exit 1
|
||||
) && return 0
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
function deploy_query_once() {
|
||||
# Afficher le résultat d'une requête
|
||||
local alv
|
||||
eval "set -- $(getopt -ov: -lallow-vars: -- "$@")"
|
||||
local alv sov sdv slv sof sdf slf
|
||||
eval "set -- $(getopt -ov:odl -lallow-vars:,object-vars,dest-vars,link-vars,of:,object-func:,df:,dest-func:,lf:,link-func: -- "$@")"
|
||||
while [ -n "$1" ]; do
|
||||
case "$1" in
|
||||
-v|--allow-vars)
|
||||
array_split alv "$2" ,
|
||||
shift; shift
|
||||
;;
|
||||
-o|--object-vars) sov=1; shift;;
|
||||
-d|--dest-vars) sdv=1; shift;;
|
||||
-l|--link-vars) slv=1; shift;;
|
||||
--of|--object-func) sof="$2"; shift; shift;;
|
||||
--df|--dest-func) sdf="$2"; shift; shift;;
|
||||
--lf|--link-func) slf="$2"; shift; shift;;
|
||||
--) shift; break;;
|
||||
*) break;;
|
||||
esac
|
||||
|
@ -27,7 +56,7 @@ function deploy_query() {
|
|||
DEST|SOURCE)
|
||||
if [ -n "$otype" ]; then
|
||||
deploy_is_type "$otype" || {
|
||||
qvals false "$otype: invalid type"
|
||||
[ "$format" == shell ] && qvals false "$otype: invalid type"
|
||||
return 2
|
||||
}
|
||||
fi
|
||||
|
@ -35,7 +64,7 @@ function deploy_query() {
|
|||
*)
|
||||
if [ -n "$qtype" ]; then
|
||||
deploy_is_type "$qtype" || {
|
||||
qvals false "$qtype: invalid type"
|
||||
[ "$format" == shell ] && qvals false "$qtype: invalid type"
|
||||
return 3
|
||||
}
|
||||
fi
|
||||
|
@ -43,12 +72,12 @@ function deploy_query() {
|
|||
esac
|
||||
if [ -n "$ltype" ]; then
|
||||
deploy_is_link "$ltype" || {
|
||||
qvals false "$ltype: invalid link type"
|
||||
[ "$format" == shell ] && qvals false "$ltype: invalid link type"
|
||||
return 4
|
||||
}
|
||||
fi
|
||||
[ -n "$term" ] || {
|
||||
qvals false "search term required"
|
||||
[ "$format" == shell ] && qvals false "search term required"
|
||||
return 5
|
||||
}
|
||||
|
||||
|
@ -57,23 +86,40 @@ function deploy_query() {
|
|||
edebug "=== search type DEST"
|
||||
edebug "term=$term, otype=$otype"
|
||||
deploy_search_artifact object type "$term" "$otype" host || {
|
||||
qvals false "artifact not found"
|
||||
[ "$format" == shell ] && qvals false "artifact not found"
|
||||
return 1
|
||||
}
|
||||
edebug "object=$object, type=$type"
|
||||
deploy_search_link link "$type" "$ltype" || {
|
||||
qvals false "link not found"
|
||||
[ "$format" == shell ] && qvals false "link not found"
|
||||
return 1
|
||||
}
|
||||
|
||||
deploy_show_values object object "$format" shell alv
|
||||
deploy_show_values type otype "$format" shell alv
|
||||
deploy_show_values link ltype "$format" shell alv
|
||||
deploy_show_links "$object" "$link" "$profile" "$format" "" alv
|
||||
if [ -n "$sov" ]; then
|
||||
deploy_copy_object_values vs "$object" "$type"
|
||||
deploy_show_values vs "$type" "$format" shell alv
|
||||
deploy_show_attrs "$object" "$type" "$format" alv vars "$sof"
|
||||
fi
|
||||
if [ -n "$sdv" ]; then
|
||||
local -a pons pgns ons gns ans ovs os; local an av o
|
||||
deploy_prepare_copy_link_attrs pons pgns ons gns "$object" "$link" "$profile"
|
||||
deploy_copy_link_attr_values hvs host "$object" "$link" "$profile" pons pgns ons gns
|
||||
for hv in "${hvs[@]}"; do
|
||||
deploy_copy_object_values hs "$hv" host
|
||||
deploy_show_values hs host "$format" shell alv
|
||||
deploy_show_attrs "$hn" host "$format" alv vars "$sdf"
|
||||
done
|
||||
fi
|
||||
deploy_show_links "$object" "$link" "$profile" "$format" "" alv vars "$slf"
|
||||
[ "$format" == shell ] && echo true
|
||||
return 0
|
||||
;;
|
||||
SOURCE)
|
||||
# XXX implémenter
|
||||
[ "$format" == shell ] && echo true
|
||||
return 0
|
||||
;;
|
||||
*)
|
||||
|
@ -83,9 +129,10 @@ function deploy_query() {
|
|||
deploy_show_values type otype "$format" shell alv
|
||||
deploy_show_values vs "$type" "$format" "" alv
|
||||
deploy_show_attrs "$object" "$type" "$format" alv
|
||||
[ "$format" == shell ] && echo true
|
||||
return 0
|
||||
fi
|
||||
qvals false "artifact not found"
|
||||
[ "$format" == shell ] && qvals false "artifact not found"
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
|
@ -224,10 +271,7 @@ function deploy_show_values() {
|
|||
[ -n "$ff" -a "$f" != "$ff" ] && return
|
||||
|
||||
case "$f" in
|
||||
shell)
|
||||
[ -n "$5" ] && echo "$t=()"
|
||||
deploy_dump_values "$t" vs
|
||||
;;
|
||||
shell) deploy_dump_values "$t" vs;;
|
||||
line) array_to_lines vs;;
|
||||
*) array_join vs "$f";;
|
||||
esac
|
||||
|
@ -244,16 +288,17 @@ function deploy_show_attrs() {
|
|||
local -a ons gns ans vs; local an
|
||||
deploy_prepare_copy_attrs ons gns "$o" "$t"
|
||||
deploy_copy_attr_names ans "$o" "$t" ons gns
|
||||
[ -n "$5" ] && echo_seta "${t}_vars" "${ans[@]}"
|
||||
for an in "${ans[@]}"; do
|
||||
if [ -n "$4" ]; then
|
||||
if ! array_isempty "$4"; then
|
||||
array_contains alv "$an" || continue
|
||||
fi
|
||||
[ "$f" == shell ] && echo "$an=()"
|
||||
fi
|
||||
deploy_copy_attr_values vs "$an" "$o" "$t" ons
|
||||
deploy_dump_values "$an" vs
|
||||
done
|
||||
[ -n "$6" ] && echo "$6"
|
||||
}
|
||||
|
||||
function deploy_show_links() {
|
||||
|
@ -272,6 +317,7 @@ function deploy_show_links() {
|
|||
|
||||
deploy_prepare_copy_link_attrs pons pgns ons gns "$o" "$l" "$p"
|
||||
deploy_copy_link_attr_names ans "$o" "$l" "$p" pons pgns ons gns
|
||||
[ -n "$7" -a "$f" == shell ] && echo_seta "${l}_vars" "${ans[@]}"
|
||||
for an in "${ans[@]}"; do
|
||||
deploy_copy_link_attr_values avs "$an" "$o" "$l" "$p" pons pgns ons gns
|
||||
if [ "$an" == host ]; then
|
||||
|
@ -287,6 +333,7 @@ function deploy_show_links() {
|
|||
deploy_show_values avs "$an" "$f" shell alv
|
||||
fi
|
||||
done
|
||||
[ -n "$8" -a "$f" == shell ] && echo "$8"
|
||||
done
|
||||
}
|
||||
|
||||
|
|
57
lib/ulib/vcs
57
lib/ulib/vcs
|
@ -456,11 +456,64 @@ function git_update() {
|
|||
return $?
|
||||
fi
|
||||
|
||||
local orig_branch restore_branch remote rbranch pbranch
|
||||
local -a branches
|
||||
local branch orig_branch restore_branch remote rbranch pbranch
|
||||
local -a branches prbranches crbranches dbranches
|
||||
|
||||
array_from_lines prbranches "$(git_list_rbranches)"
|
||||
git fetch -p "$@" || return
|
||||
array_from_lines crbranches "$(git_list_rbranches)"
|
||||
|
||||
# vérifier s'il n'y a pas des branches distantes qui ont été supprimées
|
||||
for branch in "${prbranches[@]}"; do
|
||||
if ! array_contains crbranches "$branch"; then
|
||||
array_add dbranches "${branch#*/}"
|
||||
fi
|
||||
done
|
||||
if [ ${#dbranches[*]} -gt 0 ]; then
|
||||
eimportant "One or more distant branches where deleted"
|
||||
for branch in "${dbranches[@]}"; do
|
||||
if git_have_branch "$branch"; then
|
||||
if ! ask_yesno "Do you want to delete local branch $branch?" X; then
|
||||
array_del dbranches "$branch"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
fi
|
||||
if [ ${#dbranches[*]} -gt 0 ]; then
|
||||
array_from_lines branches "$(git_list_branches)"
|
||||
branch="$(git_get_branch)"
|
||||
if array_contains dbranches "$branch"; then
|
||||
# si la branche courante est l'une des branches à supprimer, il faut
|
||||
# basculer vers develop ou master
|
||||
local swto
|
||||
if [ -z "$swto" ] && array_contains branches develop && ! array_contains dbranches develop; then
|
||||
swto=develop
|
||||
fi
|
||||
if [ -z "$swto" ] && array_contains branches master && ! array_contains dbranches master; then
|
||||
swto=master
|
||||
fi
|
||||
if ! git_check_cleancheckout; then
|
||||
echo "* There are uncommitted local changes. However current branch is slated for removal.
|
||||
Make your verifications then delete the local branches:
|
||||
${swto:+$(qvals git checkout "$swto")
|
||||
}$(qvals git branch -D "${dbranches[@]}")"
|
||||
return 1
|
||||
fi
|
||||
if [ -n "$swto" ]; then
|
||||
git checkout -q "$swto"
|
||||
else
|
||||
echo "* Current branch is slated for removal but I don't know to which branch I should switch first.
|
||||
Make your choice then delete the local branches:
|
||||
$(qvals git branch -D "${dbranches[@]}")"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
for branch in "${dbranches[@]}"; do
|
||||
git branch -D "$branch"
|
||||
done
|
||||
fi
|
||||
|
||||
# intégrer les modifications dans les branches locales
|
||||
if ! git_check_cleancheckout; then
|
||||
branch="$(git_get_branch)"
|
||||
remote="$(git_get_branch_remote "$branch")"
|
||||
|
|
131
lib/ulib/woinst
131
lib/ulib/woinst
|
@ -410,27 +410,52 @@ OPTIONS
|
|||
PREFIX=value
|
||||
Spécifier une valeur pour un préfixe, plutôt que de laisser uprefix
|
||||
l'autodétecter. Utiliser uprefix -l pour une liste de préfixes valides.
|
||||
-b Redémarrer les instances en mode bounce.
|
||||
Par défaut, les instances sont arrêtées avant le déploiement, et
|
||||
redémarrées après
|
||||
-W Ne déployer que les resources web. Implique -n
|
||||
-n Ne pas tagger les bundles déployés avec un numéro de version. Par
|
||||
défaut, l'utilisateur est invité à compléter des informations telles
|
||||
que n° de version et date de release si ces informations ne sont pas
|
||||
--prefix
|
||||
Corriger les chemins des variables qui commencent par des préfixes
|
||||
valides (c'est la valeur par défaut). Utiliser 'uprefix -l' pour avoir
|
||||
une liste de préfixes valides
|
||||
--no-prefix
|
||||
Ne jamais corriger un chemin.
|
||||
-W, --webres
|
||||
Ne déployer que les resources web. Implique -n
|
||||
-n, --no-tag
|
||||
Ne pas tagger les bundles déployés avec un numéro de version. En temps
|
||||
normal, l'utilisateur est invité à compléter des informations telles que
|
||||
n° de version et date de release si ces informations ne sont pas
|
||||
disponible.
|
||||
-x CMD
|
||||
-d, --active-dbconfig DBCONFIG
|
||||
Spécifier le profil de connexion à utiliser par défaut pour tous les
|
||||
eomodels du bundle. S'il faut un profil différent en fonction de l'eomodel, utiliser l'option -m
|
||||
-m, --active-dbconfig-map EOMODEL:DBCONFIG
|
||||
Spécifier un mapping entre un nom d'eomodel et le profil de connexion à
|
||||
utiliser. Pour les eomodels qui ne sont pas spécifiés, la valeur par
|
||||
défaut est utilisée si elle existe. Il est possible de spécifier
|
||||
plusieurs mappings en les séparant par des virgules.
|
||||
--stop-start
|
||||
Redémarrer les instances de la manière classique: les instances sont
|
||||
arrêtées avant le déploiement, et redémarrées après. C'est la valeur par
|
||||
défaut.
|
||||
-b, --bounce
|
||||
Redémarrer les instances en mode bounce.
|
||||
-x, --exec CMD
|
||||
Exécuter la commande CMD après avoir effectué le déploiement"
|
||||
}
|
||||
|
||||
local bounce webinst notag scripts istmpdir tmpdir
|
||||
scripts=()
|
||||
local istmpdir tmpdir autoprefix=1 bounce webinst notag default_dbconfig
|
||||
local -a dbconfigs scripts
|
||||
parse_opts "${PRETTYOPTS[@]}" \
|
||||
--help '$exit_with __woinst_display_help' \
|
||||
-b,--bounce bounce=1 \
|
||||
-W,--webres webinst=1 \
|
||||
-n,--notag notag=1 \
|
||||
-x:,--exec: scripts \
|
||||
--is-tmpdir '$istmpdir=1; tmpdir=.' \
|
||||
--prefix autoprefix=1 \
|
||||
--no-prefix autoprefix= \
|
||||
-W,--webres webinst=1 \
|
||||
--tag notag= \
|
||||
-n,--no-tag notag=1 \
|
||||
-d:,--active-dbconfig: default_dbconfig= \
|
||||
-m:,--active-dbconfig-map: dbconfigs \
|
||||
--stop-start bounce= \
|
||||
-b,--bounce bounce=1 \
|
||||
-x:,--exec: scripts \
|
||||
@ args -- "$@" &&
|
||||
set -- "${args[@]}" || {
|
||||
eerror "$args"
|
||||
|
@ -457,7 +482,8 @@ OPTIONS
|
|||
for src in "${@:-.}"; do
|
||||
if [[ "$src" == *=* ]]; then
|
||||
splitvar "$src" name value
|
||||
array_add variables "$name"
|
||||
array_addu variables "$name"
|
||||
[ -n "$autoprefix" ] && value="$(expand_prefix "$value")"
|
||||
_setv "$name" "$value"
|
||||
else
|
||||
src="$(abspath "$src")"
|
||||
|
@ -469,6 +495,19 @@ OPTIONS
|
|||
copied=1
|
||||
fi
|
||||
if [ -d "$src" ]; then
|
||||
setx name=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/$name.woa" ]; then
|
||||
src="$src/target/$name.woa"
|
||||
elif [ -d "$src/target/$name.framework" ]; then
|
||||
src="$src/target/$name.framework"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
if endswith "$src" .framework; then
|
||||
is_wofwkdir "$src" || {
|
||||
eerror "Framework invalide: $(ppath "$src")"
|
||||
|
@ -504,6 +543,68 @@ OPTIONS
|
|||
done
|
||||
eend
|
||||
|
||||
# Corriger les eomodelds
|
||||
array_fix_paths dbconfigs ,
|
||||
if [ -n "$default_dbconfig" -o ${#dbconfigs[*]} -gt 0 ]; then
|
||||
etitle "Configuration des eomodels"
|
||||
local -a eonames eomodels tmpeomodels
|
||||
local eom dbc eoname eomodel dbconfig found
|
||||
|
||||
estep "Calcul de la liste des eomodels"
|
||||
if [ ${#dbconfigs[*]} -eq 0 ]; then
|
||||
for src in "${frameworks[@]}"; do
|
||||
array_from_lines tmpeomodels "$(find "$src" -type d -name "*.eomodeld")"
|
||||
for eom in "${tmpeomodels[@]}"; do
|
||||
array_addu eonames "$(basename -- "$eom")"
|
||||
done
|
||||
done
|
||||
for src in "${applications[@]}"; do
|
||||
array_from_lines tmpeomodels "$(find "$src" -type d -name "*.eomodeld")"
|
||||
for eom in "${tmpeomodels[@]}"; do
|
||||
array_addu eonames "$(basename -- "$eom")"
|
||||
done
|
||||
done
|
||||
else
|
||||
for dbc in "${dbconfigs[@]}"; do
|
||||
splitpair "$dbc" eom dbc
|
||||
[ "${eom%.eomodeld}" != "$eom" ] || eom="$eom.eomodeld"
|
||||
array_addu eonames "$(basename -- "$eom")"
|
||||
done
|
||||
fi
|
||||
for eom in "${eonames[@]}"; do
|
||||
for src in "${frameworks[@]}"; do
|
||||
array_from_lines tmpeomodels "$(find "$src" -type d -name "$eom")"
|
||||
array_extendu eomodels tmpeomodels
|
||||
done
|
||||
for src in "${applications[@]}"; do
|
||||
array_from_lines tmpeomodels "$(find "$src" -type d -name "$eom")"
|
||||
array_extendu eomodels tmpeomodels
|
||||
done
|
||||
done
|
||||
|
||||
for eomodel in "${eomodels[@]}"; do
|
||||
setx eoname=basename -- "$eomodel"
|
||||
if [ ! -f "$eomodel/index.eomodeld" ]; then
|
||||
ewarn "$eomodel: eomode invalide"
|
||||
continue
|
||||
fi
|
||||
found=
|
||||
for dbc in "${dbconfigs[@]}"; do
|
||||
splitpair "$dbc" eom dbconfig
|
||||
[ "${eom%.eomodeld}" != "$eom" ] || eom="$eom.eomodeld"
|
||||
if [ "$(basename -- "$eom")" == "$eoname" ]; then
|
||||
found="$dbconfig"
|
||||
break
|
||||
fi
|
||||
done
|
||||
[ -z "$found" -a -n "$default_dbconfig" ] && found="$default_dbconfig"
|
||||
if [ -n "$found" ]; then
|
||||
estep "$eomodel [$found]"
|
||||
sed -i "/^ *activeDatabaseConfigName *=/s/=.*;/=\"$found\";/" "$eomodel/index.eomodeld"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
# Tagger les bundles
|
||||
if [ -z "$webinst" -a -z "$notag" ]; then
|
||||
etitle "Tagger les bundles"
|
||||
|
|
|
@ -0,0 +1,267 @@
|
|||
#!/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 pyulib/pyulib
|
||||
|
||||
function display_help() {
|
||||
uecho "$scriptname: Déploiement distant avec toinst
|
||||
|
||||
USAGE
|
||||
$scriptname [-h host] [-T tmproot] <archive|dir> [-- options de toinst]
|
||||
|
||||
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
|
||||
-T, --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.
|
||||
--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
|
||||
Spécifier le nom de la configuration à utiliser pour l'interrogation de
|
||||
la configuration locale de déploiement. Par défaut, utiliser le nom
|
||||
'rtoinst'
|
||||
-p, --deploy-profile PROFILE
|
||||
Spécifier le profil à utiliser pour l'interrogation de la configuration
|
||||
locale de déploiement. Par défaut, aucun profil n'est sélectionné."
|
||||
}
|
||||
|
||||
__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
|
||||
}
|
||||
|
||||
action=deploy
|
||||
tmproot=
|
||||
SSH=
|
||||
hosts=()
|
||||
deploy_enable=1
|
||||
deploy_confname=rtoinst
|
||||
deploy_profile=
|
||||
parse_opts "${PRETTYOPTS[@]}" \
|
||||
--help '$exit_with display_help' \
|
||||
-T:,--tmproot: tmproot= \
|
||||
-S:,--ssh: SSH= \
|
||||
-h:,-H:,--host: hosts \
|
||||
--deploy deploy_enable=1 \
|
||||
--no-deploy deploy_enable= \
|
||||
-c:,--deploy-config: deploy_confname= \
|
||||
-p:,--deploy-profile: deploy_profile= \
|
||||
@ args -- "$@" && set -- "${args[@]}" || die "$args"
|
||||
|
||||
: "${SSH:=ssh}"
|
||||
|
||||
## webapp à déployer et hôtes sur lesquels faire le déploiement
|
||||
confirm_webapp=
|
||||
if [ $# -eq 0 ] || [[ "$1" == -* ]]; then
|
||||
# pas d'argument, ou c'est une option (qui fait donc partie des arguments de toinst)
|
||||
[ -d WEB-INF ] && webapp=. || webapp=
|
||||
confirm_webapp=1
|
||||
else
|
||||
webapp="$1"
|
||||
fi
|
||||
|
||||
toinst_options=()
|
||||
if array_isempty hosts && [ -n "$deploy_enable" -a -n "$webapp" ]; then
|
||||
urequire deploy
|
||||
deploy_setconf "$deploy_confname"
|
||||
if deploy_loadconf; then
|
||||
setxx waname=abspath "$webapp" // basename --
|
||||
if eval "$(deploy_query -v host,wamap,protect DEST webapp rtoinst_deploy "$deploy_profile" shell "$waname")"; then
|
||||
msg="$waname: cette webapp sera déployée vers les hôtes suivants:
|
||||
$(array_to_lines host "" " ")"
|
||||
if [ -n "$wamap" -o -n "$protect" ]; then
|
||||
msg="$msg
|
||||
avec le(s) paramètre(s) suivant(s):"
|
||||
[ -n "$wamap" ] && msg="$msg
|
||||
--wamap $(qval "$wamap")"
|
||||
[ -n "$protect" ] && msg="$msg
|
||||
--protect $(qval "$protect")"
|
||||
fi
|
||||
check_interaction -c && einfo "$msg"
|
||||
ask_any "Voulez-vous continuer?" Oq || die
|
||||
array_copy hosts host
|
||||
[ -n "$wamap" ] && array_add toinst_options --wamap "$wamap"
|
||||
[ -n "$protect" ] && array_add toinst_options --protect "$protect"
|
||||
if [ -n "$confirm_webapp" ]; then
|
||||
confirm_webapp=
|
||||
set -- "$webapp" "$@"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -n "$confirm_webapp" ]; then
|
||||
# pas d'argument, ou c'est une option (qui fait donc partie des arguments de toinst)
|
||||
read_value "Veuillez entrer la webapp à déployer" webapp "$webapp" O
|
||||
set -- "$webapp" "$@"
|
||||
fi
|
||||
|
||||
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
|
||||
webapps=()
|
||||
while [ $# -gt 0 ]; do
|
||||
if [ "$1" == "--" ]; then
|
||||
# début des options de toinst
|
||||
shift
|
||||
break
|
||||
elif [[ "$1" == -* ]]; then
|
||||
# début des options de toinst
|
||||
break
|
||||
fi
|
||||
|
||||
osrc="$1"; shift
|
||||
setx src=abspath "$osrc"
|
||||
setx srcname=basename -- "$src"
|
||||
if [ -f "$src" ] && is_archive "$src"; then
|
||||
setx waname=get_archive_appname "$src"
|
||||
estep "$(ppath "$src") --> $waname"
|
||||
wadir="$workdir/$waname"
|
||||
mkdir "$wadir"
|
||||
extract_archive "$src" "$wadir" || die
|
||||
src="$wadir"
|
||||
elif [ -d "$src" ]; then
|
||||
estep "$(ppath2 "$src")"
|
||||
cp_R "$src" "$workdir/$srcname" || die
|
||||
elif [ -e "$src" ]; then
|
||||
die "$osrc: fichier invalide"
|
||||
else
|
||||
die "$osrc: fichier ou répertoire introuvable"
|
||||
fi
|
||||
|
||||
array_add webapps "$srcname"
|
||||
done
|
||||
|
||||
estep "Copie de l'environnement de déploiement"
|
||||
mkdir "$workdir/lib"
|
||||
ulibsync "$workdir/lib"
|
||||
cp "$scriptdir/toinst" "$workdir"
|
||||
chmod +x "$workdir/toinst"
|
||||
|
||||
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" -- ./toinst --is-tmpdir || die
|
||||
eend
|
||||
|
||||
## Déploiement
|
||||
|
||||
# sur l'hôte distant, ne rendre non interactif qu'à partir de -yy
|
||||
rinteraction=$__interaction
|
||||
[ $rinteraction -lt 2 ] && rinteraction=$(($rinteraction + 1))
|
||||
|
||||
for host in "${hosts[@]}"; do
|
||||
if [ "$host" == "localhost" ]; then
|
||||
etitle "Déploiement sur l'hôte local"
|
||||
"$archive" ${tmproot:+--tmproot "$tmproot"} -- "${webapps[@]}" "$@" "${toinst_options[@]}"
|
||||
eend
|
||||
else
|
||||
splituserhost "$host" user host
|
||||
[ -n "$user" ] || user=root
|
||||
|
||||
etitle "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
|
||||
${UTOOLS_LANG:+UTOOLS_LANG='$UTOOLS_LANG'; export UTOOLS_LANG
|
||||
}$(qvals "./$archivename" ${tmproot:+--tmproot "$tmproot"} -- "${webapps[@]}" "$@" "${toinst_options[@]}")"
|
||||
|
||||
eend
|
||||
fi
|
||||
done
|
98
ruinst
98
ruinst
|
@ -56,37 +56,11 @@ OPTIONS
|
|||
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 'ruinst'"
|
||||
Cette option permet de spécifier le nom de la configuration locale de
|
||||
déploiement à utiliser pour effectuer la requête. Par défaut, utiliser
|
||||
le nom 'ruinst'"
|
||||
}
|
||||
|
||||
set_defaults pubkeys
|
||||
|
||||
action=deploy
|
||||
confuser=
|
||||
uses_su=
|
||||
tmproot=
|
||||
SSH=
|
||||
force_make_archive=
|
||||
hosts=()
|
||||
deploy_enable=1
|
||||
deploy_confname=ruinst
|
||||
parse_opts "${PRETTYOPTS[@]}" \
|
||||
--help '$exit_with display_help' \
|
||||
-C,--configure-user action=configure \
|
||||
--configure: '$set@ confuser;action=configure' \
|
||||
--uses-su uses_su=1 \
|
||||
-T:,--tmproot: tmproot= \
|
||||
-S:,--ssh: SSH= \
|
||||
--force-make-archive force_make_archive=1 \
|
||||
-h:,-H:,--host: hosts \
|
||||
--deploy deploy_enable=1 \
|
||||
--no-deploy deploy_enable= \
|
||||
-c:,--deploy-config deploy_confname= \
|
||||
@ args -- "$@" && set -- "${args[@]}" || die "$args"
|
||||
|
||||
: "${SSH:=ssh}"
|
||||
|
||||
__PARSED_HOSTS=()
|
||||
__PARSED_FILES=()
|
||||
function parse_hostsfile() {
|
||||
|
@ -150,6 +124,33 @@ function fix_hosts() {
|
|||
array_map hosts __dot_is_localhost
|
||||
}
|
||||
|
||||
set_defaults pubkeys
|
||||
|
||||
action=deploy
|
||||
confuser=
|
||||
uses_su=
|
||||
tmproot=
|
||||
SSH=
|
||||
force_make_archive=
|
||||
hosts=()
|
||||
deploy_enable=1
|
||||
deploy_confname=ruinst
|
||||
parse_opts "${PRETTYOPTS[@]}" \
|
||||
--help '$exit_with display_help' \
|
||||
-C,--configure-user action=configure \
|
||||
--configure: '$set@ confuser;action=configure' \
|
||||
--uses-su uses_su=1 \
|
||||
-T:,--tmproot: tmproot= \
|
||||
-S:,--ssh: SSH= \
|
||||
--force-make-archive force_make_archive=1 \
|
||||
-h:,-H:,--host: hosts \
|
||||
--deploy deploy_enable=1 \
|
||||
--no-deploy deploy_enable= \
|
||||
-c:,--deploy-config deploy_confname= \
|
||||
@ args -- "$@" && set -- "${args[@]}" || die "$args"
|
||||
|
||||
: "${SSH:=ssh}"
|
||||
|
||||
################################################################################
|
||||
# Configuration de l'accès par clé aux hôtes
|
||||
|
||||
|
@ -218,36 +219,43 @@ fi
|
|||
################################################################################
|
||||
# Déploiement
|
||||
|
||||
make_archive=
|
||||
|
||||
## Répertoire à déployer
|
||||
src="$1"
|
||||
if [ -z "$src" ] || [[ "$src" == -* ]]; then
|
||||
## Répertoires à déployer et hôtes sur lesquels faire le déploiement
|
||||
confirm_src=
|
||||
if [ $# -eq 0 ] || [[ "$1" == -* ]] || [[ "$1" == *=* ]]; then
|
||||
# pas d'argument, ou c'est une option (qui fait donc partie des arguments de uinst)
|
||||
read_value "Entrez le répertoire à déployer" src "."
|
||||
src=.
|
||||
confirm_src=1
|
||||
else
|
||||
# Enlever le répertoire à déployer. Le reste est pour uinst
|
||||
src="$1"
|
||||
shift
|
||||
fi
|
||||
|
||||
## Hôtes sur lesquels faire le déploiement
|
||||
if array_isempty hosts && [ -n "$deploy_enable" ]; then
|
||||
if array_isempty hosts && [ -n "$deploy_enable" -a -n "$src" ]; then
|
||||
urequire deploy
|
||||
deploy_setconf "$deploy_confname"
|
||||
if deploy_loadconf; then
|
||||
setxx module=abspath "$src" // basename --
|
||||
if eval "$(deploy_query -v host DEST module ruinst_deploy "" shell "$module")"; then
|
||||
check_interaction -c && einfo "Ce module sera déployé vers les hôtes suivants:
|
||||
setxx srcname=abspath "$src" // basename --
|
||||
if eval "$(deploy_query -v host DEST module ruinst_deploy "" shell "$srcname")"; then
|
||||
check_interaction -c && einfo "$srcname: ce module sera déployé vers les hôtes suivants:
|
||||
$(array_to_lines host "" " ")"
|
||||
ask_any "Voulez-vous continuer?" Oq || die
|
||||
array_copy hosts host
|
||||
confirm_src=
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -n "$confirm_src" ]; then
|
||||
# pas d'argument, ou c'est une option (qui fait donc partie des arguments de uinst)
|
||||
read_value "Entrez le répertoire à déployer" src "$src" O
|
||||
fi
|
||||
|
||||
array_isempty hosts && read_value "Entrez une liste d'hôtes séparés par ':'" hosts "localhost"
|
||||
fix_hosts
|
||||
|
||||
## Création de l'archive?
|
||||
make_archive=
|
||||
if [ -n "$force_make_archive" ]; then
|
||||
make_archive=1
|
||||
else
|
||||
|
@ -265,13 +273,14 @@ if [ -n "$make_archive" ]; then
|
|||
ac_set_tmpfile archive
|
||||
archivename="$(basename "$archive")"
|
||||
|
||||
etitle "Création de l'archive pour le déploiement" \
|
||||
"$scriptdir/mkusfx" --tmp-archive --self-contained -o "$archive" "$src" || die
|
||||
etitle "Création de l'archive pour le déploiement"
|
||||
"$scriptdir/mkusfx" --tmp-archive --self-contained -o "$archive" "$src" || die
|
||||
eend
|
||||
fi
|
||||
|
||||
## Déploiement
|
||||
|
||||
# sur l'hôte distant, ne rendre interactif qu'à partir de -yy
|
||||
# sur l'hôte distant, ne rendre non interactif qu'à partir de -yy
|
||||
rinteraction=$__interaction
|
||||
[ $rinteraction -lt 2 ] && rinteraction=$(($rinteraction + 1))
|
||||
|
||||
|
@ -289,8 +298,10 @@ for host in "${hosts[@]}"; do
|
|||
[ -n "$user" ] || user=root
|
||||
|
||||
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
|
||||
|
@ -299,6 +310,7 @@ __tlevel=$(qval "$__tlevel")
|
|||
export __interaction __estack __tlevel
|
||||
${UTOOLS_LANG:+UTOOLS_LANG='$UTOOLS_LANG'; export UTOOLS_LANG
|
||||
}$(qvals "./$archivename" ${tmproot:+--tmproot "$tmproot"} -- MYHOST="$host" "$@")"
|
||||
|
||||
eend
|
||||
fi
|
||||
done
|
||||
|
|
292
rwoinst
292
rwoinst
|
@ -9,21 +9,11 @@ function display_help() {
|
|||
USAGE
|
||||
$scriptname [-H host] [-T tmproot] <file|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
|
||||
-C, --configure-user
|
||||
--configure USER [--uses-su]
|
||||
Ne pas faire le déploiement. Configurer uniquement la connexion par clé
|
||||
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
|
||||
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
|
||||
|
@ -32,7 +22,6 @@ OPTIONS
|
|||
Spécifier le programme à utiliser pour la connection par ssh.
|
||||
-h, --host hosts
|
||||
-h, --host @hostsfile
|
||||
-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
|
||||
|
@ -45,6 +34,17 @@ OPTIONS
|
|||
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.
|
||||
--deploy
|
||||
--no-deploy
|
||||
Autoriser (respectivement interdire) l'utilisation de la configuration
|
||||
|
@ -54,34 +54,12 @@ OPTIONS
|
|||
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'"
|
||||
pour effectuer la requête. Par défaut, utiliser le nom 'rwoinst'
|
||||
-p, --deploy-profile PROFILE
|
||||
Spécifier le profil à utiliser pour l'interrogation de la configuration
|
||||
locale de déploiement. Par défaut, aucun profil n'est sélectionné."
|
||||
}
|
||||
|
||||
set_defaults pubkeys
|
||||
|
||||
action=deploy
|
||||
confuser=
|
||||
uses_su=
|
||||
tmproot=
|
||||
SSH=
|
||||
hosts=()
|
||||
deploy_enable=1
|
||||
deploy_confname=rwoinst
|
||||
parse_opts "${PRETTYOPTS[@]}" \
|
||||
--help '$exit_with display_help' \
|
||||
-C,--configure-user action=configure \
|
||||
--configure: '$set@ confuser;action=configure' \
|
||||
--uses-su uses_su=1 \
|
||||
-T:,--tmproot: tmproot= \
|
||||
-S:,--ssh: SSH= \
|
||||
-h:,-H:,--host: hosts \
|
||||
--deploy deploy_enable=1 \
|
||||
--no-deploy deploy_enable= \
|
||||
-c:,--deploy-config deploy_confname= \
|
||||
@ args -- "$@" && set -- "${args[@]}" || die "$args"
|
||||
|
||||
SSH="${SSH:-ssh}"
|
||||
|
||||
__PARSED_HOSTS=()
|
||||
__PARSED_FILES=()
|
||||
function parse_hostsfile() {
|
||||
|
@ -145,47 +123,149 @@ function fix_hosts() {
|
|||
array_map hosts __dot_is_localhost
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Configuration de l'accès par clé aux hôtes
|
||||
function deploy_to() {
|
||||
local archive="$1" host="$2" tmproot="$3"
|
||||
shift; shift; shift
|
||||
|
||||
if [ "$action" == "configure" ]; then
|
||||
args=(${confuser:+--configure "$confuser"} ${uses_su:+--uses-su} -S "$SSH")
|
||||
for host in "${hosts[@]}"; do
|
||||
args=("${args[@]}" -H "$host")
|
||||
done
|
||||
exec "$scriptdir/ruinst" -C "${args[@]}"
|
||||
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=()
|
||||
deploy_enable=1
|
||||
deploy_confname=rwoinst
|
||||
deploy_profile=
|
||||
parse_opts "${PRETTYOPTS[@]}" \
|
||||
--help '$exit_with display_help' \
|
||||
-T:,--tmproot: tmproot= \
|
||||
-S:,--ssh: SSH= \
|
||||
-h:,-H:,--host: hosts \
|
||||
-w:,-W:,--whost: whosts \
|
||||
--deploy deploy_enable=1 \
|
||||
--no-deploy deploy_enable= \
|
||||
-c:,--deploy-config deploy_confname= \
|
||||
-p:,--deploy-profile: deploy_profile= \
|
||||
@ args -- "$@" && set -- "${args[@]}" || die "$args"
|
||||
|
||||
: "${SSH:=ssh}"
|
||||
|
||||
## Bundle à déployer et hôtes sur lesquels faire le déploiement
|
||||
confirm_bundle=
|
||||
if [ $# -eq 0 ] || [[ "$1" == -* ]] || [[ "$1" == *=* ]]; then
|
||||
# pas d'argument, ou c'est une option (qui fait donc partie des arguments de woinst)
|
||||
case "$(basename -- "$(pwd)")" in
|
||||
*.woa|*.framework) bundle=.;;
|
||||
*) bundle=;;
|
||||
esac
|
||||
confirm_bundle=1
|
||||
else
|
||||
bundle="$1"
|
||||
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
|
||||
woinst_options=()
|
||||
if array_isempty hosts && [ -n "$deploy_enable" -a -n "$bundle" ]; 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 "" " ")"
|
||||
setxx bundlename=abspath "$bundle" // basename --
|
||||
host=(); bounce=; notag=; exec=; dbconfig=; dbconfigmap=
|
||||
if eval "$(deploy_query -v host,bounce,notag,exec,dbconfig,dbconfigmap DEST wobundle rwoinst_bundle "$deploy_profile" shell "$bundlename")"; then
|
||||
array_copy deploy_hosts host
|
||||
deploy_options=()
|
||||
[ -n "$bounce" ] && array_add deploy_options -b
|
||||
[ -n "$notag" ] && array_add deploy_options -n
|
||||
if [ -n "$exec" ]; then
|
||||
for x in "${exec[@]}"; do
|
||||
array_add deploy_options -x "$x"
|
||||
done
|
||||
fi
|
||||
[ -n "$dbconfig" ] && array_add deploy_options -d "$dbconfig"
|
||||
if [ -n "$dbconfigmap" ]; then
|
||||
for m in "${dbconfigmap[@]}"; do
|
||||
array_add deploy_options -m "$m"
|
||||
done
|
||||
fi
|
||||
deploy_whosts=()
|
||||
host=(); destdir=
|
||||
if eval "$(deploy_query -v host,destdir DEST wobundle rwoinst_webres "$deploy_profile" shell "$bundlename")"; then
|
||||
for wh in "${host[@]}"; do
|
||||
array_add deploy_whosts "$wh:$destdir"
|
||||
done
|
||||
fi
|
||||
msg="$bundlename: ce bundle sera déployé vers les hôtes suivants:
|
||||
$(array_to_lines deploy_hosts "" " ")"
|
||||
if [ ${#deploy_whosts[*]} -gt 0 -o ${#deploy_options[*]} -gt 0 ]; then
|
||||
msg="$msg
|
||||
avec le(s) paramètre(s) suivant(s):"
|
||||
[ ${#deploy_whosts[*]} -gt 0 ] && msg="$msg
|
||||
$(array_to_lines deploy_whosts "" " --whost ")"
|
||||
[ ${#deploy_options[*]} -gt 0 ] && msg="$msg
|
||||
$(qvals "${deploy_options[@]}")"
|
||||
fi
|
||||
check_interaction -c && einfo "$msg"
|
||||
ask_any "Voulez-vous continuer?" Oq || die
|
||||
array_copy hosts host
|
||||
array_extend hosts deploy_hosts
|
||||
array_extend woinst_options deploy_options
|
||||
array_extend whosts deploy_whosts
|
||||
if [ -n "$confirm_bundle" ]; then
|
||||
confirm_bundle=
|
||||
set -- "$bundle" "$@"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -n "$confirm_bundle" ]; then
|
||||
# pas d'argument, ou c'est une option (qui fait donc partie des arguments de woinst)
|
||||
read_value "Veuillez entrer la bundle à déployer" bundle "$bundle" O
|
||||
set -- "$bundle" "$@"
|
||||
fi
|
||||
|
||||
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"
|
||||
|
||||
etitle "Création du répertoire de travail"
|
||||
ac_set_tmpdir workdir
|
||||
|
||||
bundles=()
|
||||
while [ -n "$1" ]; do
|
||||
if [ "$1" == "--" ]; then
|
||||
|
@ -203,6 +283,19 @@ while [ -n "$1" ]; do
|
|||
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
|
||||
|
@ -210,7 +303,7 @@ while [ -n "$1" ]; do
|
|||
else
|
||||
die "N'est pas un bundle valide: $(ppath "$src")"
|
||||
fi
|
||||
estep "$(ppath "$src")"
|
||||
estep "$(ppath2 "$src")"
|
||||
cp_R "$src" "$workdir" || die
|
||||
else
|
||||
die "Fichier ou répertoire introuvable: $src"
|
||||
|
@ -221,55 +314,34 @@ while [ -n "$1" ]; do
|
|||
done
|
||||
|
||||
estep "Copie de l'environnement de déploiement"
|
||||
ulibsync "$workdir"
|
||||
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"
|
||||
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
|
||||
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
|
||||
"$scriptdir/mkusfx" --bare --tmp-archive -o "$archive" "$workdir" -- ./woinst.sh --is-tmpdir "${bundles[@]}" || die
|
||||
|
||||
eend
|
||||
|
||||
## Déploiement
|
||||
|
||||
# sur l'hôte distant, ne rendre interactif qu'à partir de -yy
|
||||
rinteraction=$__interaction
|
||||
[ $rinteraction -lt 2 ] && rinteraction=$(($rinteraction + 1))
|
||||
|
||||
etitle "Déploiement des bundles"
|
||||
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
|
||||
${UTOOLS_LANG:+UTOOLS_LANG='$UTOOLS_LANG'; export UTOOLS_LANG
|
||||
}$(qvals "./$archivename" ${tmproot:+--tmproot "$tmproot"} -- MYHOST="$host" "$@")"
|
||||
eend
|
||||
fi
|
||||
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
|
||||
|
|
|
@ -0,0 +1,171 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 mode: python -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
|
||||
|
||||
u"""Afficher les lignes d'un fichier en mettant en surbrillance certains patterns"""
|
||||
|
||||
import sys, subprocess, re
|
||||
from collections import OrderedDict
|
||||
|
||||
def bluef(line, *ignored): return '\x1B[34m%s\x1B[0m' % line
|
||||
def greenf(line, *ignored): return '\x1B[32m%s\x1B[0m' % line
|
||||
def yellowf(line, *ignored): return '\x1B[33m%s\x1B[0m' % line
|
||||
def redf(line, *ignored): return '\x1B[31m%s\x1B[0m' % line
|
||||
def nonef(line, *ignored): return re.sub('\x1B\[.*?m', '', line)
|
||||
|
||||
DEFAULT_PATTERNS = OrderedDict([
|
||||
(r'(?i)error', redf),
|
||||
(r'(?i)warn(ing)?', yellowf),
|
||||
(r'(?i)info', bluef),
|
||||
(None, nonef),
|
||||
])
|
||||
FORMATS = OrderedDict([
|
||||
('blue', bluef),
|
||||
('green', greenf),
|
||||
('yellow', yellowf),
|
||||
('red', redf),
|
||||
('none', nonef),
|
||||
])
|
||||
FORMAT_ALIASES = {
|
||||
'b': 'blue',
|
||||
'g': 'green',
|
||||
'y': 'yellow',
|
||||
'r': 'red',
|
||||
'': 'none',
|
||||
}
|
||||
|
||||
def strip_nl(s):
|
||||
if s is None: return None
|
||||
elif s.endswith("\r\n"): s = s[:-2]
|
||||
elif s.endswith("\n"): s = s[:-1]
|
||||
elif s.endswith("\r"): s = s[:-1]
|
||||
return s
|
||||
|
||||
def run_tailor(inputfile=None, follow=False, patterns=None):
|
||||
if inputfile is None or not follow:
|
||||
if inputfile is None:
|
||||
inf = sys.stdin
|
||||
close = False
|
||||
else:
|
||||
inf = open(inputfile, 'rb')
|
||||
close = True
|
||||
def next_line():
|
||||
try:
|
||||
while True:
|
||||
try: line = inf.readline()
|
||||
except: break
|
||||
if line == '': break
|
||||
yield line
|
||||
finally:
|
||||
if close: inf.close()
|
||||
else:
|
||||
def next_line():
|
||||
p = subprocess.Popen(
|
||||
['tail', '-f', inputfile],
|
||||
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||
while True:
|
||||
try: line = p.stdout.readline()
|
||||
except: break
|
||||
if line == '': break
|
||||
yield line
|
||||
if patterns is None: patterns = DEFAULT_PATTERNS
|
||||
|
||||
for line in next_line():
|
||||
line = nonef(strip_nl(line))
|
||||
func = False
|
||||
mo = None
|
||||
for p, f in patterns.items():
|
||||
if p is None:
|
||||
func = f
|
||||
mo = None
|
||||
break
|
||||
mo = re.search(p, line)
|
||||
if mo is not None:
|
||||
func = f
|
||||
break
|
||||
if func is not False:
|
||||
line = func(line, mo)
|
||||
sys.stdout.write(line)
|
||||
sys.stdout.write('\n')
|
||||
|
||||
if __name__ == '__main__':
|
||||
from argparse import ArgumentParser, HelpFormatter
|
||||
if sys.argv[1:2] == ['--compat']:
|
||||
# Avec l'argument --compat, désactiver la classe FancyHelpFormatter qui
|
||||
# se base sur une API non documentée
|
||||
sys.argv = sys.argv[0:1] + sys.argv[2:]
|
||||
FancyHelpFormatter = HelpFormatter
|
||||
else:
|
||||
class FancyHelpFormatter(HelpFormatter):
|
||||
"""Comme HelpFormatter, mais ne touche pas aux lignes qui commencent par les
|
||||
caractères '>>>'. Cela permet de mixer du texte formaté et du texte non
|
||||
formaté.
|
||||
"""
|
||||
def _fill_text(self, text, width, indent):
|
||||
return ''.join([indent + line for line in text.splitlines(True)])
|
||||
def _split_lines(self, text, width):
|
||||
lines = ['']
|
||||
for line in text.splitlines():
|
||||
if line.startswith('>>>'):
|
||||
lines.append(line)
|
||||
lines.append('')
|
||||
else:
|
||||
lines[-1] += '\n' + line
|
||||
lines = filter(None, lines)
|
||||
texts = []
|
||||
for line in lines:
|
||||
if line.startswith('>>>'):
|
||||
texts.append(line[3:])
|
||||
else:
|
||||
texts.extend(super(FancyHelpFormatter, self)._split_lines(line, width))
|
||||
return texts
|
||||
AP = ArgumentParser(
|
||||
usage=u"%(prog)s [-f] [INPUTFILE]",
|
||||
description=__doc__,
|
||||
formatter_class=FancyHelpFormatter,
|
||||
)
|
||||
AP.set_defaults(inputfile=None, follow=False, patterns=None, defaults=True)
|
||||
pattern_help = u"""\
|
||||
Ajouter une spécification de pattern et le format dans lequel il doit être affiché.
|
||||
Le format par défaut est red. Les formats valides sont:
|
||||
>>> %(formats)s""" % {
|
||||
'formats': ', '.join(FORMATS.keys()),
|
||||
}
|
||||
AP.add_argument('-e', '--pattern', action='append', dest='patterns', metavar='PATTERN:FORMAT',
|
||||
help=pattern_help)
|
||||
default_patterns = [u"%s:%s" % (p or '', f.__name__[:-1]) for (p, f) in DEFAULT_PATTERNS.items()]
|
||||
no_defaults_help = u"""\
|
||||
Ne pas ajouter les patterns par défaut. Sans cette option, les patterns par défaut sont:
|
||||
%(default_patterns)s""" % {
|
||||
'default_patterns': '\n'.join([u">>> %s" % pattern for pattern in default_patterns]),
|
||||
}
|
||||
AP.add_argument('-z', '--no-defaults', action='store_false', dest='defaults',
|
||||
help=no_defaults_help)
|
||||
AP.add_argument('-f', '--follow', action='store_true', dest='follow',
|
||||
help=u"Suivre le contenu du fichier spécifié")
|
||||
AP.add_argument('inputfile', metavar='INPUTFILE', nargs='?',
|
||||
help=u"Fichier qu'il faut afficher ou dont il faut suivre le contenu")
|
||||
o = AP.parse_args()
|
||||
|
||||
if o.patterns is None:
|
||||
patterns = DEFAULT_PATTERNS
|
||||
else:
|
||||
patterns = OrderedDict()
|
||||
for pf in o.patterns:
|
||||
mo = re.match('(.*):([a-zA-Z]*)$', pf)
|
||||
if mo is not None:
|
||||
p = mo.group(1)
|
||||
of = mo.group(2)
|
||||
else:
|
||||
p = pf
|
||||
of = 'red'
|
||||
if p == '': p = None
|
||||
f = of.lower()
|
||||
f = FORMAT_ALIASES.get(f, f)
|
||||
if f not in FORMATS:
|
||||
raise ValueError("%s: format invalide" % of)
|
||||
patterns[p] = FORMATS[f]
|
||||
if o.defaults:
|
||||
for p, f in DEFAULT_PATTERNS.items():
|
||||
patterns.setdefault(p, f)
|
||||
|
||||
run_tailor(o.inputfile, o.follow, patterns)
|
|
@ -0,0 +1,663 @@
|
|||
#!/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 xmlsupport
|
||||
|
||||
function display_help() {
|
||||
uecho "$scriptname: Déployer une ou plusieurs webapps vers Tomcat
|
||||
|
||||
USAGE
|
||||
$scriptname [options] <archive|dir>...
|
||||
|
||||
OPTIONS
|
||||
-c, --config CONFIG
|
||||
Spécifier un fichier de configuration qui contient les informations
|
||||
spécifiées par les options ci-dessous: TOMCAT_PROFILE, CATALINA_BASE,
|
||||
TOMCAT_USER, TOMCAT_GROUP, TOMCAT_VERSION, MANAGER_URL, MANAGER_USER,
|
||||
MANAGER_PASSWORD, WAMAP, BACKUP, RESTART
|
||||
-C, --config-profile TOMCAT_PROFILE
|
||||
Spécifier le profil de configuration à utiliser. Cette valeur détermine
|
||||
la façon dont sont calculés CATALINA_BASE, TOMCAT_USER, TOMCAT_GROUP et
|
||||
TOMCAT_VERSION. Les valeurs valides sont:
|
||||
* debian:tomcatV
|
||||
Tomcat installé par 'apt-get install tomcatV'. L'alias 'd:V' est
|
||||
aussi supporté, e.g 'debian:tomcat7' ou 'd:8'
|
||||
* runs:NAME
|
||||
Tomcat installé par 'runs tomcat/V name=NAME'. Le suffixe NAME est
|
||||
le nom de base des fichiers de tomcat. Pour spécifier le cas échéant
|
||||
la version de Tomcat, il faut utiliser l'option -V ci-dessous.
|
||||
L'alias NAME sans le préfixe runs: est supporté aussi.
|
||||
Le profil par défaut est calculé comme suit:
|
||||
* Si un répertoire de la forme /var/lib/tomcatV existe alors il s'agit
|
||||
de debian:tomcatV.
|
||||
* Si le lien /opt/tomcat --> /opt/apache-tomcat-V existe, vérifier
|
||||
l'existence du script /etc/init.d/tomcatV. Si le script existe, alors
|
||||
utiliser runs:tomcatV comme profil. Sinon, utiliser runs:tomcat.
|
||||
* Sinon, aucun profil n'est sélectionné, et il faut spécifier
|
||||
manuellement les options -d, -U, -G, -V
|
||||
-d, --catalina-base CATALINA_BASE
|
||||
Spécifier le répertoire de base des configurations de Tomcat. La valeur
|
||||
par défaut est celle de CATALINA_HOME. Cette option n'a normalement pas
|
||||
besoin d'être spécifiée.
|
||||
-U, --tomcat-user TOMCAT_USER
|
||||
-G, --tomcat-group TOMCAT_GROUP
|
||||
Spécifier l'utilisateur et le groupe propriétaires des fichiers de
|
||||
Tomcat. Ces options n'ont normalement pas besoin d'être spécifiées.
|
||||
-V, --tomcat-version TOMCAT_VERSION
|
||||
Spécifier la version de tomcat installée, e.g 8.0.37 pour une version
|
||||
complète ou simplement 8 si on ne donne que la version majeure.
|
||||
Cette option peut s'avérer nécessaire avec le profil runs:tomcat bien
|
||||
que les meilleurs efforts soient faits pour détecter la valeur
|
||||
effective.
|
||||
-g, --manager-url MANAGER_URL
|
||||
Spécifier l'url du manager, e.g http://localhost:8080/manager/text
|
||||
Par défaut, le fichier server.xml est consulté pour connaitre sur quel
|
||||
port écoute le serveur.
|
||||
-u, --user MANAGER_USER
|
||||
-p, --password MANAGER_PASSWORD
|
||||
Spécifier le compte et le mot de passe à utiliser pour piloter le
|
||||
manager Tomcat, notamment pour redémarrer l'application venant d'être
|
||||
déployée. Ce compte doit avoir le rôle manager-script à partir de Tomcat
|
||||
6.0.30, et le rôle manager-gui dans les version antérieurs. Par défaut,
|
||||
le fichier tomcat-users.xml est consulté pour avoir cette information.
|
||||
-m, --wamap WAMAPS
|
||||
Ajouter un ou plusieurs mappings de la forme src:dest. Avec ce mapping,
|
||||
la webapp src est déployée avec le nom dest. Plusieurs mappings peuvent
|
||||
être spécifiés en les séparant par des virgules. Si src est mentionné
|
||||
plusieurs fois, e.g src:dest1,src:dest2 alors la webapp src est déployée
|
||||
plusieurs fois avec des noms distincts.
|
||||
--exclude EXCLUDES
|
||||
--replace-excludes EXCLUDES
|
||||
Spécifier un ensemble de fichier à exclure de la source lors du
|
||||
déploiement. La variante --replace-excludes permet de construire la
|
||||
liste des fichiers à exclure depuis zéro. La liste par défaut est:
|
||||
${DEFAULT_EXCLUDES[*]}
|
||||
--protect PROTECTS
|
||||
Spécifier un ensemble de fichier à protéger dans la destination: ils ne
|
||||
sont jamais écrasés par les fichiers sources. Cela permet de gérer des
|
||||
applications qui écrivent des fichiers dans leur répertoire.
|
||||
--rsync-option RSYNC_OPTIONS
|
||||
--replace-rsync-options RSYNC_OPTIONS
|
||||
Spécifier les options de rsync à utiliser pour le déploiement. La
|
||||
variante --replace-rsync-options permet de construire la liste des
|
||||
options depuis zéro. La liste par défaut est:
|
||||
${DEFAULT_RSYNC_OPTIONS[*]}
|
||||
-b, --backup
|
||||
--no-backup
|
||||
Avant le déploiement du service numérique, faire (resp. ne pas faire)
|
||||
une sauvegarde des fichiers actuellement déployés.
|
||||
-B, --backup-only
|
||||
Ne pas faire le déploiement. Faire uniquement la sauvegarde.
|
||||
-n, --no-restart
|
||||
Après le déploiement de la webapp, ne pas redémarrer l'application.
|
||||
-r, --restart-only
|
||||
Ne pas faire le déploiement. Redémarrer uniquement l'application.
|
||||
--fake
|
||||
Afficher simplement ce qui serait fait. Ne pas le faire réellement.
|
||||
--config-template
|
||||
Créer un modèle de configuration dans le répertoire des webapp
|
||||
spécifiées. Si aucune webapp n'est spécifiée, créer le fichier dans le
|
||||
répertoire courant."
|
||||
}
|
||||
|
||||
DEFAULT_EXCLUDES=(/.git/ /.toinst.conf)
|
||||
DEFAULT_RSYNC_OPTIONS=(-rptL --delete)
|
||||
|
||||
VARS=(
|
||||
TOMCAT_PROFILE
|
||||
CATALINA_BASE TOMCAT_USER TOMCAT_GROUP TOMCAT_VERSION
|
||||
MANAGER_URL MANAGER_USER MANAGER_PASSWORD
|
||||
BACKUP RESTART
|
||||
)
|
||||
ARRAYS=(
|
||||
WAMAPS
|
||||
EXCLUDES REPLACE_EXCLUDES
|
||||
PROTECTS
|
||||
RSYNC_OPTIONS REPLACE_RSYNC_OPTIONS
|
||||
)
|
||||
function __reset_vars() {
|
||||
local var
|
||||
for var in "${VARS[@]}"; do
|
||||
eval "$var="
|
||||
done
|
||||
for var in "${ARRAYS[@]}"; do
|
||||
eval "$var=()"
|
||||
done
|
||||
}
|
||||
function __dump_vars() {
|
||||
local var
|
||||
for var in "${VARS[@]}"; do
|
||||
eecho "$(echo_setv2 "$var")"
|
||||
done
|
||||
for var in "${ARRAYS[@]}"; do
|
||||
eecho "$(echo_seta2 "$var")"
|
||||
done
|
||||
}
|
||||
|
||||
function use_manager_script() {
|
||||
local v="$TOMCAT_VERSION"
|
||||
if [ -z "$v" ]; then
|
||||
return 0
|
||||
elif [[ "$v" == 6.0.* ]]; then
|
||||
if [ "${v#6.0.}" -ge 30 ]; then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
elif [ "${v%%.*}" -gt 6 ]; then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
function parse_server() {
|
||||
local -a lines
|
||||
local serverxml port
|
||||
serverxml="$CATALINA_BASE/conf/server.xml"
|
||||
array_from_lines lines "$(xpathtool -g "/Server/Service[@name='Catalina']/Connector/@port" "$serverxml")"
|
||||
port="${lines[0]}"
|
||||
if [ -n "$port" ]; then
|
||||
if use_manager_script; then
|
||||
MANAGER_URL="http://localhost:$port/manager/text"
|
||||
else
|
||||
MANAGER_URL="http://localhost:$port/manager/html"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
function parse_tomcat_users() {
|
||||
local -a lines
|
||||
local usersxml role
|
||||
usersxml="$CATALINA_BASE/conf/tomcat-users.xml"
|
||||
if use_manager_script; then
|
||||
role=manager-script
|
||||
else
|
||||
role=manager-gui
|
||||
fi
|
||||
array_from_lines lines "$(xpathtool -g "/tomcat-users/user[contains(@roles,'$role')]/@username" "$usersxml")"
|
||||
MANAGER_USER="${lines[0]}"
|
||||
if [ -n "$MANAGER_USER" ]; then
|
||||
array_from_lines lines "$(xpathtool -g "/tomcat-users/user[@username='$MANAGER_USER']/@password" "$usersxml")"
|
||||
MANAGER_PASSWORD="${lines[0]}"
|
||||
fi
|
||||
}
|
||||
|
||||
function build_rsync_options() {
|
||||
local -a excludes protects; local exclude protect
|
||||
if [ ${#REPLACE_EXCLUDES[*]} -gt 0 ]; then
|
||||
array_copy excludes REPLACE_EXCLUDES
|
||||
else
|
||||
array_copy excludes DEFAULT_EXCLUDES
|
||||
fi
|
||||
array_extend excludes EXCLUDES
|
||||
array_copy protects PROTECTS
|
||||
if [ ${#REPLACE_RSYNC_OPTIONS[*]} -gt 0 ]; then
|
||||
array_copy rsync_options REPLACE_RSYNC_OPTIONS
|
||||
else
|
||||
array_copy rsync_options DEFAULT_RSYNC_OPTIONS
|
||||
fi
|
||||
array_extend rsync_options RSYNC_OPTIONS
|
||||
|
||||
local toinstconf="$1/.toinst.conf"
|
||||
if [ -f "$toinstconf" ]; then
|
||||
eval "$(
|
||||
EXCLUDES=()
|
||||
PROTECTS=()
|
||||
RSYNC_OPTIONS=()
|
||||
source "$toinstconf"
|
||||
array_extend excludes EXCLUDES
|
||||
array_extend protects PROTECTS
|
||||
array_extend rsync_options RSYNC_OPTIONS
|
||||
echo_seta2 excludes
|
||||
echo_seta2 protects
|
||||
echo_seta2 rsync_options
|
||||
)"
|
||||
fi
|
||||
for exclude in "${excludes[@]}"; do
|
||||
array_add rsync_options --exclude "$exclude"
|
||||
done
|
||||
for protect in "${PROTECTS[@]}"; do
|
||||
array_add rsync_options -f "P $protect"
|
||||
done
|
||||
}
|
||||
|
||||
args=(%
|
||||
--help '$exit_with display_help'
|
||||
--config-template action=config-template
|
||||
--private-parse-server '$action=parse; parse_server=1'
|
||||
--private-parse-tomcat-users '$action=parse; parse_tomcat_users=1'
|
||||
--is-tmpdir '$istmpdir=1; tmpdir=.'
|
||||
-c:,--config: config=
|
||||
-C:,--config-profile: tomcat_profile=
|
||||
-d:,--catalina-base:,--catalina-home: catalina_base=
|
||||
-U:,--tomcat-user: tomcat_user=
|
||||
-G:,--tomcat-group: tomcat_group=
|
||||
-V:,--tomcat-version: tomcat_version=
|
||||
-g:,--manager-url: manager_url=
|
||||
-u:,--user: manager_user=
|
||||
-p:,--password: manager_password=
|
||||
-m:,--wamap: wamaps
|
||||
--exclude: excludes
|
||||
--replace-excludes: replace_excludes
|
||||
--protect: protects
|
||||
--rsync-option: rsync_options
|
||||
--replace-rsync-options: replace_rsync_options
|
||||
-b,--backup backup=1
|
||||
--no-backup backup=0
|
||||
-B,--backup-only action=backup
|
||||
--restart restart=1
|
||||
-n,--no-restart restart=0
|
||||
-r,--restart-only action=restart
|
||||
--fake fake=1
|
||||
)
|
||||
parse_args "$@"; set -- "${args[@]}"
|
||||
|
||||
[ -n "$action" ] || action=deploy
|
||||
|
||||
if [ "$action" == parse ]; then
|
||||
CATALINA_BASE="$1"
|
||||
TOMCAT_VERSION="$2"
|
||||
if [ -n "$parse_server" ]; then
|
||||
parse_server
|
||||
echo_setv2 MANAGER_URL
|
||||
fi
|
||||
if [ -n "$parse_tomcat_users" ]; then
|
||||
parse_tomcat_users
|
||||
echo_setv2 MANAGER_USER
|
||||
echo_setv2 MANAGER_PASSWORD
|
||||
fi
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Charger la configuration
|
||||
__reset_vars
|
||||
if [ -n "$config" ]; then
|
||||
eval "$(
|
||||
__reset_vars
|
||||
CATALINA_HOME=
|
||||
source "$config" 2>/dev/null || exit 1
|
||||
[ -n "$CATALINA_BASE" ] || CATALINA_BASE="$CATALINA_HOME"
|
||||
__dump_vars
|
||||
)"
|
||||
fi
|
||||
|
||||
# Traiter la ligne de commande
|
||||
for var in "${VARS[@]}"; do
|
||||
lvar="${var,,}"
|
||||
if [ -n "${!lvar}" ]; then
|
||||
setv "$var" "${!lvar}"
|
||||
fi
|
||||
done
|
||||
[ -n "$RESTART" ] || RESTART=1 # valeur par défaut
|
||||
normyesvals BACKUP RESTART
|
||||
for var in "${ARRAYS[@]}"; do
|
||||
lvar="${var,,}"
|
||||
if ! array_isempty "$lvar"; then
|
||||
array_copy "$var" "$lvar"
|
||||
fi
|
||||
done
|
||||
array_fix_paths WAMAPS ,
|
||||
|
||||
# Calculer le profil de connexion
|
||||
if [ -z "$TOMCAT_PROFILE" ]; then
|
||||
for v in 8 7; do
|
||||
if [ -d /var/lib/tomcat$v ]; then
|
||||
TOMCAT_PROFILE=debian:tomcat$v
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
if [ -z "$TOMCAT_PROFILE" ]; then
|
||||
v=
|
||||
if [ -L /opt/tomcat ]; then
|
||||
setx v=readlink /opt/tomcat
|
||||
setx v=basename -- "$v"
|
||||
else
|
||||
array_lsdirs ts /opt "apache-tomcat-*"
|
||||
if [ ${#ts[*]} -gt 0 ]; then
|
||||
[ -n "$CATALINA_BASE" ] || CATALINA_BASE="${ts[0]}"
|
||||
v="$CATALINA_BASE"
|
||||
[ -L "$v" ] && setx v=readlink "$v"
|
||||
setx v=basename -- "$v"
|
||||
fi
|
||||
fi
|
||||
if [ -n "$v" ] && [[ "$v" == apache-tomcat-* ]]; then
|
||||
v=${v#apache-tomcat-}
|
||||
mv=${v%%.*}
|
||||
if [ -f /etc/init.d/tomcat$mv ]; then
|
||||
TOMCAT_PROFILE=runs:tomcat$mv
|
||||
else
|
||||
TOMCAT_PROFILE=runs:tomcat
|
||||
fi
|
||||
[ -z "$TOMCAT_VERSION" ] && TOMCAT_VERSION="$v"
|
||||
fi
|
||||
fi
|
||||
if [ -n "$TOMCAT_PROFILE" ]; then
|
||||
case "$TOMCAT_PROFILE" in
|
||||
debian:*|runs:*) ;;
|
||||
d:*) TOMCAT_PROFILE="debian:tomcat${TOMCAT_PROFILE#d:}";;
|
||||
*) TOMCAT_PROFILE="runs:$TOMCAT_PROFILE";;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Calculer les valeurs dérivées du profil de connexion
|
||||
case "$TOMCAT_PROFILE" in
|
||||
debian:*)
|
||||
t="${TOMCAT_PROFILE#debian:}"
|
||||
v="${t#tomcat}"
|
||||
[ -z "$CATALINA_BASE" ] && CATALINA_BASE="/var/lib/$t"
|
||||
eval "$(
|
||||
setv "${t^^}_USER"
|
||||
setv "${t^^}_GROUP"
|
||||
source "/etc/default/$t" 2>/dev/null
|
||||
eval "echo tomcat_user=\"\$${t^^}_USER\""
|
||||
eval "echo tomcat_group=\"\$${t^^}_GROUP\""
|
||||
)"
|
||||
[ -z "$TOMCAT_USER" ] && TOMCAT_USER="$tomcat_user"
|
||||
[ -z "$TOMCAT_GROUP" ] && TOMCAT_GROUP="$tomcat_group"
|
||||
[ -z "$TOMCAT_VERSION" ] && TOMCAT_VERSION="$v"
|
||||
;;
|
||||
runs:*)
|
||||
v="${TOMCAT_PROFILE#runs:tomcat}"
|
||||
if [ -z "$CATALINA_BASE" -a "$v" != "$TOMCAT_PROFILE" ]; then
|
||||
array_lsdirs ts /opt "apache-tomcat-$v*"
|
||||
CATALINA_BASE="${ts[0]}"
|
||||
fi
|
||||
if [ -z "$CATALINA_BASE" ]; then
|
||||
if [ -L /opt/tomcat ]; then
|
||||
setx CATALINA_BASE=readlink /opt/tomcat
|
||||
else
|
||||
array_lsdirs ts /opt "apache-tomcat-*"
|
||||
CATALINA_BASE="${ts[0]}"
|
||||
fi
|
||||
fi
|
||||
name="${TOMCAT_PROFILE#runs:}"
|
||||
eval "$(
|
||||
TOMCAT_USER=
|
||||
source "/etc/default/$name" 2>/dev/null
|
||||
echo tomcat_user="$TOMCAT_USER"
|
||||
)"
|
||||
[ -z "$TOMCAT_USER" ] && TOMCAT_USER="$tomcat_user"
|
||||
if [ -z "$TOMCAT_VERSION" ]; then
|
||||
v="$CATALINA_BASE"
|
||||
[ -L "$v" ] && setx v=readlink "$v"
|
||||
setx v=basename -- "$v"
|
||||
if [[ "$v" == apache-tomcat-* ]]; then
|
||||
TOMCAT_VERSION="${v#apache-tomcat-}"
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
# Calculer les valeurs dérivées des fichiers de $CATALINA_BASE
|
||||
|
||||
if [ -n "$CATALINA_BASE" -a -n "$TOMCAT_VERSION" ]; then
|
||||
if [ -z "$MANAGER_URL" -o -z "$MANAGER_USER" ]; then
|
||||
# lire les fichiers de configuratione et déterminer MANAGER_URL,
|
||||
# MANAGER_USER et MANAGER_PASSWORD
|
||||
if is_root; then
|
||||
[ -z "$MANAGER_URL" ] && parse_server
|
||||
[ -z "$MANAGER_USER" ] && parse_tomcat_users
|
||||
else
|
||||
args=()
|
||||
[ -z "$MANAGER_URL" ] && array_add args --private-parse-server
|
||||
[ -z "$MANAGER_USER" ] && array_add args --private-parse-tomcat-users
|
||||
array_add args "$CATALINA_BASE" "$TOMCAT_VERSION"
|
||||
eval "$(run_as root --noexec "${args[@]}")"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# A partir de la liste des webapps et de WAMAPS, construire une liste de couples
|
||||
# waname:src pour la sauvegarde et/ou le déploiement
|
||||
|
||||
[ -n "$fake" -o "$action" == config-template ] && will_deploy= || will_deploy=1
|
||||
|
||||
if [ $# -eq 0 -a -n "$will_deploy" ]; then
|
||||
[ -d WEB-INF ] && src=. || src=
|
||||
read_value "Veuillez entrer la webapp à déployer" src "$src" O
|
||||
set -- "$src"
|
||||
elif [ $# -eq 0 -a "$action" == config-template ]; then
|
||||
[ -d WEB-INF ] && set .
|
||||
fi
|
||||
|
||||
srcs=()
|
||||
[ -n "$istmpdir" ] || ac_set_tmpdir tmpdir
|
||||
for src in "$@"; do
|
||||
if [ -f "$src" ] && is_archive "$src"; then
|
||||
setx waname=get_archive_appname "$src"
|
||||
wadir="$tmpdir/$waname"
|
||||
mkdir "$wadir"
|
||||
if extract_archive "$src" "$wadir"; then
|
||||
array_add srcs "$wadir"
|
||||
else
|
||||
eerror "$src: erreur lors de l'extraction de l'archive"
|
||||
fi
|
||||
elif [ -d "$src" ]; then
|
||||
array_add srcs "$(abspath "$src")"
|
||||
elif [ -e "$src" ]; then
|
||||
eerror "$src: fichier invalide"
|
||||
else
|
||||
eerror "$src: fichier ou répertoire introuvable"
|
||||
fi
|
||||
done
|
||||
[ ${#srcs[*]} -gt 0 -o -z "$will_deploy" ] || die
|
||||
|
||||
deploymaps=()
|
||||
for src in "${srcs[@]}"; do
|
||||
setx waname=basename -- "$src"
|
||||
found=
|
||||
for wamap in "${WAMAPS[@]}"; do
|
||||
splitpair "$wamap" from to
|
||||
if [ "$waname" == "$from" ]; then
|
||||
found=1
|
||||
array_add deploymaps "$to:$src"
|
||||
fi
|
||||
done
|
||||
if [ -z "$found" ]; then
|
||||
array_add deploymaps "$waname:$src"
|
||||
fi
|
||||
done
|
||||
|
||||
################################################################################
|
||||
# Maintenant, nous pouvons faire les actions
|
||||
|
||||
if [ "$action" == config-template ]; then
|
||||
if [ ${#deploymaps[*]} -gt 0 ]; then
|
||||
toinstconfname=.toinst.conf
|
||||
else
|
||||
toinstconfname=toinst.conf
|
||||
deploymaps=(:.)
|
||||
fi
|
||||
for deploymap in "${deploymaps[@]}"; do
|
||||
splitpair "$deploymap" waname src
|
||||
toinstconf="$src/$toinstconfname"
|
||||
if [ -f "$toinstconf" ]; then
|
||||
estepi "$(ppath "$toinstconf"): configuration déjà existante"
|
||||
else
|
||||
estep "$(ppath "$toinstconf")"
|
||||
echo >"$toinstconf" "# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
|
||||
|
||||
# Fichiers à exclure de la source lors du déploiement
|
||||
#EXCLUDES=()
|
||||
|
||||
# Fichiers à protéger dans la destination lors du déploiement
|
||||
#PROTECTS=()
|
||||
|
||||
# Options supplémentaires de rsync à utiliser pour le déploiement
|
||||
#RSYNC_OPTIONS=()"
|
||||
fi
|
||||
done
|
||||
exit 0
|
||||
fi
|
||||
|
||||
## Sauvegarde
|
||||
if [ -n "$BACKUP" -o "$action" == backup ]; then
|
||||
[ -n "$CATALINA_BASE" -o -z "$will_deploy" ] || die "Vous devez spécifier l'option --catalina-base"
|
||||
|
||||
home_bckdir="$HOME/tomcat-backups"
|
||||
if [ -n "$istmpdir" ]; then
|
||||
# déploiement distant: sauvegarder dans le répertoire utilisateur
|
||||
default_bckdir="$home_bckdir"
|
||||
else
|
||||
# déploiement local: ça dépend de la webapp
|
||||
default_bckdir=
|
||||
fi
|
||||
setx cwd=pwd
|
||||
|
||||
etitle "Sauvegarde des webapps"
|
||||
for deploymap in "${deploymaps[@]}"; do
|
||||
splitpair "$deploymap" waname src
|
||||
wadir="$CATALINA_BASE/webapps/$waname"
|
||||
|
||||
if [ ! -d "$wadir" ]; then
|
||||
einfo "$waname: la webapp n'a pas encore été déployée. elle ne sera pas sauvegardée"
|
||||
continue
|
||||
fi
|
||||
|
||||
bckdir="$default_bckdir"
|
||||
if [ -z "$bckdir" ]; then
|
||||
if withinpath "$tmpdir" "$src"; then
|
||||
bckdir="$home_bckdir"
|
||||
elif withinpath "$src" "$cwd"; then
|
||||
setx bckdir=dirname "$src"
|
||||
else
|
||||
bckdir=.
|
||||
fi
|
||||
fi
|
||||
mkdir -p "$bckdir"
|
||||
|
||||
setx base=date +%y%m%d
|
||||
i=0
|
||||
bckname="$base.$profile$i-$waname"
|
||||
while [ -d "$bckdir/$bckname" ]; do
|
||||
let i=$i+1
|
||||
bckname="$base.$profile$i-$waname"
|
||||
done
|
||||
|
||||
if [ -n "$fake" ]; then
|
||||
evalx qvals rsync -a "$wadir/" "$bckdir/$bckname" // eecho
|
||||
else
|
||||
estep "$wadir --> $(ppath "$bckdir/$bckname")"
|
||||
if ! rsync -a "$wadir/" "$bckdir/$bckname"; then
|
||||
ewarn "Une erreur s'est produite pendant la sauvegarde"
|
||||
ask_yesno "Voulez-vous continuer le déploiement?" N || die
|
||||
fi
|
||||
fi
|
||||
done
|
||||
eend
|
||||
fi
|
||||
|
||||
## Déploiement
|
||||
if [ "$action" == deploy ]; then
|
||||
[ -n "$CATALINA_BASE" -o -z "$will_deploy" ] || die "Vous devez spécifier l'option --catalina-base"
|
||||
|
||||
if [ -n "$fake" ]; then
|
||||
# Afficher ce qu'il faut faire
|
||||
etitle "Configuration globale" __dump_vars
|
||||
etitle "Déploiements des webapps"
|
||||
for deploymap in "${deploymaps[@]}"; do
|
||||
splitpair "$deploymap" waname src
|
||||
setx srcname=basename -- "$src"
|
||||
dest="${CATALINA_BASE:-CATALINA_BASE}/webapps/$waname"
|
||||
etitle "$waname"
|
||||
if [ -f "$src/.toinst.conf" ]; then
|
||||
etitle "Configuration de la webapp"
|
||||
(
|
||||
EXCLUDES=()
|
||||
PROTECTS=()
|
||||
RSYNC_OPTIONS=()
|
||||
source "$src/.toinst.conf"
|
||||
for var in EXCLUDES PROTECTS RSYNC_OPTIONS; do
|
||||
eecho "$(echo_seta2 "$var")"
|
||||
done
|
||||
)
|
||||
eend
|
||||
fi
|
||||
build_rsync_options "$src"
|
||||
evalx qvals rsync "${rsync_options[@]}" "$src/" "$dest" // eecho
|
||||
evalx qvals chmod -R u=rwX,g=rX,o=rX "$dest" // eecho
|
||||
if [ -n "$TOMCAT_USER" ]; then
|
||||
evalx qvals chown -R "$TOMCAT_USER:$TOMCAT_GROUP" "$dest" // eecho
|
||||
fi
|
||||
eend
|
||||
done
|
||||
eend
|
||||
|
||||
elif ! is_root; then
|
||||
# le déploiement doit être fait en root
|
||||
args=(
|
||||
-C "$TOMCAT_PROFILE"
|
||||
-d "$CATALINA_BASE"
|
||||
-U "$TOMCAT_USER"
|
||||
-G "$TOMCAT_GROUP"
|
||||
-V "$TOMCAT_VERSION"
|
||||
-g "$MANAGER_URL"
|
||||
-u "$MANAGER_USER"
|
||||
-p "$MANAGER_PASSWORD"
|
||||
-m "$(array_join WAMAPS ,)"
|
||||
--no-backup
|
||||
--no-restart
|
||||
)
|
||||
run_as root --noexec "${args[@]}" "${srcs[@]}" || die
|
||||
|
||||
else
|
||||
# faire le déploiement
|
||||
etitle "Déploiements des webapps"
|
||||
for deploymap in "${deploymaps[@]}"; do
|
||||
splitpair "$deploymap" waname src
|
||||
setx srcname=basename -- "$src"
|
||||
dest="$CATALINA_BASE/webapps/$waname"
|
||||
etitle "$srcname"
|
||||
estepi "Déploiement vers $dest"
|
||||
estep "Copie des fichiers"
|
||||
build_rsync_options "$src"
|
||||
if ! rsync "${rsync_options[@]}" "$src/" "$dest"; then
|
||||
eerror "Une erreur s'est produite pendant la copie des fichiers"
|
||||
else
|
||||
error=
|
||||
estep "Correction des permissions et du propriétaire"
|
||||
chmod -R u=rwX,g=rX,o=rX "$dest" || error=1
|
||||
if [ -n "$TOMCAT_USER" ]; then
|
||||
chown -R "$TOMCAT_USER:$TOMCAT_GROUP" "$dest" || error=1
|
||||
fi
|
||||
if [ -n "$error" ]; then
|
||||
eeror "Une erreur s'est produite pendant la mise à jour"
|
||||
fi
|
||||
fi
|
||||
eend
|
||||
done
|
||||
eend
|
||||
fi
|
||||
fi
|
||||
|
||||
## Redémarrage
|
||||
if [ -n "$RESTART" -o "$action" == restart ]; then
|
||||
etitle "Redémarrage des webapps"
|
||||
if [ -z "$MANAGER_URL" -o -z "$MANAGER_USER" ]; then
|
||||
ewarn "Impossible de recharger la webapp parce que l'url du manager et/ou le compte admin n'ont pas pu être déterminés."
|
||||
[ -z "$fake" ] && enote "\
|
||||
Par défaut, les webapps ne sont rechargées automatiquement que si le fichier web.xml est modifié.
|
||||
Utilisez les options -g, -u, -p pour spécifier les informations manquantes nécessaires au pilotage du manager."
|
||||
|
||||
elif [ -n "$fake" ]; then
|
||||
estepi "Utilisation du manager à l'adresse $MANAGER_URL"
|
||||
for deploymap in "${deploymaps[@]}"; do
|
||||
splitpair "$deploymap" waname src
|
||||
etitle "$waname"
|
||||
evalx qvals curl -fsS -u "$MANAGER_USER:$MANAGER_PASSWORD" "$MANAGER_URL/reload?path=/$waname" // eecho
|
||||
eend
|
||||
done
|
||||
|
||||
else
|
||||
estepi "Utilisation du manager à l'adresse $MANAGER_URL"
|
||||
for deploymap in "${deploymaps[@]}"; do
|
||||
splitpair "$deploymap" waname src
|
||||
ebegin "$waname"
|
||||
curl -fsS -u "$MANAGER_USER:$MANAGER_PASSWORD" "$MANAGER_URL/reload?path=/$waname" >/dev/null
|
||||
eend $?
|
||||
done
|
||||
fi
|
||||
eend
|
||||
fi
|
|
@ -0,0 +1,276 @@
|
|||
#!/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
|
||||
|
||||
function display_help() {
|
||||
uecho "$scriptname: classer des fichiers selon certains règles
|
||||
|
||||
Les règles sont spécifiées dans le fichier ~/etc/default/ufile
|
||||
|
||||
Dans ce fichier, le tableau RULES contient des règles qui sont chacune de la
|
||||
forme pattern:destdir[:renamef]
|
||||
|
||||
- pattern est au format glob et identifie les fichiers auxquels s'applique la
|
||||
règle
|
||||
- destdir est le répertoire de destination dans lequel classer le fichier
|
||||
- renamef est une fonction qui permet de supporter le renommage d'un fichier
|
||||
lors de son classement. Sa signature est 'renamef filename pf destdir' où
|
||||
filename est le nom du fichier source, pf son chemin complet et destdir la
|
||||
valeur de destdir mentionnée dans la règle.
|
||||
La fonction doit définir la variable dest qui est le nouveau nom. Si la
|
||||
fonction retourne un code d'erreur autre que zéro, la règle est ignorée.
|
||||
Si le nouveau nom contient un chemin, destdir est ignoré et le fichier est
|
||||
déplacé dans le répertoire spécifié avec le nom spécifié. Si dest est un
|
||||
tableau avec plusieurs destinations, alors le fichier est copié en plusieurs
|
||||
fois.
|
||||
Si dest est de la forme [user@]host:path alors le fichier est copié par scp
|
||||
sur l'hôte spécifié vers la destination spécifiée, sauf si l'hôte courant est
|
||||
déjà celui mentionné dans la valeur, auquel cas la copie est faite directement
|
||||
dans le répertoire spécifié.
|
||||
Si le user et l'hôte courant sont déjà à la valeur spécifiée, alors la copie
|
||||
est faite en local sans utiliser scp sauf si l'option --force-scp est utilisée
|
||||
Le chemin spécifié, en local ou distant, est toujours le chemin complet vers
|
||||
le fichier destination. Si on veut copier le fichier sans le renommer vers un
|
||||
répertoire, il faut mettre un slash e.g destdir/ ou user@host:destdir/
|
||||
variables pouvant être définies mais non documentées: interaction(=-i)
|
||||
|
||||
USAGE
|
||||
$scriptname [options] <files...>
|
||||
|
||||
OPTIONS
|
||||
-c, --config CONFIG
|
||||
Utiliser le fichier de configuration spécifié au lieu de la valeur par
|
||||
défaut ~/etc/default/ufile
|
||||
--file
|
||||
Classer les fichiers spécifiés. C'est l'action par défaut
|
||||
-S, --ssh SSH
|
||||
S'il faut classer sur un hôte distant avec scp, utiliser le programme
|
||||
spécifié pour la connexion par ssh
|
||||
--force-scp
|
||||
Toujours utiliser scp pour une copie distante. Par défaut s'il est
|
||||
déterminé que l'hôte distant est en réalité l'hôte courant, alors la
|
||||
copie est effectuée directement.
|
||||
-n, --fake
|
||||
Afficher les opérations qui seraient faites
|
||||
-l, --list
|
||||
Lister les règles définies
|
||||
-e, --edit
|
||||
Lancer un éditeur sur le fichier de configuration"
|
||||
}
|
||||
|
||||
function joinp() {
|
||||
# afficher le chemin $1/$2
|
||||
local pf="$1"
|
||||
[ -n "$2" -a "${pf%/}" == "$pf" ] && pf="$pf/"
|
||||
pf="$pf${2#/}"
|
||||
echo "$pf"
|
||||
}
|
||||
|
||||
function __check_destdir() {
|
||||
local destdir="$1" rule="$2"
|
||||
if [ -z "$destdir" ]; then
|
||||
eerror "$rule: règle invalide: destdir est vide"
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
function __set_dest() {
|
||||
local dest="$1" destdir="$2" filename="$3" force_scp="$4"
|
||||
local userhost remotedir destname
|
||||
if [[ "$dest" == *:* ]]; then
|
||||
splitpair "$dest" userhost remotedir
|
||||
if [ -z "$force_scp" ] && check_userhostname "$userhost"; then
|
||||
# on est déjà avec le bon user sur le bon hôte
|
||||
if [ -n "$remotedir" ]; then
|
||||
splitpath "$remotedir" destdir destname
|
||||
setx destdir=abspath "$destdir" "$HOME"
|
||||
[ -n "$destname" ] || destname="$filename"
|
||||
setx dest=joinp "$destdir" "$destname"
|
||||
else
|
||||
setx dest=joinp "$HOME" "$filename"
|
||||
fi
|
||||
fi
|
||||
elif [[ "$dest" == */* ]]; then
|
||||
splitpath "$dest" destdir destname
|
||||
[ -n "$destname" ] || destname="$filename"
|
||||
setx dest=joinp "$destdir" "$destname"
|
||||
setx dest=abspath "$dest"
|
||||
else
|
||||
__check_destdir "$destdir" "$rule" || return 1
|
||||
setx dest=joinp "$destdir" "$filename"
|
||||
fi
|
||||
upvar dest "$dest"
|
||||
return 0
|
||||
}
|
||||
|
||||
args=(%
|
||||
--help '$exit_with display_help'
|
||||
-c:,--config: config=
|
||||
--file action=file
|
||||
-S:,--ssh: SSH=
|
||||
--force-scp force_scp=1
|
||||
-n,--fake fake=1
|
||||
-l,--list action=list
|
||||
-e,--edit action=edit
|
||||
)
|
||||
parse_args "$@"; set -- "${args[@]}"
|
||||
|
||||
[ -n "$action" ] || action=file
|
||||
|
||||
## charger toutes les règles
|
||||
|
||||
RULES=()
|
||||
INCLUDES=()
|
||||
if [ -n "$config" ]; then
|
||||
if [ "$action" != edit ]; then
|
||||
# le fichier doit exister, sauf en mode édition où il sera créé s'il
|
||||
# n'existe pas déjà
|
||||
[ -f "$config" ] || die "$config: fichier introuvable"
|
||||
fi
|
||||
if [ -f "$config" ]; then
|
||||
source "$config" || die "$config: erreur lors de la lecture du fichier"
|
||||
fi
|
||||
else
|
||||
set_defaults ufile
|
||||
fi
|
||||
array_copy rules RULES
|
||||
for include in "${INCLUDES[@]}"; do
|
||||
if [ -f "$include" ]; then
|
||||
RULES=()
|
||||
source "$include"
|
||||
array_extend rules RULES
|
||||
else
|
||||
ewarn "$include: fichier introuvable"
|
||||
fi
|
||||
done
|
||||
array_copy RULES rules
|
||||
|
||||
## actions particulières
|
||||
|
||||
if [ "$action" == list ]; then
|
||||
echo "# $(echo_seta2 INCLUDES)"
|
||||
array_to_lines RULES
|
||||
exit 0
|
||||
elif [ "$action" == edit ]; then
|
||||
[ -n "$config" ] || setx config=get_user_defaults_file ufile
|
||||
if [ ! -f "$config" ]; then
|
||||
einfo "Le fichier $(ppath "$config") n'existe pas. Il sera créé avec un contenu par défaut"
|
||||
mkdirof "$config" || die
|
||||
cp "$scriptdir/lib/default/ufile" "$config"
|
||||
fi
|
||||
"${EDITOR:-vi}" "$config"
|
||||
exit $?
|
||||
elif [ "$action" != file ]; then
|
||||
die "bug: $action: action non implémentée"
|
||||
fi
|
||||
|
||||
## classement des fichiers
|
||||
|
||||
if [ -n "$fake" ]; then
|
||||
function docmd() { qvals "$@"; }
|
||||
else
|
||||
function docmd() { "$@"; }
|
||||
fi
|
||||
|
||||
[ $# -gt 0 ] || die "Vous devez spécifier des fichiers à classer"
|
||||
[ ${#RULES[*]} -gt 0 ] || die "Vous devez spécifier des règles pour le classement des fichiers dans ~/etc/default/ufile"
|
||||
|
||||
# vérifier les règles
|
||||
for rule in "${RULES[@]}"; do
|
||||
splitpair "$rule" pattern r2
|
||||
splitpair "$r2" destdir r3
|
||||
splitpair "$r3" renamef r4
|
||||
if [ -z "$destdir" -o "${destdir#"~/"}" != "$destdir" ]; then
|
||||
:
|
||||
elif [ "${destdir#/}" == "$destdir" ]; then
|
||||
ewarn "$rule: règle potentiellement problématique: destdir devrait être absolu"
|
||||
fi
|
||||
done
|
||||
|
||||
# faire le classement effectif
|
||||
r=
|
||||
for file in "$@"; do
|
||||
[ -f "$file" -o -n "$fake" ] || {
|
||||
eerror "$file: fichier introuvable. il sera ignoré"
|
||||
continue
|
||||
}
|
||||
setx pf=abspath "$file"
|
||||
setx dir=dirname -- "$pf"
|
||||
setx filename=basename -- "$pf"
|
||||
found=
|
||||
for rule in "${RULES[@]}"; do
|
||||
splitpair "$rule" pattern r2
|
||||
splitpair "$r2" odestdir r3
|
||||
splitpair "$r3" renamef r4
|
||||
if [ "${odestdir#"~/"}" != "$odestdir" ]; then
|
||||
odestdir="$HOME/${odestdir#"~/"}"
|
||||
elif [ "$odestdir" == "~" ]; then
|
||||
odestdir="$HOME"
|
||||
fi
|
||||
|
||||
eval "[[ \"\$filename\" == $(qwc "$pattern") ]]" || continue
|
||||
|
||||
unset dest
|
||||
interaction=--DEFAULT--
|
||||
if [ -n "$renamef" ]; then
|
||||
"$renamef" "$filename" "$pf" "$odestdir" || continue
|
||||
fi
|
||||
if is_array dest; then
|
||||
array_copy tmpdests dest
|
||||
dests=()
|
||||
for dest in "${tmpdests[@]}"; do
|
||||
__set_dest "$dest" "$odestdir" "$filename" "$force_scp" || break
|
||||
array_add dests "$dest"
|
||||
done
|
||||
elif is_defined dest; then
|
||||
__set_dest "$dest" "$odestdir" "$filename" "$force_scp" || break
|
||||
dests=("$dest")
|
||||
else
|
||||
__check_destdir "$odestdir" "$rule" || break
|
||||
setx dest=joinp "$odestdir" "$filename"
|
||||
dests=("$dest")
|
||||
fi
|
||||
|
||||
i=1
|
||||
mvi=${#dests[*]}
|
||||
for dest in "${dests[@]}"; do
|
||||
if [[ "$dest" == *:* ]]; then
|
||||
[ "$interaction" == --DEFAULT-- ] && int= || int="$interaction"
|
||||
estep "$filename --> $dest"
|
||||
ask_yesno $int "Voulez-vous continuer?" O || {
|
||||
r=1; found=x; break
|
||||
}
|
||||
docmd scp ${SSH:+-S "$SSH"} "$file" "$dest" || die "problème lors de la copie du fichier"
|
||||
|
||||
else
|
||||
[ "$interaction" == --DEFAULT-- ] && int=-i || int="$interaction"
|
||||
estep "$filename --> $dest"
|
||||
ask_yesno $int "Voulez-vous continuer?" O || {
|
||||
r=1; found=x; break
|
||||
}
|
||||
setx destdir=dirname -- "$dest"
|
||||
docmd mkdir -p "$destdir" || die "$destdir: impossible de créer le répertoire"
|
||||
if [ $i -eq $mvi ]; then
|
||||
mvdesc="du déplacement"
|
||||
mvcmd=mv
|
||||
else
|
||||
mvdesc="de la copie"
|
||||
mvcmd=cp
|
||||
fi
|
||||
docmd "$mvcmd" -i "$file" "$dest" || die "problème lors $mvdesc du fichier"
|
||||
fi
|
||||
i=$(($i + 1))
|
||||
done
|
||||
|
||||
[ -n "$found" ] || found=1
|
||||
break
|
||||
done
|
||||
|
||||
if [ -z "$found" ]; then
|
||||
ewarn "$file: aucune correspondance n'a été trouvée"
|
||||
fi
|
||||
done
|
||||
|
||||
[ -n "$r" ] || r=0
|
||||
exit $r
|
2
uinst
2
uinst
|
@ -1,6 +1,6 @@
|
|||
#!/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
|
||||
source "$(dirname -- "$0")/lib/ulib/ulib" || exit 1
|
||||
urequire DEFAULTS uinst
|
||||
|
||||
uinst_nolocal "$@"
|
||||
|
|
2
uinst.sh
2
uinst.sh
|
@ -2,7 +2,7 @@
|
|||
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
|
||||
# Version de uinst qui fonctionne avec /bin/sh. Le contrôle est transmis à
|
||||
# bash, qui est recherché dans une liste de répertoires standards
|
||||
. `dirname "$0"`/lib/ulib/ulibsh || exit 1
|
||||
. `dirname -- "$0"`/lib/ulib/ulibsh || exit 1
|
||||
urequire DEFAULTS uinst
|
||||
|
||||
uinst_nolocal "$@"
|
||||
|
|
162
uproject
162
uproject
|
@ -61,10 +61,27 @@ COMMANDS
|
|||
Cloner un dépôt distant. Basculer sur la branche develop si elle existe.
|
||||
Initialiser git annex si le dépôt contient des fichiers annexés.
|
||||
Récupérer aussi ces fichiers avec 'git annex get'
|
||||
-n, --no-clone
|
||||
Ne pas cloner, afficher simplement ce qui serait fait
|
||||
-u, --update
|
||||
Si le dépôt a déjà été cloné, le mettre à jour avec git pull
|
||||
-m, --master
|
||||
Ne pas chercher à basculer sur la branche develop, même si elle
|
||||
existe.
|
||||
-r, --recursive
|
||||
Cloner récursivement tous les dépôt à partir du chemin spécifié
|
||||
depuis un serveur gitolite. La signature est alors sensiblement
|
||||
différente:
|
||||
clone -r git@host:basepath [destdir]
|
||||
clone -r http://host/gituser/basepath [destdir]
|
||||
L'arborescence en dessous de basepath est recréée à partir de
|
||||
destdir, e.g le dépôt git@host:basepath/to/repo est cloné dans
|
||||
destdir/to/repo
|
||||
|
||||
crone git@host:path/to/repo [destdir]
|
||||
crone http://host/gituser/path/to/repo [destdir]
|
||||
Créer un dépôt distant sur gitolite, puis le cloner
|
||||
Créer un dépôt sur un serveur gitolite, puis le cloner. La commande
|
||||
'create' doit avoir été activée sur ce serveur.
|
||||
|
||||
develop
|
||||
release
|
||||
|
@ -268,26 +285,131 @@ elif array_contains GITANNEX_CMDS "$CMD"; then
|
|||
esac
|
||||
|
||||
elif [ "$CMD" == clone ]; then
|
||||
repourl="${1%.git}"
|
||||
[ -n "$repourl" ] || die "Vous devez spécifier l'url du dépôt git"
|
||||
splitfsep "$repourl" : userhost path
|
||||
|
||||
destdir="$2"
|
||||
if [ -z "$destdir" ]; then
|
||||
setx destdir=basename -- "$path"
|
||||
destdir="${destdir%.git}"
|
||||
fi
|
||||
[ -d "$destdir" ] && die "$(ppath "$destdir"): répertoire existant"
|
||||
|
||||
git_annex_use_ssh_wrapper
|
||||
git clone "$repourl" "$destdir" || die
|
||||
(
|
||||
cd "$destdir"
|
||||
if git_have_rbranch develop; then
|
||||
git checkout develop || exit 1
|
||||
function pclone() {
|
||||
estep "$1 --> $(ppath "$2")"
|
||||
mkdirof "$2" || return 1
|
||||
git clone "$1" "$2" || return 1
|
||||
if [ -z "$3" ]; then
|
||||
(
|
||||
cd "$2"
|
||||
if git_have_rbranch develop; then
|
||||
git checkout develop || exit 1
|
||||
fi
|
||||
) || return 1
|
||||
fi
|
||||
) || die
|
||||
git_annex_initial "$destdir" || die
|
||||
git_annex_initial "$2" || return 1
|
||||
}
|
||||
function gitolite_info() {
|
||||
local mode="$1" urlbase="$2" pattern="$3"
|
||||
case "$mode" in
|
||||
http) curl -fs "$urlbase/info${pattern:+"?$pattern"}";;
|
||||
ssh) ssh -q "$urlbase" info ${pattern:+"$pattern"} 2>/dev/null;;
|
||||
esac
|
||||
}
|
||||
function filter_repos() {
|
||||
awkrun prefix="$1" '
|
||||
NR <= 2 { next }
|
||||
{
|
||||
# filtrer les projets qui ne sont pas encore créés
|
||||
if (substr($0, 5, 2) == " C") next
|
||||
repo = substr($0, 6)
|
||||
# filtrer les projets de type wildcard
|
||||
if (repo ~ /[\[\]\*]/) next
|
||||
# enlever le prefixe
|
||||
if (prefix != "" && substr(repo, 1, length(prefix)) != prefix) next
|
||||
print repo
|
||||
}
|
||||
'
|
||||
}
|
||||
|
||||
no_clone=
|
||||
update=
|
||||
nodevelop=
|
||||
recursive=
|
||||
parse_opts "${PRETTYOPTS[@]}" \
|
||||
-n,--no-clone no_clone=1 \
|
||||
-u,--update update=1 \
|
||||
-m,--master nodevelop=1 \
|
||||
-r,--recursive recursive=1 \
|
||||
@ args -- "$@" && set -- "${args[@]}" || die "$args"
|
||||
|
||||
if [ -n "$recursive" ]; then
|
||||
repobase="$1"
|
||||
[ -n "$repobase" ] || die "Vous devez spécifier l'url de base des dépôts à cloner"
|
||||
if [ "${repobase#http://}" != "$repobase" -o "${repobase#https://}" != "$repobase" ]; then
|
||||
# accès par http
|
||||
mode=http
|
||||
splitfsep "$repobase" :// scheme hostuserpath
|
||||
splitfsep "$hostuserpath" / host userpath
|
||||
splitfsep "$userpath" / user basepath
|
||||
[ -n "$host" -a -n "$user" ] || die "Vous devez spécifier l'hôte e.g http://host/git/basepath"
|
||||
urlbase="$scheme://$host/$user"
|
||||
else
|
||||
# accès par ssh
|
||||
mode=ssh
|
||||
splitfsep "$repobase" : userhost basepath
|
||||
splituserhost "$userhost" user host
|
||||
[ -n "$user" ] || user=git
|
||||
[ -n "$host" ] || die "Vous devez spécifier l'hôte"
|
||||
urlbase="$user@$host"
|
||||
fi
|
||||
basepath="${basepath%/}"
|
||||
destbase="${2:-.}"
|
||||
|
||||
git_annex_use_ssh_wrapper
|
||||
prefix="${basepath:+$basepath/}"
|
||||
array_from_lines repos "$(set -o pipefail; gitolite_info "$mode" "$urlbase" "$prefix" | filter_repos "$prefix")" || die
|
||||
for repo in "${repos[@]}"; do
|
||||
case "$mode" in
|
||||
http) repourl="$urlbase/$repo";;
|
||||
ssh) repourl="$urlbase:$repo";;
|
||||
esac
|
||||
setx destdir=abspath "$destbase/${repo#$prefix}"
|
||||
if [ -d "$destdir" ]; then
|
||||
if [ -n "$update" ]; then
|
||||
(
|
||||
${no_clone:+qvals} cd "$destdir"
|
||||
${no_clone:+qvals} git pull
|
||||
) || die
|
||||
else
|
||||
estepe "$(ppath2 "$destdir"): répertoire existant"
|
||||
fi
|
||||
elif [ -n "$no_clone" ]; then
|
||||
qvals git clone "$repourl" "$destdir"
|
||||
else
|
||||
pclone "$repourl" "$destdir" "$nodevelop" || die
|
||||
fi
|
||||
done
|
||||
|
||||
else
|
||||
repourl="${1%.git}"
|
||||
[ -n "$repourl" ] || die "Vous devez spécifier l'url du dépôt git"
|
||||
|
||||
destdir="$2"
|
||||
if [ -z "$destdir" ]; then
|
||||
splitfsep "$repourl" : userhost path
|
||||
setx destdir=basename -- "$path"
|
||||
destdir="${destdir%.git}"
|
||||
fi
|
||||
setx destdir=abspath "$destdir"
|
||||
|
||||
git_annex_use_ssh_wrapper
|
||||
if [ -d "$destdir" ]; then
|
||||
if [ -n "$update" ]; then
|
||||
(
|
||||
${no_clone:+qvals} cd "$destdir"
|
||||
${no_clone:+qvals} git pull
|
||||
) || die
|
||||
else
|
||||
estepe "$(ppath2 "$destdir"): répertoire existant"
|
||||
fi
|
||||
elif [ -n "$no_clone" ]; then
|
||||
qvals git clone "$repourl" "$destdir"
|
||||
else
|
||||
pclone "$repourl" "$destdir" "$nodevelop" || die
|
||||
fi
|
||||
fi
|
||||
|
||||
elif [ "$CMD" == crone ]; then
|
||||
repourl="${1%.git}"
|
||||
|
@ -318,7 +440,7 @@ elif [ "$CMD" == crone ]; then
|
|||
fi
|
||||
tmpdestdir=
|
||||
if [ -d "$destdir" ]; then
|
||||
[ -d "$destdir/.git" ] && die "$(ppath "$destdir"): répertoire existant"
|
||||
[ -d "$destdir/.git" ] && die "$(ppath2 "$destdir"): un dépôt existe déjà"
|
||||
ac_set_tmpdir tmpdestdir
|
||||
fi
|
||||
|
||||
|
|
2
woinst
2
woinst
|
@ -1,6 +1,6 @@
|
|||
#!/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
|
||||
source "$(dirname -- "$0")/lib/ulib/ulib" || exit 1
|
||||
urequire DEFAULTS woinst
|
||||
|
||||
woinst "$@"
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
#!/bin/sh
|
||||
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
|
||||
# Version de woinst qui fonctionne avec /bin/sh. Le contrôle est transmis à
|
||||
# bash, qui est recherché dans une liste de répertoires standards
|
||||
. `dirname -- "$0"`/lib/ulib/ulibsh || exit 1
|
||||
urequire DEFAULTS woinst
|
||||
|
||||
woinst "$@"
|
Loading…
Reference in New Issue