#!/usr/bin/env bash # # deploy-lib.sh - shared helpers for deploy.sh and setup.sh. # # Both scripts source this file so output styling and .env handling stay # identical and are defined exactly once. Safe to source multiple times. # # Provides: # log / ok / warn / die / hr - consistent colored output # banner "title" - boxed section banner # step N M "title" - numbered decision/stage header # ask VAR "prompt" "default" - editable-default prompt (honors ARG_YES) # confirm "prompt" - y/N confirm (honors ARG_YES) # get_env KEY / set_env KEY VAL - .env read/write without sourcing it # is_ipv4 ADDR - dotted-quad shape check # # Conventions: callers may set ARG_YES=1 for unattended runs and TAG to # change the log prefix (defaults to "deploy"). TAG="${TAG:-deploy}" ARG_YES="${ARG_YES:-0}" log() { printf '\033[1;36m[%s]\033[0m %s\n' "$TAG" "$*"; } ok() { printf '\033[1;32m[%s] \xe2\x9c\x94\033[0m %s\n' "$TAG" "$*"; } warn() { printf '\033[1;33m[%s][warn]\033[0m %s\n' "$TAG" "$*" >&2; } die() { printf '\033[1;31m[%s][err]\033[0m %s\n' "$TAG" "$*" >&2; exit 1; } hr() { printf '\033[2m%s\033[0m\n' "----------------------------------------------------------------"; } # Boxed banner, e.g.: # +--------------------------------------------------------------+ # | OpenBMP stack deploy | # +--------------------------------------------------------------+ banner() { local title="$1" width=62 printf '\033[1;36m+%s+\n' "$(printf -- '-%.0s' $(seq 1 $width))" printf '| %-*s|\n' "$((width - 2))" "$title" printf '+%s+\033[0m\n' "$(printf -- '-%.0s' $(seq 1 $width))" } # Numbered header for decisions and stages: step 2 5 "Deployment type" step() { local n="$1" total="$2" title="$3" printf '\n\033[1;36m[%s] Step %s/%s\033[0m \033[1m%s\033[0m\n' "$TAG" "$n" "$total" "$title" } # Prompt with an editable default. Honors ARG_YES (accepts default silently). ask() { local __var="$1" __prompt="$2" __default="${3:-}" __reply="" if [ "$ARG_YES" -eq 1 ]; then printf -v "$__var" '%s' "$__default"; return fi if [ -n "$__default" ]; then read -r -p "$__prompt [$__default]: " __reply __reply="${__reply:-$__default}" else read -r -p "$__prompt: " __reply fi printf -v "$__var" '%s' "$__reply" } confirm() { local __prompt="$1" __reply="" [ "$ARG_YES" -eq 1 ] && return 0 read -r -p "$__prompt [y/N]: " __reply [ "$__reply" = "y" ] || [ "$__reply" = "Y" ] } # Read a single KEY=value from .env without sourcing it -- .env contains keys # with hyphens (PROX-CML_*) that a shell `source` would choke on. get_env() { grep -E "^$1=" .env | head -1 | cut -d= -f2- || true; } # Set KEY=value in .env: replace the line if present, else append. set_env() { local key="$1" val="$2" if grep -qE "^${key}=" .env; then # `|` delimiter -- values are hex/IPs, no `|`. sed -i "s|^${key}=.*|${key}=${val}|" .env else printf '%s=%s\n' "$key" "$val" >> .env fi } # Dotted-quad shape check (rejects placeholders like ). is_ipv4() { local ip="$1" o [[ "$ip" =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]] || return 1 IFS=. read -r -a o <<<"$ip" for x in "${o[@]}"; do [ "$x" -le 255 ] || return 1; done return 0 }