Publish curated Unraid-AppOps-Gateway source from 1c6a58589e215177617aa20bfa9d877c67874950
This commit is contained in:
1 parent
fd4b962bdd
commit
84a7616341
3 files changed
+226
-4
No files matched your search
@@ -1,3 +1,3 @@
|
|||||||
# Public source export
|
# Public source export
|
||||||
|
|
||||||
This source snapshot was generated from the private canonical repository at revision `945a919d1a3bbd2bb5bd21eb221fc9b58d795d80`. It contains no private Git history or operational evidence. Changes are published from the canonical repository.
|
This source snapshot was generated from the private canonical repository at revision `1c6a58589e215177617aa20bfa9d877c67874950`. It contains no private Git history or operational evidence. Changes are published from the canonical repository.
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"schemaVersion": 1,
|
"schemaVersion": 1,
|
||||||
"sourceRevision": "945a919d1a3bbd2bb5bd21eb221fc9b58d795d80",
|
"sourceRevision": "1c6a58589e215177617aa20bfa9d877c67874950",
|
||||||
"files": [
|
"files": [
|
||||||
{
|
{
|
||||||
"path": ".dockerignore",
|
"path": ".dockerignore",
|
||||||
@@ -1604,8 +1604,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "backend/tests/test_runner_admission_controller.py",
|
"path": "backend/tests/test_runner_admission_controller.py",
|
||||||
"sha256": "c05470d633c3f8c745522019724de85f470df926235fe7155f9aa754ea3e4e23",
|
"sha256": "05c4397dc9c155b6f5ba0721f1db6c231dfe3ef7a20bc0cc1a82569f47a6e655",
|
||||||
"bytes": 69519
|
"bytes": 80570
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "backend/tests/test_runner_admission_policy.py",
|
"path": "backend/tests/test_runner_admission_policy.py",
|
||||||
|
|||||||
@@ -55,6 +55,228 @@ def _host_gate_sample(module, monkeypatch):
|
|||||||
return controller, now, host, capacity
|
return controller, now, host, capacity
|
||||||
|
|
||||||
|
|
||||||
|
def test_durable_saves_preserve_pending_and_profile_references(
|
||||||
|
controller_module, monkeypatch, tmp_path
|
||||||
|
):
|
||||||
|
module = controller_module
|
||||||
|
tmp_path.chmod(0o700)
|
||||||
|
monkeypatch.setattr(module, "STATE_ROOT", tmp_path)
|
||||||
|
monkeypatch.setattr(module, "STATE_FILE", tmp_path / "admission.json")
|
||||||
|
controller = module.RunnerAdmissionController()
|
||||||
|
state = module._initial_state()
|
||||||
|
entry = state["profiles"]["frontend"]
|
||||||
|
pending = {"profileId": "frontend", "stage": "reserved"}
|
||||||
|
state["pending"] = pending
|
||||||
|
|
||||||
|
controller._save_state(state)
|
||||||
|
pending["stage"] = "enable_requested"
|
||||||
|
controller._save_state(state)
|
||||||
|
entry["enabledByController"] = True
|
||||||
|
entry["observed"] = True
|
||||||
|
state["pending"] = None
|
||||||
|
controller._save_state(state)
|
||||||
|
|
||||||
|
saved = controller._read_state()
|
||||||
|
assert saved["revision"] == state["revision"] == 3
|
||||||
|
assert saved["profiles"]["frontend"]["enabledByController"] is True
|
||||||
|
assert saved["profiles"]["frontend"]["observed"] is True
|
||||||
|
assert saved["pending"] is None
|
||||||
|
|
||||||
|
|
||||||
|
def test_durable_save_preserves_drain_entry_updates(
|
||||||
|
controller_module, monkeypatch, tmp_path
|
||||||
|
):
|
||||||
|
module = controller_module
|
||||||
|
tmp_path.chmod(0o700)
|
||||||
|
monkeypatch.setattr(module, "STATE_ROOT", tmp_path)
|
||||||
|
monkeypatch.setattr(module, "STATE_FILE", tmp_path / "admission.json")
|
||||||
|
controller = module.RunnerAdmissionController()
|
||||||
|
state = module._initial_state()
|
||||||
|
entry = state["profiles"]["frontend"]
|
||||||
|
entry.update(enabledByController=True, drainOwned=True)
|
||||||
|
controller._save_state(state)
|
||||||
|
entry.update(enabledByController=False, drainOwned=False, idleSince=None)
|
||||||
|
controller._save_state(state)
|
||||||
|
|
||||||
|
saved = controller._read_state()
|
||||||
|
assert saved["profiles"]["frontend"]["enabledByController"] is False
|
||||||
|
assert saved["profiles"]["frontend"]["drainOwned"] is False
|
||||||
|
|
||||||
|
|
||||||
|
def _operator_handover_fixture(module, monkeypatch):
|
||||||
|
controller, state, observation, _, _ = _lease_fixture(module, enabled=("frontend",))
|
||||||
|
entry = state["profiles"]["frontend"]
|
||||||
|
entry.update(enabledByController=False, operatorEnabled=True)
|
||||||
|
state["bootstrapReceiptSha256"] = "a" * 64
|
||||||
|
observation.update(specialization="active", resourceProof={"ready": True},
|
||||||
|
taskImagesVerified=True, guardState="clear")
|
||||||
|
observation["containers"][module.RUNNER_PROFILES["frontend"].container_name].update(
|
||||||
|
pid=1234, startedAt=module._utc_iso())
|
||||||
|
monkeypatch.setattr(module.os, "geteuid", lambda: 0, raising=False)
|
||||||
|
artifact = {"sourceRevision": "b" * 40, "artifactSha256": "c" * 64}
|
||||||
|
monkeypatch.setitem(sys.modules, "status_server", SimpleNamespace(_require_controller_release=lambda: artifact))
|
||||||
|
monkeypatch.setattr(controller, "_process_lock", lambda: nullcontext())
|
||||||
|
monkeypatch.setattr(controller, "_read_state", lambda: state)
|
||||||
|
monkeypatch.setattr(controller, "_observe", lambda: observation)
|
||||||
|
written = []
|
||||||
|
|
||||||
|
def persist(value, *, expected_revision):
|
||||||
|
assert value["revision"] == expected_revision
|
||||||
|
saved = json.loads(json.dumps(value))
|
||||||
|
saved["revision"] += 1
|
||||||
|
written.append(saved)
|
||||||
|
return saved
|
||||||
|
|
||||||
|
monkeypatch.setattr(controller, "_write_state", persist)
|
||||||
|
monkeypatch.setattr(controller, "_set_disabled", lambda *_args: pytest.fail("handover must not patch Gitea"))
|
||||||
|
monkeypatch.setattr(controller, "_docker_run", lambda *_args, **_kw: pytest.fail("handover must not mutate Docker"))
|
||||||
|
return controller, state, observation, written, artifact
|
||||||
|
|
||||||
|
|
||||||
|
def test_explicit_operator_handover_is_bound_and_only_transfers_metadata(controller_module, monkeypatch):
|
||||||
|
controller, state, _, written, _ = _operator_handover_fixture(controller_module, monkeypatch)
|
||||||
|
preflight = controller.operator_lease_handover("frontend")
|
||||||
|
assert preflight["executed"] is False
|
||||||
|
assert written == []
|
||||||
|
assert state["profiles"]["frontend"]["operatorEnabled"] is True
|
||||||
|
result = controller.operator_lease_handover("frontend", expected_preflight=preflight["preflightSha256"])
|
||||||
|
assert result["status"] == "handed_over" and result["executed"] is True
|
||||||
|
assert len(written) == 1
|
||||||
|
entry = written[0]["profiles"]["frontend"]
|
||||||
|
assert entry["operatorEnabled"] is False and entry["enabledByController"] is True
|
||||||
|
assert entry["lastOperatorHandover"]["containerId"] == preflight["containerId"]
|
||||||
|
assert all(written[0]["profiles"][p] == state["profiles"][p] for p in controller_module.PROFILE_IDS if p != "frontend")
|
||||||
|
with pytest.raises(controller_module.RunnerAdmissionError, match="preconditions_failed"):
|
||||||
|
controller.operator_lease_handover("frontend", expected_preflight=preflight["preflightSha256"])
|
||||||
|
assert len(written) == 1
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("change", ["busy", "active", "disabled", "operator_disabled", "controller_owned",
|
||||||
|
"pending", "inactive", "bootstrap", "identity", "stopped", "pid", "started", "resource", "images", "guard"])
|
||||||
|
def test_operator_handover_refuses_unsafe_or_unowned_observations(controller_module, monkeypatch, change):
|
||||||
|
controller, state, observation, written, _ = _operator_handover_fixture(controller_module, monkeypatch)
|
||||||
|
entry = state["profiles"]["frontend"]
|
||||||
|
row = observation["runnerRows"][controller_module.RUNNER_PROFILES["frontend"].container_name]
|
||||||
|
container = observation["containers"][controller_module.RUNNER_PROFILES["frontend"].container_name]
|
||||||
|
if change == "busy":
|
||||||
|
row["busy"] = True
|
||||||
|
elif change == "active":
|
||||||
|
observation["activeJobs"] = {999: [{"id": "foreign-job"}]}
|
||||||
|
elif change == "disabled":
|
||||||
|
row["disabled"] = True
|
||||||
|
elif change == "operator_disabled":
|
||||||
|
entry["operatorDisabled"] = True
|
||||||
|
elif change == "controller_owned":
|
||||||
|
entry["enabledByController"] = True
|
||||||
|
elif change == "pending":
|
||||||
|
state["pending"] = {"profileId": "build"}
|
||||||
|
elif change == "inactive":
|
||||||
|
observation["specialization"] = "legacy"
|
||||||
|
elif change == "bootstrap":
|
||||||
|
state["bootstrapReceiptSha256"] = None
|
||||||
|
elif change == "identity":
|
||||||
|
row["id"] += 1
|
||||||
|
elif change == "stopped":
|
||||||
|
container["running"] = False
|
||||||
|
elif change == "pid":
|
||||||
|
container["pid"] = 0
|
||||||
|
elif change == "started":
|
||||||
|
container["startedAt"] = None
|
||||||
|
elif change == "resource":
|
||||||
|
observation["resourceProof"] = None
|
||||||
|
elif change == "images":
|
||||||
|
observation["taskImagesVerified"] = False
|
||||||
|
else:
|
||||||
|
observation["guardState"] = "paused"
|
||||||
|
before = copy.deepcopy(state)
|
||||||
|
with pytest.raises(controller_module.RunnerAdmissionError, match="preconditions_failed"):
|
||||||
|
controller.operator_lease_handover("frontend")
|
||||||
|
assert state == before and written == []
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("change", ["state", "container", "artifact", "labels", "restart"])
|
||||||
|
def test_operator_handover_rechecks_current_fingerprint(controller_module, monkeypatch, change):
|
||||||
|
controller, state, observation, written, artifact = _operator_handover_fixture(controller_module, monkeypatch)
|
||||||
|
preflight = controller.operator_lease_handover("frontend")
|
||||||
|
name = controller_module.RUNNER_PROFILES["frontend"].container_name
|
||||||
|
if change == "state":
|
||||||
|
state["revision"] += 1
|
||||||
|
elif change == "container":
|
||||||
|
observation["containers"][name]["id"] = "f" * 64
|
||||||
|
elif change == "artifact":
|
||||||
|
artifact["sourceRevision"] = "d" * 40
|
||||||
|
elif change == "restart":
|
||||||
|
observation["containers"][name]["pid"] += 1
|
||||||
|
else:
|
||||||
|
observation["runnerRows"][name]["labels"].add("self-hosted")
|
||||||
|
with pytest.raises(controller_module.RunnerAdmissionError, match="preflight_changed"):
|
||||||
|
controller.operator_lease_handover("frontend", expected_preflight=preflight["preflightSha256"])
|
||||||
|
assert written == []
|
||||||
|
|
||||||
|
|
||||||
|
def test_operator_handover_requires_root_before_reading_controller_or_credentials(controller_module, monkeypatch):
|
||||||
|
controller = controller_module.RunnerAdmissionController()
|
||||||
|
monkeypatch.setattr(controller_module.os, "geteuid", lambda: 10001, raising=False)
|
||||||
|
monkeypatch.setattr(controller, "_read_state", lambda: pytest.fail("non-root must not read private state"))
|
||||||
|
with pytest.raises(controller_module.RunnerAdmissionError, match="requires_root"):
|
||||||
|
controller.operator_lease_handover("frontend")
|
||||||
|
|
||||||
|
|
||||||
|
def test_operator_handover_cas_conflict_does_not_claim_publication(controller_module, monkeypatch):
|
||||||
|
controller, _, _, written, _ = _operator_handover_fixture(controller_module, monkeypatch)
|
||||||
|
preflight = controller.operator_lease_handover("frontend")
|
||||||
|
|
||||||
|
def conflict(*_args, **_kwargs):
|
||||||
|
raise controller_module.RunnerAdmissionError("runner_admission_state_conflict")
|
||||||
|
|
||||||
|
monkeypatch.setattr(controller, "_write_state", conflict)
|
||||||
|
with pytest.raises(controller_module.RunnerAdmissionError, match="state_conflict"):
|
||||||
|
controller.operator_lease_handover("frontend", expected_preflight=preflight["preflightSha256"])
|
||||||
|
assert written == []
|
||||||
|
|
||||||
|
|
||||||
|
def test_operator_handover_reports_uncertain_durable_write(controller_module, monkeypatch):
|
||||||
|
controller, _, _, _, _ = _operator_handover_fixture(controller_module, monkeypatch)
|
||||||
|
preflight = controller.operator_lease_handover("frontend")
|
||||||
|
|
||||||
|
def uncertain(*_args, **_kwargs):
|
||||||
|
raise controller_module.RunnerAdmissionError("runner_admission_state_write_failed")
|
||||||
|
|
||||||
|
monkeypatch.setattr(controller, "_write_state", uncertain)
|
||||||
|
with pytest.raises(controller_module.RunnerAdmissionError, match="handover_outcome_unknown"):
|
||||||
|
controller.operator_lease_handover("frontend", expected_preflight=preflight["preflightSha256"])
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("args", [["--operator-handover", "frontend"],
|
||||||
|
["--preflight-operator-handover", "frontend", "--confirm", "RETURN_CI_RUNNER_TO_MANAGED_ADMISSION"]])
|
||||||
|
def test_handover_cli_refuses_missing_or_inappropriate_mutation_arguments(controller_module, args):
|
||||||
|
with pytest.raises(SystemExit) as exc:
|
||||||
|
controller_module.main(args)
|
||||||
|
assert exc.value.code == 2
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("error", [RuntimeError("fake-secret-never-output"), "uncertain"])
|
||||||
|
def test_handover_cli_redacts_errors_and_does_not_misreport_unknown_writes(controller_module, monkeypatch, capsys, error):
|
||||||
|
controller = controller_module.RunnerAdmissionController()
|
||||||
|
|
||||||
|
def refused(*_args, **_kwargs):
|
||||||
|
if error == "uncertain":
|
||||||
|
raise controller_module.RunnerAdmissionError("runner_admission_handover_outcome_unknown")
|
||||||
|
raise error
|
||||||
|
|
||||||
|
monkeypatch.setattr(controller, "operator_lease_handover", refused)
|
||||||
|
monkeypatch.setattr(controller_module, "RunnerAdmissionController", lambda: controller)
|
||||||
|
assert controller_module.main(["--preflight-operator-handover", "frontend"]) == 1
|
||||||
|
raw = capsys.readouterr().out
|
||||||
|
assert "fake-secret-never-output" not in raw
|
||||||
|
result = json.loads(raw)
|
||||||
|
if error == "uncertain":
|
||||||
|
assert result["status"] == "outcome_unknown" and result["executed"] is None
|
||||||
|
assert result["noMutation"] is False
|
||||||
|
else:
|
||||||
|
assert result["status"] == "blocked" and result["executed"] is False
|
||||||
|
|
||||||
|
|
||||||
def test_safe_live_metric_fluctuations_do_not_restart_stable_headroom(controller_module, monkeypatch):
|
def test_safe_live_metric_fluctuations_do_not_restart_stable_headroom(controller_module, monkeypatch):
|
||||||
module = controller_module
|
module = controller_module
|
||||||
controller, now, host, _ = _host_gate_sample(module, monkeypatch)
|
controller, now, host, _ = _host_gate_sample(module, monkeypatch)
|
||||||
|
|||||||
Reference in new issue
Block a user