#!/bin/bash
set -uo pipefail
#==============================================================#
# File      :   etcd-add
# Desc      :   Create ETCD Cluster / Append Members
# Ctime     :   2025-07-20
# Mtime     :   2025-07-22
# Path      :   bin/etcd-add
# Deps      :   ansible-playbook, etcd.yml
# Docs      :   https://pigsty.io/docs/etcd/admin
# License   :   Apache-2.0 @ https://pigsty.io/docs/about/license/
# Copyright :   2018-2026  Ruohang Feng / Vonng (rh@vonng.com)
#==============================================================#
APP_NAME="$(basename $0)"
APP_DIR="$(cd $(dirname $0) && pwd)"
PIGSTY_HOME=$(cd $(dirname ${APP_DIR}) && pwd)


#--------------------------------------------------------------#
# Usage
#--------------------------------------------------------------#
# bin/etcd-add             # create etcd cluster
# bin/etcd-add [ip...]     # add new members to existing cluster


#--------------------------------------------------------------#
# Utils
#--------------------------------------------------------------#
__CN='\033[0m';__CK='\033[0;30m';__CR='\033[0;31m';__CG='\033[0;32m';
__CY='\033[0;33m';__CB='\033[0;34m';__CM='\033[0;35m';__CC='\033[0;36m';__CW='\033[0;37m';
function log_info() {  printf "[${__CG} OK ${__CN}] ${__CG}$*${__CN}\n";   }
function log_warn() {  printf "[${__CY}WARN${__CN}] ${__CY}$*${__CN}\n";   }
function log_error() { printf "[${__CR}FAIL${__CN}] ${__CR}$*${__CN}\n";   }
function log_debug() { printf "[${__CB}HINT${__CN}] ${__CB}$*${__CN}\n"; }
function log_input() { printf "[${__CM} IN ${__CN}] ${__CM}$*\n=> ${__CN}"; }
function log_hint()  { printf "${__CB}$*${__CN}\n"; }
function log_line()  { printf "${__CM}[$*] ===========================================${__CN}\n"; }
function is_valid_ip(){
    if [[ "$1" =~ (([0-9]|[0-9]{2}|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[0-9]{2}|1[0-9]{2}|2[0-4][0-9]|25[0-5]) ]]; then
        return 0
    else
        return 1
    fi
}

#--------------------------------------------------------------#
# Param
#--------------------------------------------------------------#
ETCD_CLUSTER=${ETCD_CLUSTER:-'etcd'}
cd "${PIGSTY_HOME}"

#--------------------------------------------------------------#
# Create Entire Cluster                   [ 0 arg = create all ]
#--------------------------------------------------------------#
# if no args given, create entire etcd cluster
if (($# == 0)); then
    log_line "WARNING"
    log_warn "You are about to perform a etcd Create Operation!"
    log_warn "This operation will CREATE & RESTART the etcd cluster!"
    log_warn "It will not remove existing etcd cluster and data"
    log_warn "but mis-configuration could lead to DOWNTIME!"
    log_warn "if this is not what your want, Ctrl+C to abort before start!"

    # Countdown from 5 to 1
    for i in 5 4 3 2 1; do
        log_hint "\rCountdown: $i seconds remaining..."
        sleep 1
    done
    log_warn "Proceeding with etcd cluster create operation."

    log_line "EXECUTE"
    log_warn "create etcd cluster '${ETCD_CLUSTER}'"
    log_hint "$ ./etcd.yml -l ${ETCD_CLUSTER}"

    "${PIGSTY_HOME}/etcd.yml" -l "${ETCD_CLUSTER}"

    if [[ $? -ne 0 ]]; then
      log_line "FAILURE"
      log_error "fail to create etcd cluster '${ETCD_CLUSTER}'"
      exit 2
    fi
    log_line "SUMMARY"
    log_info "create etcd cluster ${ETCD_CLUSTER} complete!"
    exit 0
fi


#--------------------------------------------------------------#
# Append Members                            [1+ args = add ips ]
#--------------------------------------------------------------#
# if args given, append specific etcd members by IP
IP_LIST=""
TARGET_PATTERN=""
EXISTS_PATTERN="${ETCD_CLUSTER}"
for ((i=1; i<=$#; i++))
do
  if ! is_valid_ip "${!i}"; then
    log_error "invalid ip address given: ${!i}"
    exit 1
  fi
  IP_LIST="${IP_LIST} ${!i}"
  if [[ -z "${TARGET_PATTERN}" ]]; then
    TARGET_PATTERN="${!i}"
  else
    TARGET_PATTERN="${TARGET_PATTERN},${!i}"
  fi
  EXISTS_PATTERN="${EXISTS_PATTERN},!${!i}"
done

#---------------------------------#
# Planning
#---------------------------------#
log_line "PLANNING"
log_info "append new etcd members: ${IP_LIST} to cluster '${ETCD_CLUSTER}'"
log_warn "  append new members to cluster:"
log_info "    $ ./etcd.yml-l '${TARGET_PATTERN}'"

log_line "WARNING"
log_warn "You are about to perform a etcd cluster expand Operation!"
log_warn "This operation will append new member to the existing etcd cluster!"
log_warn "Mis-configuration could lead to DOWNTIME!"
log_warn "if this is not what your want, Ctrl+C to abort before start!"

# Countdown from 3 to 1
for i in 3 2 1; do
    log_hint "\rCountdown: $i seconds remaining..."
    sleep 1
done
log_warn "Proceeding with etcd cluster expand operation."

#---------------------------------#
# Append Members
#---------------------------------#
log_line "EXECUTE"
log_warn "append etcd members${IP_LIST} to ${ETCD_CLUSTER}"
log_hint "$ ./etcd.yml -e etcd_init=existing -l '${TARGET_PATTERN}'"

"${PIGSTY_HOME}/etcd.yml" -e etcd_init=existing -l "${TARGET_PATTERN}"

if [[ $? -ne 0 ]]; then
  log_line "FAILURE"
  log_error "fail to append etcd members${IP_LIST} to ${ETCD_CLUSTER}"
  exit 4
fi
log_info "append etcd members${IP_LIST} to ${ETCD_CLUSTER} complete"

#---------------------------------#
# Summary
#---------------------------------#
log_line "SUMMARY"
log_info "append etcd members ${IP_LIST} to ${ETCD_CLUSTER} success"

log_line "INSTRUCTIONS"
log_warn "also update existing etcd member config with"
log_hint "$ ./etcd.yml -l '${EXISTS_PATTERN}' --tags=etcd_config,etcd_launch -f 1"

log_warn "also update patroni etcd config with:"
log_hint ".$ ./pgsql.yml -t pg_conf,patroni_reload -e patroni_reload=true"

log_warn "also update vip-manager etcd config with: (if enabled)"
log_hint ".$ ./pgsql.yml -t pg_vip"

exit 0