diff --git a/gitapply.sh b/gitapply.sh index c927e3844..4c0ac3e65 100755 --- a/gitapply.sh +++ b/gitapply.sh @@ -26,6 +26,31 @@ NC='\e[0m' # Spinner frames SPIN=('⣾' '⣽' '⣻' '⢿' '⡿' '⣟' '⣯' '⣷') +# Node list +NODES=( + "10.0.254.100" + "10.0.254.101" + "10.0.254.102" + "10.0.254.103" + "10.0.254.104" + "10.0.254.105" + "10.0.254.106" + "10.0.254.107" + "10.0.254.108" + "10.0.254.109" + "10.0.254.110" +) + +# Get current node IP +CURRENT_IP=$(hostname -I | awk '{print $1}') + +# Status tracking directory +STATUS_DIR="/tmp/virtnet_deploy_$$" +mkdir -p "$STATUS_DIR" + +# SSH Key (stored securely) +SSH_KEY="/root/.ssh/virtnet_deploy" + # ============================================================================ # FUNCTIONS # ============================================================================ @@ -39,6 +64,7 @@ print_header() { echo -e " ${C1}╚██╗ ██╔╝${C2}██║${C3}██╔══██╗${C3} ██║ ${C4}██║╚██╗██║${C5}██╔══╝ ${C6} ██║ ${NC}" echo -e " ${C1} ╚████╔╝ ${C2}██║${C3}██║ ██║${C3} ██║ ${C4}██║ ╚████║${C5}███████╗${C6} ██║ ${NC}" echo -e " ${C1} ╚═══╝ ${C2}╚═╝${C3}╚═╝ ╚═╝${C3} ╚═╝ ${C4}╚═╝ ╚═══╝${C5}╚══════╝${C6} ╚═╝ ${NC}" + echo -e " ${C6}${BOLD}.bond${NC}" echo "" echo -e " ${C4}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" echo -e " ${WHITE}${BOLD} Paymenter Load Balancer - Git Update & Apply${NC}" @@ -90,24 +116,156 @@ countdown() { printf "\r ${C6}●${NC} Ready! ${GREEN}✓${NC}\n" } +# Run update on remote node +run_remote_update() { + local node=$1 + local status_file="$STATUS_DIR/$node" + echo "pending" > "$status_file" + + ssh -o StrictHostKeyChecking=no -o ConnectTimeout=10 -i "$SSH_KEY" root@"$node" \ + 'cd /var/www/paymenter && git pull && php artisan view:clear && php artisan cache:clear && systemctl restart php8.3-fpm' \ + > "$STATUS_DIR/${node}.log" 2>&1 + + if [ $? -eq 0 ]; then + echo "done" > "$status_file" + else + echo "failed" > "$status_file" + fi +} + +# Display node status panel +print_node_status() { + local cols=3 + local count=0 + + echo -e "\n${C4}┌─${NC} ${C5}${BOLD}Cluster Node Status${NC}" + echo -e " ${GRAY}┌─────────────────┬─────────────────┬─────────────────┐${NC}" + + local row="" + for node in "${NODES[@]}"; do + if [[ "$node" == "$CURRENT_IP" ]]; then + continue + fi + + local status_file="$STATUS_DIR/$node" + local status="waiting" + [[ -f "$status_file" ]] && status=$(cat "$status_file") + + local icon="" + local color="" + case "$status" in + "pending") icon="◐"; color="$C3" ;; + "done") icon="●"; color="$GREEN" ;; + "failed") icon="●"; color="$RED" ;; + *) icon="○"; color="$GRAY" ;; + esac + + local short_ip="${node##*.}" + row+=" ${color}${icon}${NC} .${short_ip}" + count=$((count + 1)) + + if [ $((count % cols)) -eq 0 ]; then + printf " │%-17s│%-17s│%-17s│\n" $row + row="" + fi + done + + # Print remaining nodes + if [ -n "$row" ]; then + while [ $((count % cols)) -ne 0 ]; do + row+=" " + count=$((count + 1)) + done + printf " │%-17s│%-17s│%-17s│\n" $row + fi + + echo -e " ${GRAY}└─────────────────┴─────────────────┴─────────────────┘${NC}" +} + +# Animated node status display +update_node_display() { + local all_done=false + while ! $all_done; do + all_done=true + + # Move cursor up and redraw + tput sc # Save cursor position + + echo -e "\r ${GRAY}┌─────────────────────────────────────────────────────┐${NC}" + + for node in "${NODES[@]}"; do + if [[ "$node" == "$CURRENT_IP" ]]; then + continue + fi + + local status_file="$STATUS_DIR/$node" + local status="waiting" + [[ -f "$status_file" ]] && status=$(cat "$status_file") + + local icon="" color="" + case "$status" in + "pending") icon="⣾"; color="$C3"; all_done=false ;; + "done") icon="●"; color="$GREEN" ;; + "failed") icon="●"; color="$RED" ;; + *) icon="○"; color="$GRAY"; all_done=false ;; + esac + + printf " ${GRAY}│${NC} ${color}${icon}${NC} %-15s" "$node" + done + + echo -e "\r ${GRAY}└─────────────────────────────────────────────────────┘${NC}" + + sleep 0.3 + + if ! $all_done; then + tput rc # Restore cursor position + fi + done +} + print_complete() { echo "" echo -e " ${C4}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" echo "" echo -e " ${C6}${BOLD}🚀 UPDATE COMPLETE${NC}" echo "" - echo -e " ${GRAY}Paymenter has been updated and all services restarted.${NC}" + + # Count successes and failures + local success=0 failed=0 + for node in "${NODES[@]}"; do + if [[ "$node" == "$CURRENT_IP" ]]; then + success=$((success + 1)) + continue + fi + local status_file="$STATUS_DIR/$node" + if [[ -f "$status_file" ]] && [[ "$(cat "$status_file")" == "done" ]]; then + success=$((success + 1)) + else + failed=$((failed + 1)) + fi + done + + echo -e " ${GRAY}Local node updated successfully.${NC}" + echo -e " ${GREEN}●${NC} ${success} nodes updated ${RED}●${NC} ${failed} nodes failed" echo "" echo -e " ${C4}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" echo "" } +cleanup() { + rm -rf "$STATUS_DIR" +} +trap cleanup EXIT + # ============================================================================ # MAIN SCRIPT # ============================================================================ print_header +echo -e " ${C3}→${NC} ${GRAY}Current Node:${NC} ${C5}${CURRENT_IP}${NC}" +echo -e " ${C3}→${NC} ${GRAY}Target Nodes:${NC} ${C5}${#NODES[@]} nodes in cluster${NC}" + # Random delay sleep_time=$((RANDOM % 5 + 1)) cd /var/www/paymenter @@ -116,8 +274,38 @@ cd /var/www/paymenter task_start "Preparing Update" countdown "$sleep_time" -# Git Pull -task_start "Pulling Latest Changes" +# Start remote updates in background +task_start "Deploying to Remote Nodes" +for node in "${NODES[@]}"; do + if [[ "$node" != "$CURRENT_IP" ]]; then + run_remote_update "$node" & + fi +done + +# Show initial node status +echo -e " ${GRAY}Background deployment started on remote nodes...${NC}" +echo "" + +# Display node grid +echo -e " ${GRAY}┌───────────────┬───────────────┬───────────────┬───────────────┐${NC}" +printf " ${GRAY}│${NC}" +col=0 +for node in "${NODES[@]}"; do + if [[ "$node" == "$CURRENT_IP" ]]; then + continue + fi + short="${node##*.}" + printf " ${GRAY}○${NC} .%-11s${GRAY}│${NC}" "$short" + col=$((col + 1)) + if [ $((col % 4)) -eq 0 ]; then + echo "" + printf " ${GRAY}│${NC}" + fi +done +echo -e "\n ${GRAY}└───────────────┴───────────────┴───────────────┴───────────────┘${NC}" + +# Local Git Pull +task_start "Local: Pulling Latest Changes" task_item "Fetching from remote..." git pull > /tmp/git_output.txt 2>&1 & spinner $! "Fetching from remote..." @@ -139,7 +327,7 @@ head -3 /tmp/git_output.txt | while IFS= read -r line; do done # Clear Caches -task_start "Clearing Caches" +task_start "Local: Clearing Caches" task_item "View cache..." php artisan view:clear > /dev/null 2>&1 & @@ -152,11 +340,51 @@ spinner $! "Application cache..." task_done "Application cache cleared" # Restart PHP-FPM -task_start "Restarting Services" +task_start "Local: Restarting Services" task_item "PHP 8.3 FPM..." systemctl restart php8.3-fpm & spinner $! "PHP 8.3 FPM..." task_done "PHP 8.3 FPM restarted" +# Wait for all remote nodes +task_start "Waiting for Remote Nodes" +task_item "Syncing cluster..." +wait +task_done "All nodes synchronized" + +# Final node status +echo "" +echo -e " ${C4}┌─${NC} ${C5}${BOLD}Final Cluster Status${NC}" +echo -e " ${GRAY}┌───────────────┬───────────────┬───────────────┬───────────────┐${NC}" +printf " ${GRAY}│${NC}" +col=0 +for node in "${NODES[@]}"; do + if [[ "$node" == "$CURRENT_IP" ]]; then + continue + fi + status_file="$STATUS_DIR/$node" + status="failed" + [[ -f "$status_file" ]] && status=$(cat "$status_file") + + icon="" + color="" + if [[ "$status" == "done" ]]; then + icon="●"; color="$GREEN" + else + icon="●"; color="$RED" + fi + + short="${node##*.}" + printf " ${color}${icon}${NC} .%-11s${GRAY}│${NC}" "$short" + col=$((col + 1)) + if [ $((col % 4)) -eq 0 ]; then + echo "" + if [ $col -lt 10 ]; then + printf " ${GRAY}│${NC}" + fi + fi +done +echo -e "\n ${GRAY}└───────────────┴───────────────┴───────────────┴───────────────┘${NC}" + # Complete print_complete diff --git a/setup-ssh-key.sh b/setup-ssh-key.sh new file mode 100644 index 000000000..cf995325a --- /dev/null +++ b/setup-ssh-key.sh @@ -0,0 +1,44 @@ +#!/bin/bash + +# ============================================================================ +# Virtnet.bond - SSH Key Setup Script +# Run this ONCE on a node to set up the deployment key +# ============================================================================ + +mkdir -p /root/.ssh +chmod 700 /root/.ssh + +cat > /root/.ssh/virtnet_deploy << 'KEYEOF' +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAgXks+OQ+dn78uBCj1LyOFKatrdQHvjCcQeC5Wte3+5BxZqAw +ibx311AsTb/k6+xbWwlgnWdso/I70vEzbifnc1DkW0TICXKJJjC4+POkWE+5bkRz +4vpFOQgr/siDkzZd9PMEzZmNdq5o/vf/NYCQPoqZZelJTU4eE//5KEsLXLtJsPBJ +clfL48/rPtr02z0T/kzDxrBQE8iY3I7xb7SElv009DLlJG5P2y6b/IrqzIxUjkWt +v5Z5zH5850hC9y0Auwq1r6Ygle5oT5+GS0fzJLL8zZ44ysyR8NruW/DZos7Qn6z1 +ExPywzcF4elrSIKl7ewXI0VE9ZUfjDC5IW9ZXwIDAQABAoIBACJIPKE2hleH7lCq +j0bAGnrbW3eAggBZDLbg0xN7tQqWR4Cd/9wonC7V2rVHj0zsy4/CXuOuw/RxKmgD +V9PeGwnMrHqCLtlZi3kiQ4gfsy9zBK1u0KSUEgo04LlYzIYJSj2Wr3nlI7D+I20H +q3q2LPtyZYW3jKI8gfhXudhybnLCABpZ7/RcCv8/F6kTrPRNzwb8qiO8kSHXya4a +pMH+DifjtJVgqMzE///n74h0+XEuvl6ZSL1AsWPj6C9pGSynZ5EPl0P0MKZ+/RPv +SVZU5bY028zT8KNxzkjNsCUEwMQB67M7cAVEXDyXmooBGShq1tKV/Wpy6awsC/0c +JdVyNdECgYEAvMLF7xdD2vsxm9TsNEwfcAOOMAvnLAuBVyZBdqGaD31PuAmSbkoF +sQKzQuuifHFX8lQlZgcJiURAPdzL0+IZ2/+s+OyBrxCmAwtA/vlWgKY8DsxIq4ZU +jD9Cb7w0/o+OmYXRcVo+I0RaW92dXH/cGphRPDmBYFEh10Bxmylm2hcCgYEAr5fv +wGT2TEvMT1KiK+nJwMO8qEnnajBrynglR/z1xAqtK9IiU+18kbtn1rFGWNC4YX/H +GKrTCLAse68LwrA32/Nz65fpLHvNYX3W7zZ4dh8gJATKREQ2JEB9HWE+Z1w03/h0 +r5msHNBmvtpj/6emN1eZaMvQE6/UIVFG10BdL/kCgYAr4sjsJqeTERXemil0m0Iv +49O6HfpYRjCDF5TexQGxmjvfmPIfjDw4hF0zMN+tORjucVvklbxE2sZo253UHFxQ +xufrU+luz1sZmBM7dLME5CFQe3Rl1Kxxkv+aRNK5YJ0R2ofwZ7/MqUas1yCP8fY1 +hLZWXzRSNWq9xfDj10NfbwKBgQCfS5jG01DVelYJCA/zAo5y/59glFsJ7I99CG3Z +1tQmWwEqpeFafjHqCzdyfzQwUnlSihbWe/IjCZ/xPKXQowip0zwwWInCPzXc4cph +DOtPTYFc67OLJs5vKMnYI2X3YqDdJorE2wZWxYDQV1MslKynvCKB/ZPwqCwrZY58 +q/leEQKBgQCzASkiJrMpsOZlxpLQksReWviFS9JMhITJMl/eF9bhOgoBnb7Lz0Lj +pL0+ToIxHkv0kcaUvMMZVVqVO+D1bmdxWlOtYXhJw1oOVFYNIETAqgbkWBLFsbxB +TuE9KF3u/HK9Y00SavPrKI76qiXv7wth48iBczKjM5gyu1ZgbFuFLw== +-----END RSA PRIVATE KEY----- +KEYEOF + +chmod 600 /root/.ssh/virtnet_deploy + +echo "SSH key installed to /root/.ssh/virtnet_deploy" +echo "Key permissions set to 600"