#!/usr/bin/env bash # TA-Proxmenu preloader [ "${2}" != "q" ] && source /opt/idssys/defaults/colors.inc source /opt/idssys/defaults/default.inc source /opt/idssys/ta-proxmenu/defaults.inc VALID_GIT_URL() { [[ "$1" =~ ^https?://[A-Za-z0-9._-]+(:[0-9]+)?/[A-Za-z0-9._/-]+$ ]] } SWITCH_GIT_URL() { local repository='/opt/idssys/ta-proxmenu' local new_url="${1:-}" local assume_yes="${2:-}" local local_hostname local local_short_hostname local node local node_output local successful=0 local failed=0 local -a cluster_nodes=() if [[ ! -d "${repository}/.git" ]]; then echo -e "${idsCL[Red]}TA-ProxMenu is not a Git repository.${idsCL[Default]}" return 1 fi if [[ -z "$new_url" ]]; then echo -en "${idsCL[LightCyan]}New TA-ProxMenu Git URL: ${idsCL[Default]}" read -r -e new_url fi if ! VALID_GIT_URL "$new_url"; then echo -e "${idsCL[Red]}Enter a complete HTTP or HTTPS repository URL without embedded credentials.${idsCL[Default]}" echo -e "${idsCL[LightYellow]}Example: https://git.example.com/organization/TA-ProxMenu.git${idsCL[Default]}" return 1 fi if command -v pvecm >/dev/null 2>&1; then mapfile -t cluster_nodes < <( pvecm nodes 2>/dev/null | awk ' $1 ~ /^(0x)?[[:xdigit:]]+$/ && $2 ~ /^[0-9]+$/ && $3 != "" { print $3 } ' ) fi if (( ${#cluster_nodes[@]} == 0 )); then cluster_nodes=("$(hostname -s)") fi echo echo -e "${idsCL[LightCyan]}Repository URL:${idsCL[Default]} $new_url" echo -e "${idsCL[LightCyan]}Target nodes:${idsCL[Default]} ${cluster_nodes[*]}" if [[ "$assume_yes" != "--yes" ]]; then echo -en "${idsCL[LightYellow]}Change origin on every listed node (y/N)? ${idsCL[Default]}" read -r -n 1 choice echo [[ "$choice" == [Yy] ]] || { echo -e "${idsCL[LightYellow]}Git URL migration cancelled.${idsCL[Default]}" return 1 } fi local_hostname="$(hostname)" local_short_hostname="$(hostname -s)" for node in "${cluster_nodes[@]}"; do echo -en "${idsCL[LightCyan]}${node}:${idsCL[Default]} " if [[ "$node" == "$local_hostname" || "$node" == "$local_short_hostname" ]]; then if ! GIT_TERMINAL_PROMPT=0 timeout 20 \ git -C "$repository" ls-remote --exit-code \ "$new_url" refs/heads/main >/dev/null 2>&1; then echo -e "${idsCL[Red]}new repository is unavailable or requires credentials${idsCL[Default]}" ((failed += 1)) continue fi if git -C "$repository" remote set-url origin "$new_url"; then echo -e "${idsCL[Green]}origin updated${idsCL[Default]}" ((successful += 1)) else echo -e "${idsCL[Red]}could not update origin${idsCL[Default]}" ((failed += 1)) fi continue fi node_output="$( ssh \ -o BatchMode=yes \ -o ConnectTimeout=10 \ "root@${node}" \ "test -d '${repository}/.git' && GIT_TERMINAL_PROMPT=0 timeout 20 git -C '${repository}' ls-remote --exit-code '${new_url}' refs/heads/main >/dev/null 2>&1 && git -C '${repository}' remote set-url origin '${new_url}'" \ 2>&1 )" if [[ $? -eq 0 ]]; then echo -e "${idsCL[Green]}origin updated${idsCL[Default]}" ((successful += 1)) else echo -e "${idsCL[Red]}failed${idsCL[Default]}" [[ -n "$node_output" ]] && echo " $node_output" ((failed += 1)) fi done echo echo -e "${idsCL[Green]}Updated nodes: ${successful}${idsCL[Default]}" if ((failed > 0)); then echo -e "${idsCL[Red]}Failed nodes: ${failed}${idsCL[Default]}" echo -e "${idsCL[LightYellow]}A failed node was left on its existing origin URL.${idsCL[Default]}" return 1 fi echo -e "${idsCL[Green]}Every installed cluster node now uses the new Git URL.${idsCL[Default]}" } SWITCH_TO_V2() { local repository='/opt/idssys/ta-proxmenu' local current_branch local head_commit local local_commit local main_commit local remote_commit if [[ ! -d "${repository}/.git" ]]; then echo -e "${idsCL[Red]}TA-ProxMenu is not a Git repository.${idsCL[Default]}" return 1 fi current_branch="$(git -C "$repository" branch --show-current 2>/dev/null)" if [[ "$current_branch" == "V2" ]]; then exec /opt/idssys/ta-proxmenu/run.sh fi if [[ -n "$(git -C "$repository" status --porcelain --untracked-files=normal)" ]]; then echo -e "${idsCL[LightYellow]}TA-ProxMenu has local changes; branch switching was refused to preserve them.${idsCL[Default]}" git -C "$repository" status --short return 1 fi echo -e "${idsCL[LightCyan]}Fetching TA-ProxMenu branch 'V2'...${idsCL[Default]}" if ! timeout 30 git -C "$repository" fetch --prune origin \ '+refs/heads/main:refs/remotes/origin/main' \ '+refs/heads/V2:refs/remotes/origin/V2' >/dev/null 2>&1; then echo -e "${idsCL[Red]}Could not fetch branch 'V2' from origin.${idsCL[Default]}" return 1 fi if [[ -z "$current_branch" ]]; then head_commit="$(git -C "$repository" rev-parse --verify 'HEAD^{commit}' 2>/dev/null)" main_commit="$(git -C "$repository" rev-parse --verify \ 'refs/remotes/origin/main^{commit}' 2>/dev/null)" if [[ -z "$head_commit" || "$head_commit" != "$main_commit" ]]; then echo -e "${idsCL[Red]}TA-ProxMenu has an unrecognized detached HEAD; branch switching was refused.${idsCL[Default]}" return 1 fi echo -e "${idsCL[LightCyan]}Recovered the legacy updater's detached main checkout.${idsCL[Default]}" fi remote_commit="$(git -C "$repository" rev-parse --verify \ 'refs/remotes/origin/V2^{commit}' 2>/dev/null)" || { echo -e "${idsCL[Red]}Origin does not provide a usable V2 branch.${idsCL[Default]}" return 1 } if git -C "$repository" show-ref --verify --quiet refs/heads/V2; then local_commit="$(git -C "$repository" rev-parse --verify \ 'refs/heads/V2^{commit}' 2>/dev/null)" || return 1 if [[ "$local_commit" != "$remote_commit" ]] && ! git -C "$repository" merge-base --is-ancestor \ "$local_commit" "$remote_commit"; then echo -e "${idsCL[LightYellow]}Local branch 'V2' has local-only or diverged commits; switching was refused.${idsCL[Default]}" return 1 fi git -C "$repository" switch V2 >/dev/null || return 1 if [[ "$local_commit" != "$remote_commit" ]] && ! git -C "$repository" merge --ff-only \ refs/remotes/origin/V2 >/dev/null; then echo -e "${idsCL[Red]}Could not fast-forward V2; no commits were discarded.${idsCL[Default]}" return 1 fi else git -C "$repository" switch --create V2 \ --track origin/V2 >/dev/null || return 1 fi rm -f /var/cache/ta-proxmenu/update-status 2>/dev/null || true echo -e "${idsCL[Green]}TA-ProxMenu is now using branch 'V2'. Loading the V2 menu...${idsCL[Default]}" exec /opt/idssys/ta-proxmenu/run.sh } if [[ "${1:-}" == "V2" ]]; then SWITCH_TO_V2 exit $? fi if [[ "${1:-}" == "git-url" ]]; then SWITCH_GIT_URL "${2:-}" "${3:-}" exit $? fi if [[ "${noupdate}" != *" ${1} "* ]] && [[ "${noupdate}" != *" ${2} "* ]]; then if GIT_TERMINAL_PROMPT=0 timeout 15 git -C /opt/idssys/ta-proxmenu \ ls-remote --exit-code origin refs/heads/main >/dev/null 2>&1; then if [ "${1}" != "tapm" ]; then echo -en "${idsCL[LightCyan]}Checking for updates...${idsCL[Default]}" echo "" udtd=0 fi if [ "${1}" != "tapm" ]; then if [ ! -d /opt/idssys/defaults ]; then git clone https://git.scity.us/voltron/iDS-Defaults.git /opt/idssys/defaults else cd /opt/idssys/defaults if [ "`git log --pretty=%H ...refs/heads/master^ | head -n 1`" != "`git ls-remote origin -h refs/heads/master |cut -f1`" ]; then if [ "${1}" != "tapm" ]; then echo -en "\e[1A"; echo -en "\e[0K\r${idsCL[LightCyan]}Updating iDSSYS-Defaults...${idsCL[Default]}" udtd=1 fi git fetch origin master >/dev/null 2>&1 git reset --hard origin/master >/dev/null 2>&1 git reflog expire --expire=now --all >/dev/null 2>&1 git repack -ad >/dev/null 2>&1 git prune >/dev/null 2>&1 git pull >/dev/null 2>&1 [ "${1}" != "tapm" ] && echo -e "${idsCL[Green]}Done${idsCL[Default]}" fi fi fi cd /opt/idssys/ta-proxmenu if [ "`git log --pretty=%H ...refs/heads/main^ | head -n 1`" != "`git ls-remote origin -h refs/heads/main |cut -f1`" ]; then if [ "${1}" != "tapm" ]; then [ ${udtd} -eq 0 ] && echo -en "\e[1A"; echo -en "\e[0K\r${idsCL[LightCyan]}Updating TA-Proxmenu...${idsCL[Default]}" fi git fetch origin main >/dev/null 2>&1 git reset --hard origin/main >/dev/null 2>&1 git reflog expire --expire=now --all >/dev/null 2>&1 git repack -ad >/dev/null 2>&1 git prune >/dev/null 2>&1 git pull >/dev/null 2>&1 if [ "${1}" != "tapm" ]; then source /opt/idssys/ta-proxmenu/defaults.inc # echo -en "\e[1A"; # echo -e "\e[0K\r ${idsCL[Green]}Updated to v${VERS}${idsCL[Default]}" echo -e " ${idsCL[Green]}Updated to v${VERS}${idsCL[Default]}\n" fi elif [ "${1}" != "tapm" ] && [ ${udtd} -eq 0 ]; then echo -e "\e[1A\e[0K\r ${idsCL[Green]}No updates available${idsCL[Default]}\n" fi else echo -e "${idsCL[Red]}Could not connect to the configured TA-ProxMenu Git origin for updates${idsCL[Default]}" fi fi if [ "${1}" != "tapm" ] && [ "${1}" != "update" ] && [ "${1}" != "u" ]; then /opt/idssys/ta-proxmenu/proxmenu-scripts.sh $1 $2 $3 $4 fi exit 0