2626# - `authbridge-proxy` post-binary-split (proxy-sidecar mode);
2727# the operator picks this name when injecting
2828# the proxy-sidecar binary
29- # This script auto-detects which one is in the pod.
29+ # This script auto-detects which one is in the pod. During a rollout it
30+ # probes every sidecar-bearing pod each poll and succeeds as soon as any
31+ # reports the target SHA, so it doesn't matter which pod is "first".
3032
3133set -euo pipefail
3234
@@ -35,57 +37,89 @@ AGENT_NAME=${2:?agent name required}
3537WANT_SHA=${3:? want-sha required}
3638TIMEOUT=${4:- 180}
3739
38- # Auto-detect the authbridge container name. Sidecars are injected by
39- # the AuthBridge webhook at pod-admission, so the Deployment spec only
40- # lists the agent — we have to look at a running pod. Try the legacy
41- # name first (`envoy-proxy`) since most clusters today still run the
42- # older operator layout; fall back to the post-#411 combined name
43- # (`authbridge`).
44- POD_CONTAINERS=$( kubectl -n " $NAMESPACE " get pods \
45- -l app.kubernetes.io/name=" $AGENT_NAME " \
46- -o jsonpath=' {.items[0].spec.containers[*].name}' 2> /dev/null || true)
40+ # The operator-injected sidecar container is one of these names,
41+ # depending on operator version (see header comment).
4742AUTHBRIDGE_CANDIDATES=(authbridge-proxy authbridge envoy-proxy)
48- AUTHBRIDGE_CONTAINER=" "
49- for candidate in " ${AUTHBRIDGE_CANDIDATES[@]} " ; do
50- if echo " $POD_CONTAINERS " | tr ' ' ' \n' | grep -qx " $candidate " ; then
51- AUTHBRIDGE_CONTAINER=" $candidate "
52- break
53- fi
54- done
55- if [[ -z " $AUTHBRIDGE_CONTAINER " ]]; then
56- echo " ERROR: could not find an authbridge sidecar container in pods of $AGENT_NAME ." >&2
57- echo " Looked for: ${AUTHBRIDGE_CANDIDATES[*]} ." >&2
58- echo " Containers found: ${POD_CONTAINERS:- <none>} " >&2
59- exit 1
60- fi
61- echo " [*] Authbridge container detected: $AUTHBRIDGE_CONTAINER "
43+
44+ # Enumerate the agent's pods and, for each, the authbridge sidecar
45+ # container it carries (if any). Emits one "pod<TAB>container" line per
46+ # sidecar-bearing pod. We re-run this every poll iteration rather than
47+ # picking a single pod up front:
48+ #
49+ # During a rollout the pod list contains, in arbitrary order, the old
50+ # pod (agent-only if it predates AuthBridge, or a sidecar still serving
51+ # the stale config) alongside the new pod (mounting the patched
52+ # ConfigMap). The old `.items[0]` assumption picked whichever came first
53+ # — often the old/agent-only pod — and then either failed to find a
54+ # sidecar at all or waited forever on a pod whose config will never
55+ # advance (it's being terminated). Because success is defined purely by
56+ # "some sidecar reports the target SHA", we just probe every sidecar pod
57+ # each round; the converged pod wins regardless of list order, and
58+ # old/terminating pods that never match are harmless.
59+ list_sidecar_pods () {
60+ kubectl -n " $NAMESPACE " get pods \
61+ -l app.kubernetes.io/name=" $AGENT_NAME " \
62+ -o jsonpath=' {range .items[*]}{.metadata.name}{"|"}{range .spec.containers[*]}{.name}{","}{end}{"\n"}{end}' \
63+ 2> /dev/null | while IFS=' |' read -r pod containers; do
64+ [[ -z " $pod " ]] && continue
65+ for candidate in " ${AUTHBRIDGE_CANDIDATES[@]} " ; do
66+ if echo " $containers " | tr ' ,' ' \n' | grep -qx " $candidate " ; then
67+ printf ' %s\t%s\n' " $pod " " $candidate "
68+ break
69+ fi
70+ done
71+ done
72+ }
6273
6374DEADLINE=$(( $(date +% s) + TIMEOUT ))
6475
6576echo " [*] Waiting for authbridge to load the patched config (timeout ${TIMEOUT} s)"
6677echo " target SHA: $WANT_SHA "
6778
68- ACTIVE_SHA=" "
79+ SAW_SIDECAR=false # did we ever find a sidecar-bearing pod?
80+ LAST_POD=" " # for the failure diagnostics
81+ LAST_CONTAINER=" "
82+ LAST_SHA=" "
6983while [[ $( date +%s) -lt $DEADLINE ]]; do
70- ACTIVE_SHA=$( kubectl -n " $NAMESPACE " exec deploy/" $AGENT_NAME " -c " $AUTHBRIDGE_CONTAINER " -- \
71- wget -q -O - http://localhost:9093/reload/status 2> /dev/null | \
72- python3 -c ' import json, sys
84+ SIDECAR_PODS=$( list_sidecar_pods || true)
85+ if [[ -n " $SIDECAR_PODS " ]]; then
86+ SAW_SIDECAR=true
87+ while IFS=$' \t ' read -r pod container; do
88+ [[ -z " $pod " ]] && continue
89+ LAST_POD=" $pod " ; LAST_CONTAINER=" $container "
90+ active=$( kubectl -n " $NAMESPACE " exec " $pod " -c " $container " -- \
91+ wget -q -O - http://localhost:9093/reload/status 2> /dev/null | \
92+ python3 -c ' import json, sys
7393try:
7494 print(json.load(sys.stdin).get("active_config_sha256", ""))
7595except Exception:
7696 pass' 2> /dev/null || true)
77- if [[ " $ACTIVE_SHA " == " $WANT_SHA " ]]; then
78- echo " [*] Active config SHA matches — patch is live."
79- exit 0
97+ [[ -n " $active " ]] && LAST_SHA=" $active "
98+ if [[ " $active " == " $WANT_SHA " ]]; then
99+ echo " [*] Active config SHA matches on pod $pod ($container ) — patch is live."
100+ exit 0
101+ fi
102+ done <<< " $SIDECAR_PODS"
80103 fi
81104 sleep 3
82105done
83106
107+ if ! $SAW_SIDECAR ; then
108+ echo " ERROR: could not find an authbridge sidecar container in pods of $AGENT_NAME ." >&2
109+ echo " Looked for: ${AUTHBRIDGE_CANDIDATES[*]} ." >&2
110+ echo " Pods and their containers:" >&2
111+ kubectl -n " $NAMESPACE " get pods -l app.kubernetes.io/name=" $AGENT_NAME " \
112+ -o jsonpath=' {range .items[*]}{" "}{.metadata.name}{": "}{range .spec.containers[*]}{.name}{" "}{end}{"\n"}{end}' >&2 2> /dev/null || true
113+ exit 1
114+ fi
115+
84116echo " ERROR: authbridge active config did not match patched SHA within ${TIMEOUT} s." >&2
85117echo " want: $WANT_SHA " >&2
86- echo " last active: ${ACTIVE_SHA:- <none>} " >&2
87- echo " Last 20 lines of the $AUTHBRIDGE_CONTAINER container:" >&2
88- kubectl -n " $NAMESPACE " logs deploy/" $AGENT_NAME " -c " $AUTHBRIDGE_CONTAINER " --tail=20 >&2 || true
118+ echo " last active: ${LAST_SHA:- <none>} " >&2
119+ if [[ -n " $LAST_POD " ]]; then
120+ echo " Last 20 lines of the $LAST_CONTAINER container (pod $LAST_POD ):" >&2
121+ kubectl -n " $NAMESPACE " logs " $LAST_POD " -c " $LAST_CONTAINER " --tail=20 >&2 || true
122+ fi
89123echo >&2
90124echo " Likely causes:" >&2
91125echo " - ConfigMap parse error (look for 'reload failed' above)" >&2
0 commit comments