381 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			381 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
#!/bin/bash
 | 
						|
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
 | 
						|
 | 
						|
function display_help() {
 | 
						|
    uecho "$scriptname: Lancer un script avec le protocole runs
 | 
						|
 | 
						|
USAGE
 | 
						|
    $scriptname [options] rscriptname name=value...
 | 
						|
    $scriptname [options] @recipe name=value...
 | 
						|
    $scriptname [options] -f rscript name=value...
 | 
						|
    $scriptname [options] -r recipe name=value...
 | 
						|
 | 
						|
OPTIONS
 | 
						|
Configuration
 | 
						|
    --init
 | 
						|
    --verify
 | 
						|
        Vérifier le nom d'hôte et créer si nécessaire le répertoire d'hôte
 | 
						|
        correspondant à l'hôte courant ou à l'hôte spécifié avec l'option -h
 | 
						|
        Avec --verify, la création du répertoire d'hôte n'est pas effectuée.
 | 
						|
    --sysinfos DATA
 | 
						|
        Avec l'option --init, initialiser le fichier sysinfos.conf avec DATA, si
 | 
						|
        le fichier n'a pas déjà été provisionné. Sans cette option, un fichier
 | 
						|
        vide avec des commentaires est créé à la place.
 | 
						|
    --create RSCRIPT
 | 
						|
        Créer un modèle de script avec le nom donné.
 | 
						|
        Avec l'option -h, le script est créé dans le répertoire d'hôte
 | 
						|
        correspondant à l'hôte spécifié
 | 
						|
 | 
						|
Gestion des scripts
 | 
						|
    -s  Forcer l'exécution du script avec l'utilisateur root si ce n'est pas
 | 
						|
        déjà le cas
 | 
						|
    -f RSCRIPT
 | 
						|
        Lancer le script individuel spécifié au lieu de chercher dans les
 | 
						|
        répertoires de \$RUNSSCRIPTSPATH
 | 
						|
    -r RECIPE
 | 
						|
        Lancer les scripts spécifiés dans le fichier de recettes individuel
 | 
						|
        spécifié.
 | 
						|
    -h HOSTNAME[.DOMAIN]
 | 
						|
        Spécifier que les scripts sont destinés à être lancés sur l'hôte
 | 
						|
        spécifié. Les scripts sont alors aussi cherchés dans les répertoires
 | 
						|
        {\$RUNSHOSTSPATH}/\$hostname.\$domain (par défaut) et
 | 
						|
        {\$RUNSHOSTSPATH}/\$domain/\$hostname (le cas échéant)
 | 
						|
        L'option --host est équivalente, sauf que son argument est facultatif et
 | 
						|
        que sa valeur par défaut est l'hôte courant, soit $MYHOST
 | 
						|
    --list
 | 
						|
        Afficher la liste des scripts qui sont disponibles. Avec l'option -h,
 | 
						|
        inclure aussi les scripts spécifiques à cet hôte.
 | 
						|
        Avec cette option, les arguments supplémentaires agissent comme des
 | 
						|
        filtres (regexp utilisée avec l'opérateur == de la commande [[). Les
 | 
						|
        noms des scripts doivent valider au moins un filtre.
 | 
						|
    --info
 | 
						|
        Afficher la la description du script et la valeur de chaque variable
 | 
						|
        définies
 | 
						|
    --desc-only
 | 
						|
        Afficher seulement la description du script
 | 
						|
    -z  Forcer la réinstallation des scripts qui se basent sur shouldrun/setdone"
 | 
						|
}
 | 
						|
 | 
						|
source "$(dirname "$0")/ulib/ulib" &&
 | 
						|
urequire DEFAULTS runs ||
 | 
						|
exit 1
 | 
						|
 | 
						|
set_defaults runs
 | 
						|
 | 
						|
function runs_path_required() {
 | 
						|
    die "Vous devez définir $1 dans ~/etc/default/runs"
 | 
						|
}
 | 
						|
 | 
						|
action=runs
 | 
						|
create_verbose=
 | 
						|
init_sysinfos=--NOT-SET--
 | 
						|
list_verbose=
 | 
						|
run_as_root=
 | 
						|
rscripts=()
 | 
						|
recipes=()
 | 
						|
runshost=
 | 
						|
runssysname=
 | 
						|
runssysdist=
 | 
						|
runssysver=
 | 
						|
runsbits=
 | 
						|
runsscriptspath=
 | 
						|
runsmodulespath=
 | 
						|
runshostspath=
 | 
						|
runsexportdir= # répertoire dans lequel exporter les fichiers
 | 
						|
runsworkdir= # si runsexportdir n'est pas spécifié, répertoire de travail
 | 
						|
runsvarsfile= # fichier contenant des définitions à charger
 | 
						|
runs_init "$scriptdir"
 | 
						|
parse_opts "${PRETTYOPTS[@]}" \
 | 
						|
    --help '$exit_with display_help' \
 | 
						|
    --i '$action=init;create_verbose=false' \
 | 
						|
    --init '$action=init;create_verbose=true' \
 | 
						|
    --verify action=verify \
 | 
						|
    --sysinfos: init_sysinfos= \
 | 
						|
    -c,--c '$action=create;create_verbose=false' \
 | 
						|
    --create '$action=create;create_verbose=true' \
 | 
						|
    -l,--l '$action=list;list_verbose=false' \
 | 
						|
    --list '$action=list;list_verbose=true' \
 | 
						|
    --desc-only '$action=runs;RUNSACTION=runs_action_desc' \
 | 
						|
    -d,--dump,-i,--info '$action=runs;RUNSACTION=runs_action_dump' \
 | 
						|
    --export '$action=runs;RUNSACTION=runs_action_export' \
 | 
						|
    -s run_as_root \
 | 
						|
    -f: rscripts \
 | 
						|
    -r: recipes \
 | 
						|
    -h:,-H: runshost= \
 | 
						|
    --host:: '$set@ runshost "$MYHOST"' \
 | 
						|
    --sysname: runssysname= \
 | 
						|
    --sysdist: runssysdist= \
 | 
						|
    --sysver: runssysver= \
 | 
						|
    --bits: runsbits= \
 | 
						|
    --runsscriptspath: runsscriptspath= \
 | 
						|
    --runsmodulespath: runsmodulespath= \
 | 
						|
    --runshostspath: runshostspath= \
 | 
						|
    --runsexportdir: runsexportdir= \
 | 
						|
    --runsworkdir: runsworkdir= \
 | 
						|
    --runsvarsfile: runsvarsfile= \
 | 
						|
    -z RUNSRESET=1 \
 | 
						|
    @ args -- "$@" && set -- "${args[@]}" || die "$args"
 | 
						|
 | 
						|
[ -n "$runsscriptspath" ] && RUNSSCRIPTSPATH="$runsscriptspath"
 | 
						|
[ -n "$runsmodulespath" ] && RUNSMODULESPATH="$runsmodulespath"
 | 
						|
[ -n "$runshostspath" ] && RUNSHOSTSPATH="$runshostspath"
 | 
						|
 | 
						|
if [ "$action" == runs \
 | 
						|
    -o "$action" == init -o "$action" == verify \
 | 
						|
    -o \( -n "$runshost" -a \( "$action" == create -o "$action" == list \) \) ]; then
 | 
						|
    # configurer le nom d'hôté ici, parce qu'avec l'option -s, le fichier de
 | 
						|
    # configuration ~/etc/default/runs ne sera plus disponible
 | 
						|
    runs_initdomains
 | 
						|
    runs_inithost "$runshost"
 | 
						|
    host="$RUNSHOST"
 | 
						|
    splithost "$host" hostname domain
 | 
						|
    if [ -z "$domain" ]; then
 | 
						|
        host="$(runs_find_host "$host")"
 | 
						|
        splithost "$host" hostname domain
 | 
						|
    fi
 | 
						|
    [ -n "$domain" ] || host="$(runs_add_domain "$host")"
 | 
						|
    if [ "$host" != "$RUNSHOST" ]; then
 | 
						|
        enote "Le nom d'hôte '$RUNSHOST' a été automatiquement corrigé en '$host'"
 | 
						|
        if ask_yesno "Acceptez-vous cette modification?" O; then
 | 
						|
            RUNSHOST="$host"
 | 
						|
            runshost="$host" # pour l'option -s
 | 
						|
        fi
 | 
						|
    fi
 | 
						|
fi
 | 
						|
 | 
						|
if ! is_root && [ -n "$run_as_root" ]; then
 | 
						|
    # reconstruire la ligne de commande
 | 
						|
    args=()
 | 
						|
    if [ "$action" == "init" ]; then
 | 
						|
        args=("${args[@]}" --init)
 | 
						|
    elif [ "$action" == "verify" ]; then
 | 
						|
        args=("${args[@]}" --verify)
 | 
						|
    elif [ "$action" == "create" ]; then
 | 
						|
        is_yes "$create_verbose" &&
 | 
						|
        args=("${args[@]}" --create) ||
 | 
						|
        args=("${args[@]}" -c)
 | 
						|
    elif [ "$action" == "runs" ]; then
 | 
						|
        if [ "$RUNSACTION" == "runs_action_run" ]; then
 | 
						|
            :
 | 
						|
        elif [ "$RUNSACTION" == "runs_action_desc" ]; then
 | 
						|
            args=("${args[@]}" --desc-only)
 | 
						|
        elif [ "$RUNSACTION" == "runs_action_dump" ]; then
 | 
						|
            args=("${args[@]}" --dump)
 | 
						|
        else
 | 
						|
            ewarn "RUNSACTION inconnu: $RUNSACTION"
 | 
						|
        fi
 | 
						|
    else
 | 
						|
        ewarn "action inconnue: $action"
 | 
						|
    fi
 | 
						|
    for rscript in "${rscripts[@]}"; do
 | 
						|
        args=("${args[@]}" -f "$rscript")
 | 
						|
    done
 | 
						|
    for recipe in "${recipes[@]}"; do
 | 
						|
        args=("${args[@]}" -r "$recipe")
 | 
						|
    done
 | 
						|
    args=("${args[@]}" ${runshost:+-h "$runshost"}
 | 
						|
        ${runssysname:+--sysname "$runssysname"} ${runssysdist:+--sysdist "$runssysdist"} ${runssysver:+--sysver "$runssysver"} ${runsbits:+--bits "$runsbits"}
 | 
						|
        ${RUNSSCRIPTSPATH:+--runsscriptspath "$RUNSSCRIPTSPATH"}
 | 
						|
        ${RUNSMODULESPATH:+--runsmodulespath "$RUNSMODULESPATH"}
 | 
						|
        ${RUNSHOSTSPATH:+--runshostspath "$RUNSHOSTSPATH"}
 | 
						|
        ${runsexportdir:+--runsexportdir "$runsexportdir"} ${runsworkdir:+--runsworkdir "$runsworkdir"}
 | 
						|
        ${runsvarsfile:+--runsvarsfile "$runsvarsfile"}
 | 
						|
        ${RUNSRESET:+-z})
 | 
						|
    # puis relancer le script en root
 | 
						|
    run_as root "${args[@]}" -- "$@"
 | 
						|
fi
 | 
						|
 | 
						|
# si on donne un chemin relatif à '.' ou '..' ou un chemin absolu, forcer -f
 | 
						|
if [ -z "${rscripts[*]}" -a -z "${recipes[*]}" -a -n "$1" ]; then
 | 
						|
    if withpath "$1"; then
 | 
						|
        rscripts=("$1")
 | 
						|
        shift
 | 
						|
    fi
 | 
						|
fi
 | 
						|
 | 
						|
################################################################################
 | 
						|
if [ "$action" == "init" -o "$action" == "verify" ]; then
 | 
						|
    if [ "$init_sysinfos" == "--NOT-SET--" ]; then
 | 
						|
        init_sysinfos=
 | 
						|
    elif [ -z "$init_sysinfos" ]; then
 | 
						|
        # Valeur par défaut de sysinfos pour l'hôte courant
 | 
						|
        init_sysinfos="\
 | 
						|
sysname=(${MYSYSNAME[*]})
 | 
						|
sysdist=(${MYSYSDIST[*]})
 | 
						|
sysver=(${MYSYSVER[*]})
 | 
						|
bits=$MYBITS"
 | 
						|
    fi
 | 
						|
 | 
						|
    __runs_setpath
 | 
						|
    [ -n "${RUNSHOSTSDIRS[*]}" ] || runs_path_required RUNSHOSTSPATH
 | 
						|
    runshost="${runshost:-$RUNSHOST}"
 | 
						|
 | 
						|
    resolv_ips __runs_ips "$runshost"
 | 
						|
    if [ -z "${__runs_ips[*]}" ]; then
 | 
						|
        eerror "$runshost ne semble pas être une adresse valide."
 | 
						|
        ask_yesno "Voulez-vous réellement utiliser cette adresse, bien qu'elle n'existe pas dans le DNS?" N || die
 | 
						|
    fi
 | 
						|
 | 
						|
    if [ "$action" == "init" ]; then
 | 
						|
        etitle "$runshost" runs_initdir "$runshost" "$create_verbose" "$init_sysinfos"
 | 
						|
    fi
 | 
						|
 | 
						|
################################################################################
 | 
						|
elif [ "$action" == "create" ]; then
 | 
						|
    if [ -n "$runshost" ]; then
 | 
						|
        __runs_setpath
 | 
						|
        [ -n "${RUNSHOSTSDIRS[*]}" ] || runs_path_required RUNSHOSTSPATH
 | 
						|
        etitle "$runshost" runs_initdir "$runshost" "$create_verbose"
 | 
						|
    fi
 | 
						|
 | 
						|
    # générer les scripts spécifié
 | 
						|
    overwrite=no
 | 
						|
    error=
 | 
						|
    new_rscripts=()
 | 
						|
    for rscript in "$@"; do
 | 
						|
        etitle "$(ppath "$rscript")" runs_create_rscript "$rscript" "$runshost" "$create_verbose" "$overwrite" || error=1
 | 
						|
    done
 | 
						|
 | 
						|
    # Puis éditer les fichiers nouvellement créés
 | 
						|
    if [ -z "$error" -a -n "${new_rscripts[*]}" ]; then
 | 
						|
        etitle "Edition des fichiers"
 | 
						|
        if ask_yesno "Voulez-vous éditer le script nouvellement créé?" O; then
 | 
						|
            "${EDITOR:-vi}" "${new_rscripts[@]}"
 | 
						|
        fi
 | 
						|
        eend
 | 
						|
    fi
 | 
						|
 | 
						|
################################################################################
 | 
						|
elif [ "$action" == "list" ]; then
 | 
						|
    function find_items() {
 | 
						|
        # Trouver tous les scripts runs et les répertoire uinstallable à partir
 | 
						|
        # du répertoire $2, et mettre les chemins dans le tableau $1
 | 
						|
        local dest="$1"
 | 
						|
        local runsdir="$2"
 | 
						|
        # $3 est un préfixe à enlever des chemins, pour qu'ils soient exprimés
 | 
						|
        # relativement à un chemin qui vaut $2 par défaut
 | 
						|
        local prefix="${3:-$runsdir/}"
 | 
						|
        local items item
 | 
						|
 | 
						|
        [ -d "$runsdir" ] || return
 | 
						|
        array_lsall items "$runsdir"
 | 
						|
        for item in "${items[@]}"; do
 | 
						|
            if __runs_is_runsscript "$item"; then
 | 
						|
                array_add "$dest" "${item#$prefix}"
 | 
						|
            elif [ -d "$item" ]; then
 | 
						|
                find_items "$dest" "$item" "$prefix"
 | 
						|
            fi
 | 
						|
        done
 | 
						|
    }
 | 
						|
 | 
						|
    __runs_setpath
 | 
						|
    [ -n "${RUNSSCRIPTSDIRS[*]}" ] || runs_path_required RUNSSCRIPTSPATH
 | 
						|
    [ -n "${RUNSMODULESDIRS[*]}" ] || runs_path_required RUNSMODULESPATH
 | 
						|
    [ -z "$runshost" -o -n "${RUNSHOSTSDIRS[*]}" ] || runs_path_required RUNSHOSTSPATH
 | 
						|
 | 
						|
    splithost "$runshost" hostname domain
 | 
						|
 | 
						|
    # chercher tous les scripts runs et les répertoires uinstallables
 | 
						|
    rscriptpaths=()
 | 
						|
    if [ -n "$runshost" ]; then
 | 
						|
        for runsdir in "${RUNSHOSTSDIRS[@]}"; do
 | 
						|
            find_items rscriptpaths "$runsdir/$runshost"
 | 
						|
            find_items rscriptpaths "$runsdir/$domain/$hostname"
 | 
						|
        done
 | 
						|
    fi
 | 
						|
    for runsdir in "${RUNSSCRIPTSDIRS[@]}" "${RUNSMODULESDIRS[@]}"; do
 | 
						|
        find_items rscriptpaths "$runsdir"
 | 
						|
    done
 | 
						|
 | 
						|
    # les trier en enlevant les doublons, recalculer le nom canonique
 | 
						|
    # RUNSSCRIPT, puis les afficher
 | 
						|
    array_from_lines rscriptpaths "$(array_to_lines rscriptpaths | sort -u)"
 | 
						|
    for rscriptpath in "${rscriptpaths[@]}"; do
 | 
						|
        runs_find_scriptfile "$rscriptpath" "$runshost" || continue
 | 
						|
        if [ -n "$*" ]; then
 | 
						|
            # filtrer
 | 
						|
            match=
 | 
						|
            for filter in "$@"; do
 | 
						|
                [[ "$filter" == *\** ]] || filter="$filter*"
 | 
						|
                eval "[[ \"\$rscriptpath\" == $filter ]] && match=1"
 | 
						|
            done
 | 
						|
            [ -n "$match" ] || continue
 | 
						|
        fi
 | 
						|
        if is_yes "$list_verbose"; then
 | 
						|
            echo "$rscriptpath $RUNSSCRIPT"
 | 
						|
        else
 | 
						|
            echo "$rscriptpath"
 | 
						|
        fi
 | 
						|
    done
 | 
						|
 | 
						|
################################################################################
 | 
						|
elif [ "$action" == "runs" ]; then
 | 
						|
    if [ -n "${rscripts[*]}" ]; then
 | 
						|
        # sans l'option -f, il faut définir RUNS*PATH
 | 
						|
        __runs_setpath
 | 
						|
        [ -n "${RUNSSCRIPTSDIRS[*]}" ] || runs_path_required RUNSSCRIPTSPATH
 | 
						|
        [ -n "${RUNSMODULESDIRS[*]}" ] || runs_path_required RUNSMODULESPATH
 | 
						|
        [ -z "$runshost" -o -n "${RUNSHOSTSDIRS[*]}" ] || runs_path_required RUNSHOSTSPATH
 | 
						|
    fi
 | 
						|
 | 
						|
    # initialisation
 | 
						|
    [ -f "$runsvarsfile" ] && source "$runsvarsfile"
 | 
						|
    runs_initsysinfos "$runssysname" "$runssysdist" "$runssysver" "$runsbits"
 | 
						|
    runs_initworkdir "$runsexportdir" "$runsworkdir" "$scriptdir"
 | 
						|
 | 
						|
    if [ -n "${rscripts[*]}" ]; then
 | 
						|
        # scripts individuels
 | 
						|
        for rscript in "${rscripts[@]}"; do
 | 
						|
            etitle "$(ppath "$rscript")" \
 | 
						|
                runs_rscript "$rscript" "$@" || die "Arrêt du déploiement"
 | 
						|
        done
 | 
						|
 | 
						|
    elif [ -n "${recipes[*]}" ]; then
 | 
						|
        # fichiers de recette
 | 
						|
        for recipe in "${recipes[@]}"; do
 | 
						|
            [ -f "$recipe" ] || die "$recipe: fichier introuvable"
 | 
						|
            etitle "$(ppath "$recipe")" \
 | 
						|
                runs_recipe "$recipe" "$@" || die "Arrêt du déploiement"
 | 
						|
        done
 | 
						|
 | 
						|
    else
 | 
						|
        # suite de scripts et/ou de recettes séparés par --
 | 
						|
        # note: si on spécifie plusieurs scripts séparés par --, il faut le
 | 
						|
        # faire de cette manière:
 | 
						|
        #     runs -- script1 ... -- script2 ... -- @recipe ...
 | 
						|
        # le premier -- est important, il permet de ne pas traiter les arguments
 | 
						|
        # suivants, et donc de ne pas fusionner les valeurs script1 avec script2
 | 
						|
        while [ -n "$1" ]; do
 | 
						|
            if [ "$1" == -- ]; then
 | 
						|
                shift
 | 
						|
                continue
 | 
						|
            elif [ "${1#@}" != "$1" ]; then
 | 
						|
                # recette à chercher dans RUNSSCRIPTSPATH
 | 
						|
                # prendre les arguments jusqu'à --
 | 
						|
                recipe="${1#@}"; shift
 | 
						|
                args=()
 | 
						|
                while [ -n "$1" -a "$1" != "--" ]; do
 | 
						|
                    args=("${args[@]}" "$1")
 | 
						|
                    shift
 | 
						|
                done
 | 
						|
                etitle "@$recipe" \
 | 
						|
                    runs_recipepath "$recipe" "${args[@]}" || die "Arrêt du déploiement"
 | 
						|
                shift
 | 
						|
            else
 | 
						|
                # script à chercher dans RUNSSCRIPTSPATH
 | 
						|
                # prendre les arguments jusqu'à --
 | 
						|
                args=()
 | 
						|
                while [ -n "$1" -a "$1" != "--" ]; do
 | 
						|
                    args=("${args[@]}" "$1")
 | 
						|
                    shift
 | 
						|
                done
 | 
						|
                etitle "${args[0]}" \
 | 
						|
                    runs_rscriptpath "${args[@]}" || die "Arrêt du déploiement"
 | 
						|
            fi
 | 
						|
        done
 | 
						|
    fi
 | 
						|
 | 
						|
    # traitement après déploiement
 | 
						|
    runs_after_export
 | 
						|
fi
 |