fix(deploy): allow unhealthy selected Core recovery

This commit is contained in:
Codex
2026-08-22 01:27:00 +03:00
parent 26dbcfd262
commit c1c9818e30
2 changed files with 323 additions and 23 deletions
@@ -28,6 +28,197 @@ RUNNER = load_runner()
class DevicePlaneRegistryTest(unittest.TestCase):
def test_control_core_predecessor_health_is_phase_scoped(self):
with self.assertRaisesRegex(
RUNNER.DeployError,
"preflight phase is invalid",
):
RUNNER.validate_device_plane_control_core_release_predecessor(
Path("/not-used"),
preflight_phase="unknown",
)
plan_source = inspect.getsource(RUNNER.plan_artifact)
self.assertIn(
'validate_device_plane_control_core_release_predecessor(\n'
' payload_dir,\n'
' preflight_phase="plan",',
plan_source,
)
apply_source = inspect.getsource(RUNNER.apply_artifact)
self.assertIn(
'validate_device_plane_control_core_release_predecessor(\n'
' payload_dir,\n'
' preflight_phase="apply",',
apply_source,
)
def test_control_core_preflight_health_excludes_selected_target(self):
descriptor = {
"preservedServices": [
"device-manager",
"device-gateway",
"device-postgres",
"device-backhaul-target",
],
}
with mock.patch.object(
RUNNER,
"healthcheck_compose_service",
) as healthcheck:
services = (
RUNNER.validate_device_plane_control_core_preserved_runtime_health(
descriptor
)
)
self.assertEqual(
services,
(
"device-manager",
"device-gateway",
"device-postgres",
"device-backhaul-target",
),
)
self.assertEqual(
healthcheck.call_args_list,
[
mock.call("device-plane", "device-manager"),
mock.call("device-plane", "device-gateway"),
mock.call("device-plane", "device-postgres"),
mock.call("device-plane", "device-backhaul-target"),
],
)
self.assertNotIn(
mock.call("device-plane", "device-control-core"),
healthcheck.call_args_list,
)
def test_control_core_selected_predecessor_may_be_unhealthy(self):
inventory = {
"schemaVersion": "nodedc.device-plane.runtime-inventory.v1",
"composeProject": "nodedc-device-plane",
"services": [{
"service": "device-control-core",
"containerId": "a" * 64,
"imageId": "sha256:" + "b" * 64,
"status": "running",
"running": True,
"health": "unhealthy",
"restartCount": 4,
}],
}
with mock.patch.object(
RUNNER,
"device_plane_runtime_inventory",
return_value=inventory,
):
selected = (
RUNNER.validate_device_plane_control_core_selected_predecessor_runtime()
)
self.assertEqual(selected["health"], "unhealthy")
def test_control_core_rollback_accepts_restored_unhealthy_boundary(self):
service_names = (
"device-control-core",
"device-manager",
"device-gateway",
"device-postgres",
"device-backhaul-target",
)
inventory = {
"schemaVersion": "nodedc.device-plane.runtime-inventory.v1",
"composeProject": "nodedc-device-plane",
"services": [
{
"service": service,
"containerId": chr(97 + index) * 64,
"imageId": "sha256:" + str(index + 1) * 64,
"status": "running",
"running": True,
"health": "unhealthy" if index == 0 else "healthy",
"restartCount": index,
}
for index, service in enumerate(service_names)
],
}
restored_id = "f" * 64
restored = {
"Id": restored_id,
"State": {
"Status": "running",
"Running": True,
"Health": {"Status": "unhealthy"},
},
}
with (
mock.patch.object(
RUNNER,
"healthcheck_compose_service_with_grace",
) as preserved_health,
mock.patch.object(
RUNNER,
"compose_service_container_id",
return_value=restored_id,
),
mock.patch.object(
RUNNER,
"inspect_device_plane_container",
return_value=restored,
),
):
accepted = (
RUNNER.accept_device_plane_control_core_rollback_runtime(
inventory
)
)
self.assertEqual(accepted["health"], "unhealthy")
self.assertEqual(accepted["predecessorHealth"], "unhealthy")
self.assertEqual(
preserved_health.call_args_list,
[
mock.call("device-plane", "device-manager"),
mock.call("device-plane", "device-gateway"),
mock.call("device-plane", "device-postgres"),
mock.call("device-plane", "device-backhaul-target"),
],
)
def test_control_core_post_apply_health_includes_backhaul(self):
with (
mock.patch.object(
RUNNER,
"healthcheck_compose_service_with_grace",
) as healthcheck,
mock.patch.object(
RUNNER,
"component_healthchecks",
return_value=(),
),
mock.patch.object(
RUNNER,
"validate_device_manager_control_plane_runtime",
),
):
RUNNER.run_healthchecks(
"device-plane",
RUNNER.DEVICE_PLANE_CONTROL_CORE_RELEASE_V2_ENTRIES,
("device-control-core",),
)
self.assertEqual(
healthcheck.call_args_list,
[
mock.call("device-plane", "device-control-core"),
mock.call("device-plane", "device-manager"),
mock.call("device-plane", "device-gateway"),
mock.call("device-plane", "device-postgres"),
mock.call("device-plane", "device-backhaul-target"),
],
)
def test_manager_predecessor_health_is_phase_scoped(self):
with self.assertRaisesRegex(
RUNNER.DeployError,