diff --git a/scripts/dc-plane-ipam.sh b/scripts/dc-plane-ipam.sh index 305fb9a..1f28dd3 100755 --- a/scripts/dc-plane-ipam.sh +++ b/scripts/dc-plane-ipam.sh @@ -9,12 +9,17 @@ # with no artifact, which is the class the 2026-07-27 audit found twice. # # ACTIONS -# check READ-ONLY. Compare live MAAS against the ruled expected state -# and report per-plane. Exit 0 only if every assertion passes. +# check READ-ONLY. Compare live MAAS against the ruled expected +# state. Exit 0 only if every assertion passes. +# carve-v6 Create the six v6 plane subnets, each on the SAME MAAS vlan +# as its v4 twin (R2 dual-stack). DRY unless --commit. +# reserve Create the D-134 reserved bands + the FIP pool (R4). +# DRY unless --commit. # -# The MUTATING actions (v6 carve, band reservation) are NOT in this file yet -- -# hard rule 3, verify before mutate: the read-only gate ships and runs first, so -# the mutation is planned against a MEASURED baseline rather than an assumed one. +# The read-only gate was shipped and RUN FIRST, deliberately (hard rule 3), so the +# mutations are planned against a MEASURED baseline rather than an assumed one. +# Both mutating actions are DRY BY DEFAULT, IDEMPOTENT, and READ BACK every write +# -- this repo has been bitten by a script whose `apply` always silently dry-ran. # # EXPECTED STATE IS DERIVED, NEVER HARDCODED (hard rule 3): # v4 plane CIDRs <- scripts/lib-net.sh via lib_net_select_dc (site-keyed) @@ -34,7 +39,11 @@ HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" REPO="$(cd "$HERE/.." && pwd)" -ACTION="${1:-}"; SITE="${2:-}"; shift 2 2>/dev/null || true +ACTION="${1:-}"; SITE="${2:-}" +# Shift ONLY what actually exists: `shift 2` with a single argument fails, leaving +# "$@" holding the action itself, which the option loop below then rejected as an +# unknown option instead of printing usage. Found by the harness, not by review. +if [ "$#" -gt 2 ]; then shift 2; else set --; fi COMMIT=0 for a in "$@"; do case "$a" in --commit) COMMIT=1 ;; *) echo "FAIL: unknown option '$a'" >&2; exit 2 ;; esac; done MAAS_PROFILE="${MAAS_PROFILE:-admin}" diff --git a/tests/dc-plane-ipam/run-tests.sh b/tests/dc-plane-ipam/run-tests.sh index 2e0c95e..29d96bf 100755 --- a/tests/dc-plane-ipam/run-tests.sh +++ b/tests/dc-plane-ipam/run-tests.sh @@ -50,12 +50,12 @@ python3 - "$v6" <<'PY' import json,sys v6=sys.argv[1] -s=[{"cidr":c,"id":i,"vlan":{"fabric":"f-%d"%i}} for i,c in enumerate( +s=[{"cidr":c,"id":i,"vlan":{"id":5000+i,"fabric":"f-%d"%i}} for i,c in enumerate( ["10.12.4.0/22","10.12.8.0/22","10.12.12.0/22","10.12.16.0/22","10.12.32.0/22","10.12.36.0/22"])] if v6=="full": for i,c in enumerate(["fd50:840e:74e2:220::/64","fd50:840e:74e2:221::/64","fd50:840e:74e2:230::/64", "fd50:840e:74e2:240::/64","fd50:840e:74e2:250::/64","2602:f3e2:f02:10::/64"]): - s.append({"cidr":c,"id":100+i,"vlan":{"fabric":"f-%d"%i}}) + s.append({"cidr":c,"id":100+i,"vlan":{"id":5000+i,"fabric":"f-%d"%i}}) print(json.dumps(s)) PY exit 0 @@ -140,6 +140,66 @@ ok "T9 provider VIP /64 is reported for visibility, deliberately not asserted" else bad "T9 provider VIP /64 handling wrong" "$out"; fi +# ============ carve-v6 / reserve (dry by default) ============================ +runact() { # runact