# POSIX-compatible shared normalizer. Also mounted beside the bootstrap script. # Inputs are data, never evaluated shell. IPv4/DNS endpoints only in API 1. mc_peer_endpoints() { LC_ALL=C awk -v peers="$1" -v self="$2" -v select_node="${3:-}" ' BEGIN { n=split(peers, entries, ","); self=tolower(self); select_node=tolower(select_node); if(n<2 || n>32 || self=="") exit 1; for(i=1;i<=n;i++) { if(split(entries[i],pair,"=")!=2 || pair[1]!~/^[A-Za-z0-9_][A-Za-z0-9_.-]*$/) exit 1; node=tolower(pair[1]); if(seen[node]++) exit 1; if(split(pair[2],addr,":")!=2 || addr[1]!~/^[A-Za-z0-9][A-Za-z0-9.-]*$/ || addr[2]!~/^[0-9]+$/ || addr[2]+0<1 || addr[2]+0>65535) exit 1; endpoint=tolower(addr[1]) ":" (addr[2]+0); if(addresses[endpoint]++) exit 1; if(node==self) { own++; continue; } if(select_node!="" && node!=select_node) continue; hosts=hosts (count?",":"") addr[1]; ports=ports (count?",":"") (addr[2]+0); count++; } if(own!=1 || count<1 || (select_node!="" && count!=1)) exit 1; print hosts "|" ports; }' } mc_peer_conninfo() { # peers, self, replication user, application name case "$3" in ''|*[!a-zA-Z0-9_.-]*) return 1;; esac case "$4" in ''|*[!a-zA-Z0-9_.-]*) return 1;; esac mc_peer_pair=$(mc_peer_endpoints "$1" "$2") || return 1 printf 'host=%s port=%s user=%s application_name=%s target_session_attrs=primary connect_timeout=2\n' \ "${mc_peer_pair%|*}" "${mc_peer_pair#*|}" "$3" "$4" } mc_peer_write_recovery() ( # PGDATA, peers, self, user, application, slot. No credentials in output. set -eu data=$1 conn=$(mc_peer_conninfo "$2" "$3" "$4" "$5") || exit 1 case "$6" in ''|*[!a-z0-9_]*) exit 1;; esac [ ${#6} -le 63 ] || exit 1 [ -d "$data" ] && [ -f "$data/postgresql.auto.conf" ] && [ ! -L "$data/postgresql.auto.conf" ] || exit 1 [ ! -L "$data/standby.signal" ] || exit 1 umask 077 tmp=$(mktemp "$data/.peer-recovery.XXXXXXXX") trap 'rm -f "$tmp"' EXIT HUP INT TERM sed -e '/^[[:space:]]*primary_conninfo[[:space:]]*=/d' \ -e '/^[[:space:]]*primary_slot_name[[:space:]]*=/d' "$data/postgresql.auto.conf" > "$tmp" printf "primary_conninfo = '%s'\nprimary_slot_name = '%s'\n" "$conn" "$6" >> "$tmp" chmod 600 "$tmp" mv -f "$tmp" "$data/postgresql.auto.conf" [ ! -L "$data/standby.signal" ] || exit 1 touch "$data/standby.signal" chmod 600 "$data/standby.signal" )