From c584648913490ce0c673a3d77f87b035daefa96e Mon Sep 17 00:00:00 2001 From: Voomra Date: Tue, 23 Apr 2024 07:41:00 +0300 Subject: [PATCH] import code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit сохранён для истории --- scripts/playbook.sh | 149 ++++++++++++++++++++ scripts/scripts.d/00-environment.sh | 18 +++ scripts/scripts.d/10-install.sh | 76 +++++++++++ scripts/scripts.d/20-backup.sh | 117 ++++++++++++++++ scripts/scripts.d/30-restore.sh | 203 ++++++++++++++++++++++++++++ scripts/scripts.d/99-openports.sh | 20 +++ 6 files changed, 583 insertions(+) create mode 100644 scripts/playbook.sh create mode 100644 scripts/scripts.d/00-environment.sh create mode 100644 scripts/scripts.d/10-install.sh create mode 100644 scripts/scripts.d/20-backup.sh create mode 100644 scripts/scripts.d/30-restore.sh create mode 100644 scripts/scripts.d/99-openports.sh diff --git a/scripts/playbook.sh b/scripts/playbook.sh new file mode 100644 index 0000000..df4cd07 --- /dev/null +++ b/scripts/playbook.sh @@ -0,0 +1,149 @@ +#!/bin/bash +# vi: set tabstop=2 shiftwidth=2 noexpandtab : +SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd) +BASE_DIR=$(cd "$(dirname "$0")"/../ && pwd) +declare -A MAP_COMMAND +declare -A MAP_COMMAND_DESC +declare -A MAP_COMMAND_HELP + +################################################################################ +# COLORS +################################################################################ + +CW="\e[1;37m" # White +CG="\e[0;32m" # Green +CY="\e[0;33m" # Yellow +CC="\e[1;36m" # Cyan +BR="\e[41m" # Background Red +BB="\e[44m" # Background Blue +NC="\e[0m" # Reset + +################################################################################ +# FUNCTIONS +################################################################################ + +# Заполнение символом. +# +# @param char символ +# @param len сколько раз повторять +function StrFill() { + local __char=$1 + local __len=$2 + + for (( i = 0; i < $__len; i++ )); do + echo -ne $__char + done +} + +# Текст в рамке. +# +# @param text текст +function Title() { + local __text="$1" + local __clear_text=$(echo -e "$__text" | sed "s,\x1B\[[0-9;]*[a-zA-Z],,g") + local __size=${#__clear_text} + + local __line=$(StrFill "─" $__size+2) + + echo -e "┌${__line}┐" + echo -e "│ ${__text} │" + echo -e "└${__line}┘" +} + +# Сообщение об ошибке. +# +# @param text сообщение +function LogError { + echo -e "${BR}${CW}ERR${NC} $@" +} + +# Отладочное сообщение. +# +# @param text сообщение +function LogDebug { + if [[ $DD_DEBUG -gt 0 ]]; then + echo -e "${BB}${CW}DBG${NC} $@" + fi +} + +# Вывести заголовок скрипта (логотип) +# +function AppHeader() { + Title "${CG}LAUNCHER v3" + echo -e "${NC}" +} + +# Табличное представление. +# +# Пример: +# echo "command | description" | as_table +function as_table() { + cat < /dev/stdin | column -d -t -s"|" -o"-" +# cat < /dev/stdin | awk 'BEGIN { FS = "|"}; { printf "%-20s - %-20s\n", $1, $2 }' +} + +################################################################################ +# HELP COMMAND +################################################################################ + +MAP_COMMAND["help"]=fn_command_help +MAP_COMMAND_DESC["help"]="показать страницу помощи или страницу помощи указанной команды (help ${CY}${NC})." + +function fn_command_help() { + local __cmd=$1 + + if [[ -n "$__cmd" ]]; then + ${MAP_COMMAND_HELP[$__cmd]} + else + fn_command_help_full + fi +} + +function fn_command_help_full() { + echo -e "Использование:\n ${CW}$(basename $0) ${CY}${NC}" + + echo -e "\nКоммнды:" + + __text="" + for V in "${!MAP_COMMAND[@]}"; do + __text="${__text} ${CY}${V}${NC} | ${MAP_COMMAND_DESC[$V]}\n" + done + + echo -e "$__text" | as_table +} + +################################################################################ +# IMPORT +################################################################################ + +for V in $(ls "$SCRIPT_DIR"/scripts.d/*.sh); do + . $V +done + +################################################################################ +# MAIN +################################################################################ + +function Main() { + local __args=($@) + local __command=${__args[0]} + + if [[ -n $__command ]]; then + for __cmd in $(echo "${!MAP_COMMAND[@]}"); do + if [ $__command = $__cmd ]; then + AppHeader + ${MAP_COMMAND[$__cmd]} ${__args[@]:1} + return + fi + done + + LogError "Не известная команда '${__command}'" + echo + fi + + fn_command_help +} + +################################################################################ + +Main $@ diff --git a/scripts/scripts.d/00-environment.sh b/scripts/scripts.d/00-environment.sh new file mode 100644 index 0000000..aba54d3 --- /dev/null +++ b/scripts/scripts.d/00-environment.sh @@ -0,0 +1,18 @@ +#!/bin/bash +# vi: set tabstop=2 shiftwidth=2 noexpandtab : +DD_DEBUG=${DEBUG:-0} + +SSH_TARGET=dedic2 + +ANSIBLE_TARGET_HOST=dedic2 +ANSIBLE_PLAYBOOK=DevDi9.playbook.yml + +ANSIBLE_PARTS=( + system + postgres + gitea +) +ANSIBLE_PARTS_RESTORE=(gitea) + +ANSIBLE_BECOME=0 +ANSIBLE_BECOME_USER=root diff --git a/scripts/scripts.d/10-install.sh b/scripts/scripts.d/10-install.sh new file mode 100644 index 0000000..c571578 --- /dev/null +++ b/scripts/scripts.d/10-install.sh @@ -0,0 +1,76 @@ +#!/bin/bash +# vi: set tabstop=2 shiftwidth=2 noexpandtab : + +MAP_COMMAND["install"]=fn_command_install +MAP_COMMAND_DESC["install"]="запуск установки." +MAP_COMMAND_HELP["install"]=fn_command_install_help + +function fn_command_install() { + local __parts=($@) + + if [[ "list" == "${__parts[0]}" ]]; then + echo "Части playbook'а:" + for __ansible_part in "${ANSIBLE_PARTS[@]}"; do + echo -e " - ${CY}${__ansible_part}${NC}" + done + exit 0 + fi + + if [[ ${#__parts[@]} -gt 0 ]]; then + # Проверяем указанные части + for __part in "${__parts[@]}"; do + if [[ ! "${ANSIBLE_PARTS[*]}" =~ "${__part}" ]]; then + LogError "Unknown part: ${CY}${__part}${NC}" + exit 1 + fi + done + fi + + run ${__parts[*]} +} + +function run() { + local __parts=($@) + + local __ansible_extra_vars + __ansible_extra_vars="--extra-vars \"dd_vars=$ANSIBLE_TARGET_HOST\"" + + if [[ ${#__parts[@]} -eq 0 ]]; then + __ansible_extra_vars="$__ansible_extra_vars --extra-vars \"dd_install=true\"" + else + for __part in "${__parts[@]}"; do + __ansible_extra_vars="$__ansible_extra_vars --extra-vars \"dd_install_${__part}=true\"" + done + fi + + local __ansible_become="" + if [[ $ANSIBLE_BECOME == 1 ]]; then + __ansible_become="--become --become-user=$ANSIBLE_BECOME_USER" + fi + + local __ansible_vvv="" + if [[ $DD_DEBUG -gt 1 ]]; then + __ansible_vvv="-vvv" + fi + + local __ansible_eval="ansible-playbook \ + $__ansible_vvv \ + $__ansible_become \ + -i "$BASE_DIR"/hosts.yml \ + -l "$ANSIBLE_TARGET_HOST" \ + "$BASE_DIR"/"$ANSIBLE_PLAYBOOK" \ + $__ansible_extra_vars" + + Title "Start Annsible Playbook" + LogDebug $__ansible_eval + eval $__ansible_eval +} + +function fn_command_install_help() { + echo "Использование:" + echo -e " ${CW}$(basename $0) ${CY}install ${CC}[list|]${NC}" + echo -e "\nКоманды:" + echo -e " ${CY}list${NC} - показать список известных частей playbook'а." + echo -e " ${CY}${NC} - (опционально) установить только часть playbook'а. Можно указать несколько частей, разделяя их запятой(,)." + echo -e " * - Полная установка." +} diff --git a/scripts/scripts.d/20-backup.sh b/scripts/scripts.d/20-backup.sh new file mode 100644 index 0000000..7ff7374 --- /dev/null +++ b/scripts/scripts.d/20-backup.sh @@ -0,0 +1,117 @@ +#!/bin/bash +# vi: set tabstop=2 shiftwidth=2 noexpandtab : + +MAP_COMMAND["backup"]=fn_command_backup +MAP_COMMAND_DESC["backup"]="создание резервной копии." +MAP_COMMAND_HELP["backup"]=fn_command_backup_help + +ARRAY_BACKUP_PARTS=() +ARRAY_BACKUP_FLAGS=() + +function fn_command_backup() { + local __parts=($@) + + if [[ "list" == "${__parts[0]}" ]]; then + echo "Части playbook'а:" + for __ansible_part in "${ANSIBLE_PARTS_RESTORE[@]}"; do + echo -e " - ${CY}${__ansible_part}${NC}" + done + exit 0 + fi + + if [[ ${#__parts[@]} -gt 0 ]]; then + # Разеляем флаги и ansible части + for __part in "${__parts[@]}"; do + if [[ "$__part" = '-'* ]]; then + ARRAY_BACKUP_FLAGS+=($__part) + else + ARRAY_BACKUP_PARTS+=($__part) + fi + done + fi + + if [[ ${#ARRAY_BACKUP_PARTS[@]} -gt 0 ]]; then + # Проверяем указанные части + for __part in "${ARRAY_BACKUP_PARTS[@]}"; do + if [[ ! "${ANSIBLE_PARTS_RESTORE[*]}" =~ "${__part}" ]]; then + LogError "Unknown part: ${CY}${__part}${NC}" + exit 1 + fi + done + fi + + fn_command_backup_run +} + +function fn_command_backup_run() { + local __ansible_extra_vars + __ansible_extra_vars="--extra-vars \"dd_vars=$ANSIBLE_TARGET_HOST\"" + + if [[ ${#ARRAY_BACKUP_PARTS[@]} -eq 0 ]]; then + __ansible_extra_vars="$__ansible_extra_vars --extra-vars \"dd_backup=true\"" + else + for __part in "${ARRAY_BACKUP_PARTS[@]}"; do + __ansible_extra_vars="$__ansible_extra_vars --extra-vars \"dd_backup_$__part=true\"" + done + fi + + local __flag_remote_only=0 + for __flag in "${ARRAY_BACKUP_FLAGS[@]}"; do + if [[ $__flag = "-r" ]] || [[ $__flag = "--remote" ]] || [[ $__flag = "--remote-only" ]]; then + __flag_remote_only=1 + break + fi + done + + local __postbackup_file="" + if [[ $__flag_remote_only -eq 0 ]]; then + __postbackup_file="/tmp/$(date +%s)" + __ansible_extra_vars="$__ansible_extra_vars --extra-vars \"dd_postbackup=true\"" + __ansible_extra_vars="$__ansible_extra_vars --extra-vars \"dd_postbackup_file=${__postbackup_file}\"" + fi + + local __ansible_become="" + if [[ $ANSIBLE_BECOME == 1 ]]; then + __ansible_become="--become --become-user=$ANSIBLE_BECOME_USER" + fi + + local __ansible_vvv="" + if [[ $DD_DEBUG -gt 1 ]]; then + __ansible_vvv="-vvv" + fi + + local __ansible_eval="ansible-playbook \ + $__ansible_vvv \ + $__ansible_become \ + -i "$BASE_DIR"/hosts.yml \ + -l "$ANSIBLE_TARGET_HOST" \ + "$BASE_DIR"/"$ANSIBLE_PLAYBOOK" \ + $__ansible_extra_vars" + + Title "Start Annsible Playbook" + LogDebug $__ansible_eval + eval $__ansible_eval + + if [[ $__flag_remote_only -eq 0 ]]; then + Title "Download files" + + chmod +x "$__postbackup_file" + bash -c "$__postbackup_file" + rm -f "$__postbackup_file" + + Title "Remove files" + + chmod +x "${__postbackup_file}_clean" + bash -c "${__postbackup_file}_clean" + rm -f "${__postbackup_file}_clean" + fi +} + +function fn_command_backup_help() { + echo "Использование:" + echo -e " ${CW}$(basename $0) ${CY}backup ${CC}[list|]${NC}" + echo -e "\nКоманды:" + echo -e " ${CY}list${NC} - показать список известных частей playbook'а с возможностью создания резервной копии." + echo -e " ${CY}${NC} - (опционально) установить только часть playbook'а. Можно указать несколько частей, разделяя их запятой(,)." + echo -e " * - Создание полной резервной копии." +} diff --git a/scripts/scripts.d/30-restore.sh b/scripts/scripts.d/30-restore.sh new file mode 100644 index 0000000..6bb018a --- /dev/null +++ b/scripts/scripts.d/30-restore.sh @@ -0,0 +1,203 @@ +#!/bin/bash +# vi: set tabstop=2 shiftwidth=2 noexpandtab : + +MAP_COMMAND["restore"]=fn_command_restore +MAP_COMMAND_DESC["restore"]="восстановление резервной копии." +MAP_COMMAND_HELP["restore"]=fn_command_restore_help + +ARRAY_RESTORE_PARTS=() +declare -A MAP_RESTORE_FLAGS +PRERESTORE_FILE="" + +function fn_command_restore_break() { + echo "-- BREAK --" + exit 1 +} + +function fn_command_restore() { + local __parts=($@) + + # Default values + MAP_RESTORE_FLAGS["remote_only"]=0 + MAP_RESTORE_FLAGS["datetime"]="latest" + MAP_RESTORE_FLAGS["inventory"]="$ANSIBLE_TARGET_HOST" + + # Trapping Ctrl-C + trap fn_command_restore_break INT + + if [[ "list" == "${__parts[0]}" ]]; then + echo "Части playbook'а:" + for __ansible_part in "${ANSIBLE_PARTS_RESTORE[@]}"; do + echo -e " - ${CY}${__ansible_part}${NC}" + done + exit 0 + fi + + local __flag_arg="" + if [[ ${#__parts[@]} -gt 0 ]]; then + # Разеляем флаги и ansible части + for __part in "${__parts[@]}"; do + if [[ "$__part" = '-'* ]]; then + if [[ -n $__flag_arg ]]; then + LogError "Missing flag argument for '${__flag_arg}'" + exit 1 + fi + + if [[ "-i" = "$__part" ]] || [[ "--inventory" = "$__part" ]]; then + __flag_arg="inventory" + elif [[ "-d" = "$__part" ]] || [[ "--datetime" = "$__part" ]]; then + __flag_arg="datetime" + elif [[ "-r" = "$__part" ]] || [[ "--remote-only" = "$__part" ]]; then + MAP_RESTORE_FLAGS["remote_only"]=1 + fi + else + if [[ -n $__flag_arg ]]; then + MAP_RESTORE_FLAGS["$__flag_arg"]="$__part" + __flag_arg="" + else + ARRAY_RESTORE_PARTS+=($__part) + fi + fi + done + fi + + if [[ -n $__flag_arg ]]; then + LogError "Missing flag argument for '${__flag_arg}'" + exit 1 + fi + + LogDebug "ARRAY_RESTORE_PARTS: ${ARRAY_RESTORE_PARTS[*]}" + LogDebug "MAP_RESTORE_FLAGS.keys: ${!MAP_RESTORE_FLAGS[@]}" + LogDebug "MAP_RESTORE_FLAGS.value: ${MAP_RESTORE_FLAGS[@]}" + + if [[ ${#ARRAY_RESTORE_PARTS[@]} -gt 0 ]]; then + # Проверяем указанные части + local __check=0 + for __part in "${ARRAY_RESTORE_PARTS[@]}"; do + __check=0 + for __ansible_part in "${ANSIBLE_PARTS_RESTORE[@]}"; do + if [[ $__part = $__ansible_part ]]; then + __check=1 + break + fi + done + + if [[ $__check -eq 0 ]]; then + LogError "Unknown part for restore: ${CY}${__part}${NC}" + exit 1 + fi + done + unset __check + fi + + fn_command_restore_pre_run + fn_command_restore_run + fn_command_restore_post_run +} + +function fn_command_restore_pre_run() { + if [[ MAP_RESTORE_FLAGS["remote_only"] -eq 1 ]]; then + return + fi + + local __extra_vars + + __ansible_extra_vars="--extra-vars \"dd_vars=$TARGET_HOST\"" + if [[ ${#ARRAY_RESTORE_PARTS} -eq 0 ]]; then + __ansible_extra_vars="$__ansible_extra_vars --extra-vars \"dd_prerestore=true\"" + else + for __part in "${ARRAY_RESTORE_PARTS[@]}"; do + __ansible_extra_vars="$__ansible_extra_vars --extra-vars \"dd_prerestore_${__part}=true\"" + done + fi + + PRERESTORE_FILE="/tmp/$(date +%s)" + + __ansible_extra_vars="$__ansible_extra_vars --extra-vars \"dd_restore_datetime=${MAP_RESTORE_FLAGS["datetime"]}\"" + __ansible_extra_vars="$__ansible_extra_vars --extra-vars \"dd_restore_inventory=${MAP_RESTORE_FLAGS["inventory"]}\"" + __ansible_extra_vars="$__ansible_extra_vars --extra-vars \"dd_prerestore_file=${PRERESTORE_FILE}\"" + + local __ansible_vvv="" + if [[ $DD_DEBUG -gt 1 ]]; then + __ansible_vvv="-vvv" + fi + + local __ansible_eval="ansible-playbook \ + $__ansible_vvv \ + -i "$BASE_DIR"/hosts.yml \ + -l "$ANSIBLE_TARGET_HOST" \ + "$BASE_DIR"/"$ANSIBLE_PLAYBOOK" \ + $__ansible_extra_vars" + + Title "Pre restore Ansible" + LogDebug $__ansible_eval + eval $__ansible_eval + + Title "Send files" + + chmod +x "$PRERESTORE_FILE" + bash -c "$PRERESTORE_FILE" + rm -f "$PRERESTORE_FILE" +} + +function fn_command_restore_run() { + local __ansible_extra_vars + __ansible_extra_vars="--extra-vars \"dd_vars=$ANSIBLE_TARGET_HOST\"" + + if [[ ${#ARRAY_RESTORE_PARTS[@]} -eq 0 ]]; then + __ansible_extra_vars="$__ansible_extra_vars --extra-vars \"dd_restore=true\"" + else + for __part in "${ARRAY_RESTORE_PARTS[@]}"; do + __ansible_extra_vars="$__ansible_extra_vars --extra-vars \"dd_restore_${__part}=true\"" + done + fi + + __ansible_extra_vars="$__ansible_extra_vars --extra-vars \"dd_restore_datetime=${MAP_RESTORE_FLAGS["datetime"]}\"" + __ansible_extra_vars="$__ansible_extra_vars --extra-vars \"dd_restore_inventory=${MAP_RESTORE_FLAGS["inventory"]}\"" + + local __ansible_become="" + if [[ $ANSIBLE_BECOME == 1 ]]; then + __ansible_become="--become --become-user=$ANSIBLE_BECOME_USER" + fi + + local __ansible_vvv="" + if [[ $DD_DEBUG -gt 1 ]]; then + __ansible_vvv="-vvv" + fi + + local __ansible_eval="ansible-playbook \ + $__ansible_vvv \ + $__ansible_become \ + -i "$BASE_DIR"/hosts.yml \ + -l "$ANSIBLE_TARGET_HOST" \ + "$BASE_DIR"/"$ANSIBLE_PLAYBOOK" \ + $__ansible_extra_vars" + + Title "Start Annsible Playbook" + LogDebug $__ansible_eval + eval $__ansible_eval +} + +function fn_command_restore_post_run() { + if [[ MAP_RESTORE_FLAGS["remote_only"] -eq 1 ]]; then + return + fi + + Title "Remove files" + + chmod +x "${PRERESTORE_FILE}_clean" + bash -c "${PRERESTORE_FILE}_clean" + rm -f "${PRERESTORE_FILE}_clean" +} + +function fn_command_restore_help() { + echo "Использование:" + echo -e " ${CW}$(basename $0) ${CY}restore ${CC}[list|] [-i|--inventory inventory_name] [-d|--datetime ]${NC}" + echo -e "\nКоманды:" + echo -e " ${CY}list${NC} - показать список известных частей playbook'а с возможностью восстановления из резервной копии." + echo -e " ${CY}${NC} - (опционально) восстановить только часть playbook'а. Можно указать несколько частей." + echo -e " ${CY}-i|--inventory${NC} - (опционально) восстановить из указанного ansible inventory." + echo -e " ${CY}-d|--datetime${NC} - (опционально) восстановить из указанной копии." + echo -e " ${CY}-r|--remote-only${NC} - (опционально) использовать резервную копию ранее загруженную на удалённый хост." + echo -e " * - Полное восстановление." +} diff --git a/scripts/scripts.d/99-openports.sh b/scripts/scripts.d/99-openports.sh new file mode 100644 index 0000000..4b78c9b --- /dev/null +++ b/scripts/scripts.d/99-openports.sh @@ -0,0 +1,20 @@ +#!/bin/bash +# vi: set tabstop=2 shiftwidth=2 noexpandtab : + +MAP_COMMAND["openports"]=fn_command_openports +MAP_COMMAND_DESC["openports"]="проброс локальных портов." +MAP_COMMAND_HELP["openports"]=fn_command_openports_help + +function fn_command_openports() { + echo "Open SSH connection to" + echo " - Postgres (6543 -> 5432)" + + ssh -N \ + -L127.0.0.1:6543:127.0.0.1:5432 \ + $SSH_TARGET +} + +function fn_command_openports_help() { + echo "Описание:" + echo " Пробрасывает локальные порты через SSH на удалённый хост." +}