deploy: keep manager health out of plan
This commit is contained in:
@@ -12234,7 +12234,33 @@ def validate_device_plane_manager_v3_active_baseline(descriptor):
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def validate_device_plane_manager_activation_predecessor(payload_dir):
|
def device_plane_manager_preserved_runtime_health_services(descriptor):
|
||||||
|
if descriptor.get("schemaVersion") == (
|
||||||
|
"nodedc.device-plane.device-manager-release.v3"
|
||||||
|
):
|
||||||
|
return (
|
||||||
|
"device-control-core",
|
||||||
|
"device-postgres",
|
||||||
|
)
|
||||||
|
return ("device-postgres",)
|
||||||
|
|
||||||
|
|
||||||
|
def validate_device_plane_manager_preserved_runtime_health(descriptor):
|
||||||
|
services = device_plane_manager_preserved_runtime_health_services(
|
||||||
|
descriptor
|
||||||
|
)
|
||||||
|
for service in services:
|
||||||
|
healthcheck_compose_service("device-plane", service)
|
||||||
|
return services
|
||||||
|
|
||||||
|
|
||||||
|
def validate_device_plane_manager_activation_predecessor(
|
||||||
|
payload_dir,
|
||||||
|
*,
|
||||||
|
preflight_phase,
|
||||||
|
):
|
||||||
|
if preflight_phase not in ("plan", "apply"):
|
||||||
|
die("Device Manager predecessor preflight phase is invalid")
|
||||||
descriptor = validate_device_plane_manager_release_payload(
|
descriptor = validate_device_plane_manager_release_payload(
|
||||||
payload_dir
|
payload_dir
|
||||||
)
|
)
|
||||||
@@ -12367,13 +12393,16 @@ def validate_device_plane_manager_activation_predecessor(payload_dir):
|
|||||||
)
|
)
|
||||||
if installed_descriptor != predecessor_descriptor:
|
if installed_descriptor != predecessor_descriptor:
|
||||||
die("Device Manager release predecessor is not current")
|
die("Device Manager release predecessor is not current")
|
||||||
for service in (
|
runtime = {
|
||||||
"device-control-core",
|
"accepted": True,
|
||||||
"device-manager",
|
"preservedRuntimeHealth": "deferred-to-apply",
|
||||||
"device-postgres",
|
}
|
||||||
):
|
if preflight_phase == "apply":
|
||||||
healthcheck_compose_service("device-plane", service)
|
runtime["preservedRuntimeHealth"] = (
|
||||||
runtime = {"accepted": True}
|
validate_device_plane_manager_preserved_runtime_health(
|
||||||
|
descriptor
|
||||||
|
)
|
||||||
|
)
|
||||||
v3_baseline = validate_device_plane_manager_v3_active_baseline(
|
v3_baseline = validate_device_plane_manager_v3_active_baseline(
|
||||||
descriptor
|
descriptor
|
||||||
)
|
)
|
||||||
@@ -19306,7 +19335,8 @@ def plan_artifact(artifact):
|
|||||||
):
|
):
|
||||||
device_plane_manager_activation_preflight = (
|
device_plane_manager_activation_preflight = (
|
||||||
validate_device_plane_manager_activation_predecessor(
|
validate_device_plane_manager_activation_predecessor(
|
||||||
payload_dir
|
payload_dir,
|
||||||
|
preflight_phase="plan",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
if is_device_plane_edge_core_channel_bootstrap_slice(
|
if is_device_plane_edge_core_channel_bootstrap_slice(
|
||||||
@@ -24614,7 +24644,8 @@ def apply_artifact(artifact):
|
|||||||
entries,
|
entries,
|
||||||
):
|
):
|
||||||
validate_device_plane_manager_activation_predecessor(
|
validate_device_plane_manager_activation_predecessor(
|
||||||
payload_dir
|
payload_dir,
|
||||||
|
preflight_phase="apply",
|
||||||
)
|
)
|
||||||
if is_device_plane_edge_core_channel_bootstrap_slice(
|
if is_device_plane_edge_core_channel_bootstrap_slice(
|
||||||
component,
|
component,
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
import importlib.machinery
|
import importlib.machinery
|
||||||
import importlib.util
|
import importlib.util
|
||||||
|
import inspect
|
||||||
import json
|
import json
|
||||||
import tempfile
|
import tempfile
|
||||||
import unittest
|
import unittest
|
||||||
@@ -27,6 +28,75 @@ RUNNER = load_runner()
|
|||||||
|
|
||||||
|
|
||||||
class DevicePlaneRegistryTest(unittest.TestCase):
|
class DevicePlaneRegistryTest(unittest.TestCase):
|
||||||
|
def test_manager_predecessor_health_is_phase_scoped(self):
|
||||||
|
with self.assertRaisesRegex(
|
||||||
|
RUNNER.DeployError,
|
||||||
|
"preflight phase is invalid",
|
||||||
|
):
|
||||||
|
RUNNER.validate_device_plane_manager_activation_predecessor(
|
||||||
|
Path("/not-used"),
|
||||||
|
preflight_phase="unknown",
|
||||||
|
)
|
||||||
|
|
||||||
|
plan_source = inspect.getsource(RUNNER.plan_artifact)
|
||||||
|
self.assertIn('preflight_phase="plan"', plan_source)
|
||||||
|
apply_source = inspect.getsource(RUNNER.apply_artifact)
|
||||||
|
self.assertIn('preflight_phase="apply"', apply_source)
|
||||||
|
|
||||||
|
def test_manager_v3_health_gate_checks_only_preserved_services(self):
|
||||||
|
descriptor = {
|
||||||
|
"schemaVersion": (
|
||||||
|
"nodedc.device-plane.device-manager-release.v3"
|
||||||
|
),
|
||||||
|
}
|
||||||
|
with mock.patch.object(
|
||||||
|
RUNNER,
|
||||||
|
"healthcheck_compose_service",
|
||||||
|
) as healthcheck:
|
||||||
|
services = (
|
||||||
|
RUNNER.validate_device_plane_manager_preserved_runtime_health(
|
||||||
|
descriptor
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
services,
|
||||||
|
("device-control-core", "device-postgres"),
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
healthcheck.call_args_list,
|
||||||
|
[
|
||||||
|
mock.call("device-plane", "device-control-core"),
|
||||||
|
mock.call("device-plane", "device-postgres"),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
self.assertNotIn(
|
||||||
|
mock.call("device-plane", "device-manager"),
|
||||||
|
healthcheck.call_args_list,
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_legacy_manager_health_gate_excludes_selected_services(self):
|
||||||
|
descriptor = {
|
||||||
|
"schemaVersion": (
|
||||||
|
"nodedc.device-plane.device-manager-release.v2"
|
||||||
|
),
|
||||||
|
}
|
||||||
|
with mock.patch.object(
|
||||||
|
RUNNER,
|
||||||
|
"healthcheck_compose_service",
|
||||||
|
) as healthcheck:
|
||||||
|
services = (
|
||||||
|
RUNNER.validate_device_plane_manager_preserved_runtime_health(
|
||||||
|
descriptor
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(services, ("device-postgres",))
|
||||||
|
healthcheck.assert_called_once_with(
|
||||||
|
"device-plane",
|
||||||
|
"device-postgres",
|
||||||
|
)
|
||||||
|
|
||||||
def test_registry_has_exact_roots_project_and_stateless_services(self):
|
def test_registry_has_exact_roots_project_and_stateless_services(self):
|
||||||
component = RUNNER.COMPONENTS["device-plane"]
|
component = RUNNER.COMPONENTS["device-plane"]
|
||||||
root = Path("/volume1/docker/nodedc-device-plane")
|
root = Path("/volume1/docker/nodedc-device-plane")
|
||||||
|
|||||||
Reference in New Issue
Block a user