Receives the State Hub rows of the 2026-10-21 node allocation review (CUST-WP-0071 T03/T04, RESOURCE-WP-0008). The release preflight now derives the API surge from the values the release deploys instead of the stale 100m STATE-WP-0091 constant, and reports the steady remainder after rollout. Ordering: apply after rail-knative reductions, before forge/telemetry increases. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: opus Assistant-Process: 8340@bnt-lap001 Assistant-Session: 2e192b3d-b3e8-4403-94d4-d55a2c8b476c
140 lines
5.1 KiB
Python
140 lines
5.1 KiB
Python
from __future__ import annotations
|
|
|
|
import json
|
|
from pathlib import Path
|
|
|
|
from scripts.release_headroom_preflight import (
|
|
DEFAULT_API_SURGE_CPU_M,
|
|
DEFAULT_API_SURGE_MEMORY,
|
|
DEFAULT_MCP_SURGE_CPU_M,
|
|
DEFAULT_MIGRATE_CPU_M,
|
|
DEFAULT_VALUES_FILES,
|
|
evaluate,
|
|
load_values,
|
|
main,
|
|
pod_effective_requests,
|
|
release_from_values,
|
|
)
|
|
|
|
FIXTURES = Path(__file__).parent / "fixtures" / "release_headroom"
|
|
|
|
|
|
HISTORICAL_100M = {"api_surge_cpu_m": 100}
|
|
|
|
|
|
def _load(name: str) -> dict:
|
|
return json.loads((FIXTURES / name).read_text())
|
|
|
|
|
|
def test_revision_61_65m_refuses_api_surge() -> None:
|
|
report = evaluate(_load("rev61-65m.json"))
|
|
assert report["ok"] is False
|
|
assert report["remaining_cpu_m"] == 65
|
|
assert any("65m remaining" in r or "needs 100m" in r for r in report["reasons"])
|
|
assert "not a kube-scheduler guarantee" in " ".join(report["notes"]).lower() or any(
|
|
"guarantee" in n.lower() for n in report["notes"]
|
|
)
|
|
|
|
|
|
def test_revision_63_105m_is_narrowly_sufficient() -> None:
|
|
report = evaluate(_load("rev63-105m.json"), HISTORICAL_100M)
|
|
assert report["ok"] is True
|
|
assert report["remaining_cpu_m"] == 105
|
|
assert report["reasons"] == []
|
|
assert any("105m" in n or "Not factory" in n for n in report["notes"])
|
|
|
|
|
|
def test_unrelated_pending_demand_refuses_105m() -> None:
|
|
report = evaluate(_load("rev63-105m-concurrent-pending.json"), HISTORICAL_100M)
|
|
assert report["ok"] is False
|
|
assert any("unrelated pending" in r for r in report["reasons"])
|
|
|
|
|
|
def test_stale_observation_refuses() -> None:
|
|
observation = _load("rev63-105m.json")
|
|
observation["freshness_seconds"] = 3600
|
|
report = evaluate(observation, HISTORICAL_100M)
|
|
assert report["ok"] is False
|
|
assert any("old" in r for r in report["reasons"])
|
|
|
|
|
|
def test_non_atomic_refuses() -> None:
|
|
report = evaluate(_load("rev63-105m.json"), {**HISTORICAL_100M, "atomic": False})
|
|
assert report["ok"] is False
|
|
assert any("atomic" in r for r in report["reasons"])
|
|
|
|
|
|
def test_init_overhead_uses_max_not_sum() -> None:
|
|
pod = {
|
|
"spec": {
|
|
"initContainers": [{"resources": {"requests": {"cpu": "80m", "memory": "64Mi"}}}],
|
|
"containers": [{"resources": {"requests": {"cpu": "100m", "memory": "512Mi"}}}],
|
|
}
|
|
}
|
|
cpu, _mem = pod_effective_requests(pod)
|
|
assert cpu == 100
|
|
|
|
|
|
def test_cli_fixture_exit_codes() -> None:
|
|
historical = str(FIXTURES / "historical-100m-release.json")
|
|
assert main(["--fixture", str(FIXTURES / "rev63-105m.json"), "--release", historical]) == 0
|
|
assert main(["--fixture", str(FIXTURES / "rev61-65m.json"), "--release", historical]) == 1
|
|
# Default surge now derives from the shipped values (390m): 105m refuses.
|
|
assert main(["--fixture", str(FIXTURES / "rev63-105m.json")]) == 1
|
|
|
|
|
|
# STATE-WP-0099: the surge follows the API request the release deploys.
|
|
|
|
|
|
def test_shipped_values_drive_surge_and_match_fallbacks() -> None:
|
|
release = release_from_values(load_values(DEFAULT_VALUES_FILES))
|
|
assert release["api_surge_cpu_m"] == 390
|
|
assert release["api_surge_cpu_m"] == DEFAULT_API_SURGE_CPU_M
|
|
assert release["api_surge_memory_bytes"] == DEFAULT_API_SURGE_MEMORY
|
|
assert release["mcp_surge_cpu_m"] == DEFAULT_MCP_SURGE_CPU_M
|
|
assert release["migrate_cpu_m"] == DEFAULT_MIGRATE_CPU_M
|
|
|
|
|
|
def test_values_override_order_and_disabled_sections() -> None:
|
|
chart = {"resources": {"requests": {"cpu": "250m", "memory": "512Mi"}},
|
|
"mcp": {"enabled": False, "resources": {"requests": {"cpu": "50m"}}},
|
|
"migrations": {"enabled": True, "resources": {"requests": {"cpu": "50m"}}}}
|
|
override = {"resources": {"requests": {"cpu": "0.39"}}, "migrations": {"enabled": False}}
|
|
from scripts.release_headroom_preflight import _deep_merge
|
|
|
|
release = release_from_values(_deep_merge(chart, override))
|
|
assert release["api_surge_cpu_m"] == 390
|
|
assert release["api_surge_memory_bytes"] == 512 * 1024**2
|
|
assert release["mcp_surge_cpu_m"] == 0
|
|
assert release["migrate_cpu_m"] == 0
|
|
|
|
|
|
def test_today_395m_fits_390m_surge_narrowly() -> None:
|
|
report = evaluate(_load("2026-10-21-395m-live250.json"))
|
|
assert report["ok"] is True
|
|
assert report["api_surge_cpu_m"] == 390
|
|
assert report["remaining_after_rollout_cpu_m"] == 255
|
|
notes = " ".join(report["notes"])
|
|
assert "250m -> 390m" in notes
|
|
assert "only 5m above" in notes
|
|
assert "next release will be refused" in notes
|
|
|
|
|
|
def test_after_knative_reduction_fits_with_margin() -> None:
|
|
report = evaluate(_load("2026-10-21-555m-after-knative.json"))
|
|
assert report["ok"] is True
|
|
assert report["remaining_after_rollout_cpu_m"] == 415
|
|
assert "next release will be refused" not in " ".join(report["notes"])
|
|
|
|
|
|
def test_forge_increase_before_state_hub_refuses() -> None:
|
|
report = evaluate(_load("2026-10-21-320m-forge-first.json"))
|
|
assert report["ok"] is False
|
|
assert any("needs 390m" in r for r in report["reasons"])
|
|
|
|
|
|
def test_after_full_wave1_routine_release_refuses() -> None:
|
|
report = evaluate(_load("2026-10-21-110m-after-wave1.json"))
|
|
assert report["ok"] is False
|
|
assert report["remaining_cpu_m"] == 110
|
|
assert any("needs 390m" in r for r in report["reasons"])
|