Newer
Older
openstack-caracal-dc-dc / tests / dc-plane-ipam / run-tests.sh
#!/usr/bin/env bash
# tests/dc-plane-ipam/run-tests.sh -- offline harness for scripts/dc-plane-ipam.sh.
#
# Stubs the `maas` client with a fakebin returning controlled JSON, and points the
# tool at fixture apex records. Mutates nothing outside $TMP; never touches live MAAS.
#
# THE POINT OF T6: everything this gate asserts is currently ABSENT live, so every
# real run FAILS. A gate only ever observed failing is as untrustworthy as one only
# ever observed passing -- T6 proves it CAN go green on a fully-provisioned fixture,
# so a future green is meaningful rather than merely unobserved.
# Exit: 0 all pass | 1 any case failed.  ASCII + LF.
set -uo pipefail
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO="$(cd "$HERE/../.." && pwd)"
TMP="$(mktemp -d)"; trap 'rm -rf "$TMP"' EXIT
PASS=0; FAIL=0

ok()  { PASS=$((PASS+1)); printf '  PASS  %s\n' "$1"; }
bad() { FAIL=$((FAIL+1)); printf '  FAIL  %s\n' "$1"; shift; [ $# -gt 0 ] && printf '%s\n' "$*" | sed 's/^/        /'; }

# ---- fixture apex record: the six dc0 plane /64s + the provider VIP /64 --------
mkapex() { # mkapex <file> [omit-role]
  python3 - "$1" "${2:-}" <<'PY'
import json, sys
out, omit = [], sys.argv[2]
planes = [("metal-admin","fd50:840e:74e2:220::/64"),("metal-internal","fd50:840e:74e2:221::/64"),
          ("data-tenant","fd50:840e:74e2:230::/64"),("storage","fd50:840e:74e2:240::/64"),
          ("replication","fd50:840e:74e2:250::/64"),("provider-public","2602:f3e2:f02:10::/64")]
for role, pre in planes:
    if role == omit: continue
    out.append({"prefix":pre,"scope":{"name":"vr1-dc0"},"role":{"slug":role},
                "description":"VR1 DC0 %s (ULA /64 active)" % role})
out.append({"prefix":"2602:f3e2:f02:11::/64","scope":{"name":"vr1-dc0"},
            "role":{"slug":"provider-public"},"description":"VR1 DC0 provider-public (GUA VIP /64)"})
out.append({"prefix":"fd50:840e:74e2:220::/60","scope":{"name":"vr1-dc0"},
            "role":{"slug":"metal-admin"},"description":"parent /60 -- must be IGNORED"})
json.dump({"ipam/prefixes": out}, open(sys.argv[1], "w"))
PY
}

# ---- fakebin maas -------------------------------------------------------------
# <dir> <v6:full|none> <bands:full|none|wrongtype> [subnets_rc] [ranges_rc]
mkmaas() {
  local d="$1" v6="$2" bands="$3" src="${4:-0}" rrc="${5:-0}"
  mkdir -p "$d/fakebin"
  cat > "$d/fakebin/maas" <<FB
#!/usr/bin/env bash
if [ "\$2" = "subnets" ]; then
  [ "$src" -ne 0 ] && exit $src
  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(
   ["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}})
print(json.dumps(s))
PY
  exit 0
fi
if [ "\$2" = "ipranges" ]; then
  [ "$rrc" -ne 0 ] && exit $rrc
  python3 - "$bands" <<'PY'
import json,sys
b=sys.argv[1]; r=[]
if b in ("full","wrongtype"):
    t = "dynamic" if b=="wrongtype" else "reserved"
    for third in (4,8,12,16,32,36):
        r.append({"type":t,"start_ip":"10.12.%d.4"%third,"end_ip":"10.12.%d.49"%third})
        r.append({"type":t,"start_ip":"10.12.%d.50"%third,"end_ip":"10.12.%d.99"%third})
print(json.dumps(r))
PY
  exit 0
fi
exit 1
FB
  chmod +x "$d/fakebin/maas"
}

run() { # run <want_rc> <regex> <label> <dir> [apex]
  local want="$1" re="$2" label="$3" d="$4"
  local apex="${5:-$d/apex.json}"   # split: bash expands ALL words of a `local`
                                     # before assigning any, so $d is unset above
  local out rc
  out="$(cd "$REPO" && PATH="$d/fakebin:$PATH" APEX_RECORD="$apex" \
         bash scripts/dc-plane-ipam.sh check vr1-dc0 2>&1)"; rc=$?
  if [ "$rc" = "$want" ] && grep -qE "$re" <<<"$out"; then ok "$label"
  else bad "$label (rc=$rc want=$want)" "$(printf '%s' "$out" | tail -4)"; fi
}

echo "== dc-plane-ipam =="

# ---- argument / selector guards ----
for a in "check dc0:2:RETIRED" "check dc1:2:RETIRED" "bogus vr1-dc0:2:usage" "check:2:usage"; do
  args="${a%%:*}"; rest="${a#*:}"; want="${rest%%:*}"; re="${rest##*:}"
  out="$(cd "$REPO" && bash scripts/dc-plane-ipam.sh $args 2>&1)"; rc=$?
  if [ "$rc" = "$want" ] && grep -qiE "$re" <<<"$out"; then ok "T-guard '$args' -> rc$want ($re)"
  else bad "T-guard '$args' (rc=$rc want=$want)" "$out"; fi
done

# ---- T1 the fully-absent baseline: the live state today ----
D="$TMP/absent"; mkdir -p "$D"; mkapex "$D/apex.json"; mkmaas "$D" none none
run 1 'v6 metal-admin .* ABSENT' "T1 no v6 and no bands -> FAIL (the measured live baseline)" "$D"

# ---- T2/T3 "could not look" must never read as clean ----
D="$TMP/subrc"; mkdir -p "$D"; mkapex "$D/apex.json"; mkmaas "$D" full full 4 0
run 2 'REFUSE' "T2 'maas subnets read' failing REFUSES (exit 2), never reports clean" "$D"
D="$TMP/rngrc"; mkdir -p "$D"; mkapex "$D/apex.json"; mkmaas "$D" full full 0 4
run 2 'REFUSE' "T3 'maas ipranges read' failing REFUSES (exit 2)" "$D"

# ---- T4 an unreadable apex REFUSES rather than asserting over zero planes ----
D="$TMP/noapex"; mkdir -p "$D"; mkmaas "$D" full full
run 2 'REFUSE' "T4 unreadable apex record REFUSES -- never 'no v6 planes, all clear'" "$D" "$D/nope.json"

# ---- T5 bands present but the WRONG TYPE: unrecognised state must not pass ----
D="$TMP/wrongtype"; mkdir -p "$D"; mkapex "$D/apex.json"; mkmaas "$D" full wrongtype
run 1 "type='dynamic'" "T5 band exists as 'dynamic' not 'reserved' -> FAIL, not a pass" "$D"

# ---- T6 THE CRITICAL ONE: a fully-provisioned fixture must PASS ----
D="$TMP/full"; mkdir -p "$D"; mkapex "$D/apex.json"; mkmaas "$D" full full
run 0 'PASS: dc-plane-ipam' "T6 fully-provisioned fixture PASSES -- the gate can go green" "$D"

# ---- T7 one missing v6 plane is caught (not masked by the other five) ----
D="$TMP/one"; mkdir -p "$D"; mkapex "$D/apex.json" storage; mkmaas "$D" full full
run 0 'PASS: dc-plane-ipam' "T7a apex omitting a plane does not invent a failure" "$D"
D="$TMP/one2"; mkdir -p "$D"; mkapex "$D/apex.json"; mkmaas "$D" none full
run 1 'v6 storage .* ABSENT' "T7b a v6 plane absent from MAAS is named individually" "$D"

# ---- T8 the parent /60 must be IGNORED, not treated as a plane ----
D="$TMP/p60"; mkdir -p "$D"; mkapex "$D/apex.json"; mkmaas "$D" full full
out="$(cd "$REPO" && PATH="$D/fakebin:$PATH" APEX_RECORD="$D/apex.json" \
       bash scripts/dc-plane-ipam.sh check vr1-dc0 2>&1)"
if ! grep -q '220::/60' <<<"$out"; then ok "T8 parent /60 blocks are ignored, not asserted as planes"
else bad "T8 a /60 parent block was treated as a plane" "$out"; fi

# ---- T9 the provider VIP /64 is reported but NOT asserted ----
if grep -q 'provider VIP block' <<<"$out" && ! grep -qE '\[FAIL\].*f02:11::/64' <<<"$out"; then
  ok "T9 provider VIP /64 is reported for visibility, deliberately not asserted"
else bad "T9 provider VIP /64 handling wrong" "$out"; fi

echo
echo "RESULT: PASS=$PASS FAIL=$FAIL"
[ "$FAIL" -eq 0 ] || exit 1