learning_ai_common_plat/scripts/godaddy-sync-bytelyst-dns.sh

211 lines
4.8 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
DOMAIN="${GODADDY_DOMAIN:-bytelyst.com}"
TTL="${GODADDY_DNS_TTL:-600}"
TARGET_IP="${GODADDY_DNS_TARGET_IP:-}"
AUTO_IP=false
DRY_RUN=false
VALIDATE=false
HOSTS=("api" "gitea" "admin" "tracker" "llmlab" "ollama")
CONFIG_FILE="${XDG_CONFIG_HOME:-$HOME/.config}/godaddypy/credentials.yaml"
usage() {
cat <<'USAGE'
Upsert ByteLyst GoDaddy A records for the Azure VM cutover.
Usage:
scripts/godaddy-sync-bytelyst-dns.sh [options]
Options:
--ip <address> Target IPv4 address for all managed A records
--auto-ip Detect the current public IP with api.ipify.org
--domain <domain> GoDaddy zone to update (default: bytelyst.com)
--ttl <seconds> TTL for the managed A records (default: 600)
--hosts <csv> Hostnames to manage (default: api,gitea,admin,tracker,llmlab,ollama)
--validate Run dig validation after changes
--dry-run Print the API operations without applying them
-h, --help Show help
Credentials:
- Preferred: GODADDY_API_KEY and GODADDY_API_SECRET
- Fallback: ~/.config/godaddypy/credentials.yaml
Examples:
scripts/godaddy-sync-bytelyst-dns.sh --ip 20.81.12.34 --validate
scripts/godaddy-sync-bytelyst-dns.sh --auto-ip --dry-run
USAGE
}
while [[ $# -gt 0 ]]; do
case "$1" in
--ip)
TARGET_IP="${2:-}"
shift 2
;;
--auto-ip)
AUTO_IP=true
shift
;;
--domain)
DOMAIN="${2:-}"
shift 2
;;
--ttl)
TTL="${2:-}"
shift 2
;;
--hosts)
IFS=',' read -r -a HOSTS <<<"${2:-}"
shift 2
;;
--validate)
VALIDATE=true
shift
;;
--dry-run)
DRY_RUN=true
shift
;;
-h|--help)
usage
exit 0
;;
*)
echo "Unknown arg: $1" >&2
usage
exit 2
;;
esac
done
trim() {
local value="$1"
value="${value#"${value%%[![:space:]]*}"}"
value="${value%"${value##*[![:space:]]}"}"
printf '%s' "$value"
}
load_credential_from_file() {
local key_name="$1"
if [[ ! -f "$CONFIG_FILE" ]]; then
return 1
fi
sed -nE "s/^[[:space:]]*${key_name}:[[:space:]]*['\"]?([^'\"]+)['\"]?[[:space:]]*$/\\1/p" "$CONFIG_FILE" | head -n 1
}
GODADDY_API_KEY="${GODADDY_API_KEY:-}"
GODADDY_API_SECRET="${GODADDY_API_SECRET:-}"
if [[ -z "$GODADDY_API_KEY" ]]; then
GODADDY_API_KEY="$(load_credential_from_file key || true)"
fi
if [[ -z "$GODADDY_API_SECRET" ]]; then
GODADDY_API_SECRET="$(load_credential_from_file secret || true)"
fi
if [[ -z "$GODADDY_API_KEY" || -z "$GODADDY_API_SECRET" ]]; then
echo "Missing GoDaddy credentials. Set GODADDY_API_KEY and GODADDY_API_SECRET, or configure $CONFIG_FILE." >&2
exit 2
fi
if [[ "$AUTO_IP" == true ]]; then
TARGET_IP="$(curl -fsS https://api.ipify.org)"
fi
if [[ -z "$TARGET_IP" ]]; then
echo "Missing target IP. Use --ip <address> or --auto-ip." >&2
exit 2
fi
if [[ ! "$TARGET_IP" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]; then
echo "Target IP does not look like an IPv4 address: $TARGET_IP" >&2
exit 2
fi
if [[ ! "$TTL" =~ ^[0-9]+$ ]]; then
echo "TTL must be numeric: $TTL" >&2
exit 2
fi
if ! command -v curl >/dev/null 2>&1; then
echo "curl is required." >&2
exit 1
fi
api_request() {
local method="$1"
local path="$2"
local body="${3:-}"
local -a curl_args=(
-fsS
-X "$method"
-H "Authorization: sso-key ${GODADDY_API_KEY}:${GODADDY_API_SECRET}"
-H "Accept: application/json"
"https://api.godaddy.com${path}"
)
if [[ -n "$body" ]]; then
curl_args+=(-H "Content-Type: application/json" --data "$body")
fi
curl "${curl_args[@]}"
}
printf 'Domain: %s\n' "$DOMAIN"
printf 'Target IP: %s\n' "$TARGET_IP"
printf 'TTL: %s\n' "$TTL"
printf 'Hosts: %s\n' "$(IFS=,; printf '%s' "${HOSTS[*]}")"
for raw_host in "${HOSTS[@]}"; do
host="$(trim "$raw_host")"
if [[ -z "$host" ]]; then
continue
fi
path="/v1/domains/${DOMAIN}/records/A/${host}"
payload=$(printf '[{"data":"%s","ttl":%s}]' "$TARGET_IP" "$TTL")
echo
printf 'Record: %s.%s\n' "$host" "$DOMAIN"
if [[ "$DRY_RUN" == true ]]; then
printf 'Dry run: PUT %s %s\n' "$path" "$payload"
continue
fi
current_records="$(api_request GET "$path" || true)"
if [[ -n "$current_records" ]]; then
printf 'Existing A records: %s\n' "$current_records"
else
echo "Existing A records: none"
fi
api_request PUT "$path" "$payload" >/dev/null
echo "Updated A record."
done
if [[ "$VALIDATE" == true ]]; then
echo
echo "Validation:"
if ! command -v dig >/dev/null 2>&1; then
echo "dig not found; skipping DNS validation." >&2
exit 0
fi
for raw_host in "${HOSTS[@]}"; do
host="$(trim "$raw_host")"
if [[ -z "$host" ]]; then
continue
fi
resolved_ip="$(dig +short "${host}.${DOMAIN}" | tail -n 1)"
printf '%s.%s -> %s\n' "$host" "$DOMAIN" "${resolved_ip:-<no answer>}"
done
fi