#!/usr/bin/env bash # T49: ServiceEntry.resolution DNS<->DNS_ROUND_ROBIN compiles to STRICT_DNS<->LOGICAL_DNS, # and during an in-flight DNS A-record flip, LOGICAL_DNS pins the already-established # connection (no drain) while STRICT_DNS would drain (asymmetric; only LOGICAL_DNS side # is exercised end-to-end here per the test spec's own scope note). set -euo pipefail NS=istio-vt-t49 SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" cleanup() { echo "[cleanup] deleting namespace $NS" kubectl delete namespace "$NS" --wait=false --ignore-not-found } trap cleanup EXIT echo "[1/9] create namespace" kubectl create namespace "$NS" kubectl label namespace "$NS" istio-injection=enabled echo "[2/9] apply manifest (first pass will fail on gslb-client placeholder nameserver IP - expected)" kubectl apply -f "$SCRIPT_DIR/manifest.yaml" || true echo "[3/9] resolve lab-dns-verify ClusterIP and patch it into manifest, then re-apply" LABDNS_IP=$(kubectl -n "$NS" get svc lab-dns-verify -o jsonpath='{.spec.clusterIP}') echo "LABDNS_IP=$LABDNS_IP" TMP_MANIFEST=$(mktemp) sed "s/REPLACE_WITH_LABDNS_CLUSTERIP/$LABDNS_IP/" "$SCRIPT_DIR/manifest.yaml" > "$TMP_MANIFEST" 2>/dev/null || cp "$SCRIPT_DIR/manifest.yaml" "$TMP_MANIFEST" # manifest.yaml as saved already has the literal ClusterIP baked in from the original run; # if re-running against a fresh cluster where the ClusterIP differs, patch it explicitly: kubectl -n "$NS" patch deploy gslb-client --type=json \ -p "[{\"op\":\"replace\",\"path\":\"/spec/template/spec/dnsConfig/nameservers/0\",\"value\":\"$LABDNS_IP\"}]" 2>/dev/null || true kubectl apply -f "$SCRIPT_DIR/manifest.yaml" echo "[4/9] wait for workloads" kubectl -n "$NS" rollout status deploy/lab-dns-verify deploy/backend-a deploy/backend-b deploy/gslb-client --timeout=120s kubectl -n "$NS" wait --for=condition=Ready pod/client --timeout=120s echo "[5/9] FIXTURE FIX: ServiceEntry declares port 80(http) but backend-a/backend-b Services" echo " only expose 8080 -> Envoy's real upstream connect to :80 black-holes (no kube-proxy" echo " NAT for that port). Add port 80 -> targetPort 8080 to both Services so the HTTP path is usable." kubectl -n "$NS" patch svc backend-a --type=json -p '[{"op":"replace","path":"/spec/ports","value":[{"name":"app","port":8080,"targetPort":8080},{"name":"http80","port":80,"targetPort":8080}]}]' kubectl -n "$NS" patch svc backend-b --type=json -p '[{"op":"replace","path":"/spec/ports","value":[{"name":"app","port":8080,"targetPort":8080},{"name":"http80","port":80,"targetPort":8080}]}]' echo "[6/9] seed DNS hosts entry -> backend-a, verify STRICT_DNS for resolution: DNS" BA_IP=$(kubectl -n "$NS" get svc backend-a -o jsonpath='{.spec.clusterIP}') BB_IP=$(kubectl -n "$NS" get svc backend-b -o jsonpath='{.spec.clusterIP}') echo "BA_IP=$BA_IP BB_IP=$BB_IP" kubectl -n "$NS" exec deploy/lab-dns-verify -c writer -- sh -c "echo $BA_IP gslb.verify.internal > /hosts/addn" kubectl apply -f - < /tmp/t49_fortio.log 2>&1 & FORTIO_PID=$! sleep 8 kubectl -n "$NS" exec deploy/gslb-client -c istio-proxy -- pilot-agent request GET stats \ | grep -E 'cluster.outbound.*gslb.verify.internal.*(upstream_cx_destroy|membership_change)' > /tmp/t49_before_logical.txt kubectl -n "$NS" exec deploy/lab-dns-verify -c writer -- sh -c "echo $BB_IP gslb.verify.internal > /hosts/addn" sleep 10 kubectl -n "$NS" exec deploy/gslb-client -c istio-proxy -- pilot-agent request GET stats \ | grep -E 'cluster.outbound.*gslb.verify.internal.*(upstream_cx_destroy|membership_change)' > /tmp/t49_after_logical.txt echo "diff (expect empty = no connection churn from the flip):" diff /tmp/t49_before_logical.txt /tmp/t49_after_logical.txt && echo "OK: no churn" wait "$FORTIO_PID" || true echo "fortio summary (expect single socket, 100% success, all requests against the ORIGINAL backend-a IP):" grep -E 'Sockets used|IP addresses distribution|Code 200' -A1 /tmp/t49_fortio.log || true echo "[9/9] new connection after flip (expect backend-b: LOGICAL_DNS resolves fresh per NEW connection;" echo " only the pre-existing session from step 8 stays pinned to backend-a)" kubectl -n "$NS" exec deploy/gslb-client -c curltools -- curl -s http://gslb.verify.internal/ echo "done"