fix(device-plane): activate manager from v2 reconciliation
This commit is contained in:
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"schemaVersion": "nodedc.device-plane.device-manager-control-plane.v3",
|
||||||
|
"action": "activate",
|
||||||
|
"predecessor": {
|
||||||
|
"patchId": "device-manager-control-plane-v2-reconciliation-20260811-004",
|
||||||
|
"artifactSha256": "09600bfd99717314b43936e17ffaaf6b6fca1f2fd008beddddc68480cdf3d284",
|
||||||
|
"mode": "failed-v2-control-plane-baseline-adoption"
|
||||||
|
},
|
||||||
|
"service": "device-manager",
|
||||||
|
"publicIngress": "reverse-proxy-only",
|
||||||
|
"deviceCoreManagementApi": "file-token-authenticated",
|
||||||
|
"launcherTrust": "file-token-scoped-to-device-core-handoff",
|
||||||
|
"healthGate": "bounded-container-grace+core-contract",
|
||||||
|
"commandTransport": "disabled",
|
||||||
|
"gelios": "untouched",
|
||||||
|
"rollback": "restore-v2-reconciled-baseline"
|
||||||
|
}
|
||||||
@@ -12,7 +12,7 @@ const devicePlaneRoot = resolve(platformRoot, "device-plane");
|
|||||||
const designRoot = resolve(process.env.NODEDC_DEVICE_MANAGER_SOURCE_ROOT || resolve(platformRoot, "../NODEDC_DESIGN_GUIDELINE"));
|
const designRoot = resolve(process.env.NODEDC_DEVICE_MANAGER_SOURCE_ROOT || resolve(platformRoot, "../NODEDC_DESIGN_GUIDELINE"));
|
||||||
const managerRoot = resolve(designRoot, "apps/device-manager");
|
const managerRoot = resolve(designRoot, "apps/device-manager");
|
||||||
const artifactDir = resolve(process.env.NODEDC_DEPLOY_ARTIFACT_DIR || resolve(scriptDir, "../deploy-artifacts"));
|
const artifactDir = resolve(process.env.NODEDC_DEPLOY_ARTIFACT_DIR || resolve(scriptDir, "../deploy-artifacts"));
|
||||||
const [patchId = "device-manager-control-plane-20260811-003", ...extra] = process.argv.slice(2);
|
const [patchId = "device-manager-control-plane-v3-20260811-005", ...extra] = process.argv.slice(2);
|
||||||
if (extra.length || !/^[A-Za-z0-9._-]{1,96}$/.test(patchId)) throw new Error("usage: build-device-manager-control-plane-artifact.mjs [patch-id]");
|
if (extra.length || !/^[A-Za-z0-9._-]{1,96}$/.test(patchId)) throw new Error("usage: build-device-manager-control-plane-artifact.mjs [patch-id]");
|
||||||
|
|
||||||
const entries = [
|
const entries = [
|
||||||
@@ -26,7 +26,7 @@ const entries = [
|
|||||||
"services/device-gateway/package.json",
|
"services/device-gateway/package.json",
|
||||||
"services/device-edge-relay/package.json",
|
"services/device-edge-relay/package.json",
|
||||||
"services/device-manager",
|
"services/device-manager",
|
||||||
"deployment/device-manager-control-plane-v2.json",
|
"deployment/device-manager-control-plane-v3.json",
|
||||||
];
|
];
|
||||||
const stage = await mkdtemp(join(tmpdir(), "nodedc-device-manager-control-plane-"));
|
const stage = await mkdtemp(join(tmpdir(), "nodedc-device-manager-control-plane-"));
|
||||||
const payload = join(stage, "payload");
|
const payload = join(stage, "payload");
|
||||||
@@ -89,15 +89,16 @@ try {
|
|||||||
if (compose.includes(forbidden)) throw new Error(`device_manager_compose_boundary_violation:${forbidden}`);
|
if (compose.includes(forbidden)) throw new Error(`device_manager_compose_boundary_violation:${forbidden}`);
|
||||||
}
|
}
|
||||||
const descriptor = JSON.parse(await readFile(
|
const descriptor = JSON.parse(await readFile(
|
||||||
join(payload, "deployment/device-manager-control-plane-v2.json"),
|
join(payload, "deployment/device-manager-control-plane-v3.json"),
|
||||||
"utf8",
|
"utf8",
|
||||||
));
|
));
|
||||||
if (
|
if (
|
||||||
descriptor.schemaVersion !== "nodedc.device-plane.device-manager-control-plane.v2"
|
descriptor.schemaVersion !== "nodedc.device-plane.device-manager-control-plane.v3"
|
||||||
|| descriptor.predecessor?.patchId !== "device-manager-control-plane-reconciliation-20260811-002"
|
|| descriptor.predecessor?.patchId !== "device-manager-control-plane-v2-reconciliation-20260811-004"
|
||||||
|| descriptor.predecessor?.artifactSha256 !== "dd86dd58e4f649db0981db5089e003caf3961356179f2abb514662351487e1e6"
|
|| descriptor.predecessor?.artifactSha256 !== "09600bfd99717314b43936e17ffaaf6b6fca1f2fd008beddddc68480cdf3d284"
|
||||||
|
|| descriptor.predecessor?.mode !== "failed-v2-control-plane-baseline-adoption"
|
||||||
|| descriptor.healthGate !== "bounded-container-grace+core-contract"
|
|| descriptor.healthGate !== "bounded-container-grace+core-contract"
|
||||||
|| descriptor.rollback !== "restore-reconciled-baseline"
|
|| descriptor.rollback !== "restore-v2-reconciled-baseline"
|
||||||
) throw new Error("device_manager_activation_successor_contract_mismatch");
|
) throw new Error("device_manager_activation_successor_contract_mismatch");
|
||||||
await writeFile(join(stage, "manifest.env"), `id=${patchId}\ncomponent=device-plane\ntype=app-overlay\n`, "utf8");
|
await writeFile(join(stage, "manifest.env"), `id=${patchId}\ncomponent=device-plane\ntype=app-overlay\n`, "utf8");
|
||||||
await writeFile(join(stage, "files.txt"), `${entries.join("\n")}\n`, "utf8");
|
await writeFile(join(stage, "files.txt"), `${entries.join("\n")}\n`, "utf8");
|
||||||
|
|||||||
@@ -213,9 +213,12 @@ DEVICE_PLANE_FOUNDATION_ENTRIES = (
|
|||||||
DEVICE_PLANE_MANAGER_FAILED_CONTROL_PLANE_REL = (
|
DEVICE_PLANE_MANAGER_FAILED_CONTROL_PLANE_REL = (
|
||||||
"deployment/device-manager-control-plane-v1.json"
|
"deployment/device-manager-control-plane-v1.json"
|
||||||
)
|
)
|
||||||
DEVICE_PLANE_MANAGER_CONTROL_PLANE_REL = (
|
DEVICE_PLANE_MANAGER_V2_CONTROL_PLANE_REL = (
|
||||||
"deployment/device-manager-control-plane-v2.json"
|
"deployment/device-manager-control-plane-v2.json"
|
||||||
)
|
)
|
||||||
|
DEVICE_PLANE_MANAGER_CONTROL_PLANE_REL = (
|
||||||
|
"deployment/device-manager-control-plane-v3.json"
|
||||||
|
)
|
||||||
DEVICE_PLANE_MANAGER_COMPOSE_REL = "docker-compose.device-manager.yml"
|
DEVICE_PLANE_MANAGER_COMPOSE_REL = "docker-compose.device-manager.yml"
|
||||||
DEVICE_PLANE_MANAGER_COMPOSE_SHA256 = (
|
DEVICE_PLANE_MANAGER_COMPOSE_SHA256 = (
|
||||||
"4954120aaddc999798b64c304d8cf692b79714feb727d873117bd1f3434e865e"
|
"4954120aaddc999798b64c304d8cf692b79714feb727d873117bd1f3434e865e"
|
||||||
@@ -233,6 +236,19 @@ DEVICE_PLANE_MANAGER_FAILED_CONTROL_PLANE_ENTRIES = (
|
|||||||
"services/device-manager",
|
"services/device-manager",
|
||||||
DEVICE_PLANE_MANAGER_FAILED_CONTROL_PLANE_REL,
|
DEVICE_PLANE_MANAGER_FAILED_CONTROL_PLANE_REL,
|
||||||
)
|
)
|
||||||
|
DEVICE_PLANE_MANAGER_V2_CONTROL_PLANE_ENTRIES = (
|
||||||
|
".dockerignore",
|
||||||
|
"package.json",
|
||||||
|
"package-lock.json",
|
||||||
|
DEVICE_PLANE_MANAGER_COMPOSE_REL,
|
||||||
|
"packages/device-protocol-contract",
|
||||||
|
"packages/arusnavi-b2-adapter",
|
||||||
|
"services/device-control-core",
|
||||||
|
"services/device-gateway/package.json",
|
||||||
|
"services/device-edge-relay/package.json",
|
||||||
|
"services/device-manager",
|
||||||
|
DEVICE_PLANE_MANAGER_V2_CONTROL_PLANE_REL,
|
||||||
|
)
|
||||||
DEVICE_PLANE_MANAGER_CONTROL_PLANE_ENTRIES = (
|
DEVICE_PLANE_MANAGER_CONTROL_PLANE_ENTRIES = (
|
||||||
".dockerignore",
|
".dockerignore",
|
||||||
"package.json",
|
"package.json",
|
||||||
@@ -334,6 +350,17 @@ DEVICE_PLANE_MANAGER_V2_FAILED_ARTIFACT_SHA256 = (
|
|||||||
DEVICE_PLANE_MANAGER_V2_RECONCILIATION_PATCH_ID = (
|
DEVICE_PLANE_MANAGER_V2_RECONCILIATION_PATCH_ID = (
|
||||||
"device-manager-control-plane-v2-reconciliation-20260811-004"
|
"device-manager-control-plane-v2-reconciliation-20260811-004"
|
||||||
)
|
)
|
||||||
|
DEVICE_PLANE_MANAGER_V2_RECONCILIATION_ARTIFACT = (
|
||||||
|
"nodedc-device-plane-device-manager-control-plane-v2-reconciliation-"
|
||||||
|
"20260811-004.tgz"
|
||||||
|
)
|
||||||
|
DEVICE_PLANE_MANAGER_V2_RECONCILIATION_ARTIFACT_SHA256 = (
|
||||||
|
"09600bfd99717314b43936e17ffaaf6b6fca1f2fd008beddddc68480cdf3d284"
|
||||||
|
)
|
||||||
|
DEVICE_PLANE_MANAGER_V2_RECONCILIATION_APPLY_BACKUP_ID = (
|
||||||
|
"device-plane-device-manager-control-plane-v2-reconciliation-"
|
||||||
|
"20260811-004-20260811-100533"
|
||||||
|
)
|
||||||
DEVICE_PLANE_MANAGER_V2_RECONCILIATION_BACKUP_ID = (
|
DEVICE_PLANE_MANAGER_V2_RECONCILIATION_BACKUP_ID = (
|
||||||
"device-plane-device-manager-control-plane-20260811-003-"
|
"device-plane-device-manager-control-plane-20260811-003-"
|
||||||
"20260811-012505"
|
"20260811-012505"
|
||||||
@@ -371,7 +398,7 @@ DEVICE_PLANE_MANAGER_V2_RECONCILIATION_EXISTING = (
|
|||||||
DEVICE_PLANE_MANAGER_V2_RECONCILIATION_MISSING = (
|
DEVICE_PLANE_MANAGER_V2_RECONCILIATION_MISSING = (
|
||||||
DEVICE_PLANE_MANAGER_COMPOSE_REL,
|
DEVICE_PLANE_MANAGER_COMPOSE_REL,
|
||||||
"services/device-manager",
|
"services/device-manager",
|
||||||
DEVICE_PLANE_MANAGER_CONTROL_PLANE_REL,
|
DEVICE_PLANE_MANAGER_V2_CONTROL_PLANE_REL,
|
||||||
)
|
)
|
||||||
DEVICE_PLANE_FOUNDATION_RECOVERY_REL = (
|
DEVICE_PLANE_FOUNDATION_RECOVERY_REL = (
|
||||||
"deployment/device-plane-foundation-recovery-v1.json"
|
"deployment/device-plane-foundation-recovery-v1.json"
|
||||||
@@ -8677,10 +8704,15 @@ def reject_terminal_device_plane_manager_artifact(
|
|||||||
if (
|
if (
|
||||||
manifest.get("id") == DEVICE_PLANE_MANAGER_V2_FAILED_PATCH_ID
|
manifest.get("id") == DEVICE_PLANE_MANAGER_V2_FAILED_PATCH_ID
|
||||||
or sha256 == DEVICE_PLANE_MANAGER_V2_FAILED_ARTIFACT_SHA256
|
or sha256 == DEVICE_PLANE_MANAGER_V2_FAILED_ARTIFACT_SHA256
|
||||||
|
or is_device_plane_manager_v2_control_plane_slice(
|
||||||
|
manifest.get("component"),
|
||||||
|
entries,
|
||||||
|
)
|
||||||
):
|
):
|
||||||
die(
|
die(
|
||||||
"Device Manager control-plane 003 is terminal failed; "
|
"Device Manager control-plane 003 is terminal failed; "
|
||||||
"use the exact v2 reconciliation successor"
|
"use the exact v2 reconciliation successor followed by the "
|
||||||
|
"exact v3 activation successor"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -8745,6 +8777,14 @@ def is_device_plane_manager_control_plane_slice(component, entries):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def is_device_plane_manager_v2_control_plane_slice(component, entries):
|
||||||
|
return (
|
||||||
|
component == "device-plane"
|
||||||
|
and entries is not None
|
||||||
|
and tuple(entries) == DEVICE_PLANE_MANAGER_V2_CONTROL_PLANE_ENTRIES
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def is_device_plane_manager_failed_control_plane_slice(component, entries):
|
def is_device_plane_manager_failed_control_plane_slice(component, entries):
|
||||||
return (
|
return (
|
||||||
component == "device-plane"
|
component == "device-plane"
|
||||||
@@ -8796,15 +8836,15 @@ def expected_platform_device_manager_public_route_descriptor():
|
|||||||
def expected_device_plane_manager_control_plane_descriptor():
|
def expected_device_plane_manager_control_plane_descriptor():
|
||||||
return {
|
return {
|
||||||
"schemaVersion": (
|
"schemaVersion": (
|
||||||
"nodedc.device-plane.device-manager-control-plane.v2"
|
"nodedc.device-plane.device-manager-control-plane.v3"
|
||||||
),
|
),
|
||||||
"action": "activate",
|
"action": "activate",
|
||||||
"predecessor": {
|
"predecessor": {
|
||||||
"patchId": DEVICE_PLANE_MANAGER_RECONCILIATION_PATCH_ID,
|
"patchId": DEVICE_PLANE_MANAGER_V2_RECONCILIATION_PATCH_ID,
|
||||||
"artifactSha256": (
|
"artifactSha256": (
|
||||||
DEVICE_PLANE_MANAGER_RECONCILIATION_ARTIFACT_SHA256
|
DEVICE_PLANE_MANAGER_V2_RECONCILIATION_ARTIFACT_SHA256
|
||||||
),
|
),
|
||||||
"mode": "failed-control-plane-baseline-adoption",
|
"mode": "failed-v2-control-plane-baseline-adoption",
|
||||||
},
|
},
|
||||||
"service": "device-manager",
|
"service": "device-manager",
|
||||||
"publicIngress": "reverse-proxy-only",
|
"publicIngress": "reverse-proxy-only",
|
||||||
@@ -8813,7 +8853,7 @@ def expected_device_plane_manager_control_plane_descriptor():
|
|||||||
"healthGate": "bounded-container-grace+core-contract",
|
"healthGate": "bounded-container-grace+core-contract",
|
||||||
"commandTransport": "disabled",
|
"commandTransport": "disabled",
|
||||||
"gelios": "untouched",
|
"gelios": "untouched",
|
||||||
"rollback": "restore-reconciled-baseline",
|
"rollback": "restore-v2-reconciled-baseline",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -10455,7 +10495,7 @@ def validate_device_plane_manager_activation_predecessor(payload_dir):
|
|||||||
payload_dir
|
payload_dir
|
||||||
)
|
)
|
||||||
reconciliation_artifact = (
|
reconciliation_artifact = (
|
||||||
APPLIED_DIR / DEVICE_PLANE_MANAGER_RECONCILIATION_ARTIFACT
|
APPLIED_DIR / DEVICE_PLANE_MANAGER_V2_RECONCILIATION_ARTIFACT
|
||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
artifact_stat = reconciliation_artifact.lstat()
|
artifact_stat = reconciliation_artifact.lstat()
|
||||||
@@ -10465,7 +10505,7 @@ def validate_device_plane_manager_activation_predecessor(payload_dir):
|
|||||||
stat.S_ISLNK(artifact_stat.st_mode)
|
stat.S_ISLNK(artifact_stat.st_mode)
|
||||||
or not stat.S_ISREG(artifact_stat.st_mode)
|
or not stat.S_ISREG(artifact_stat.st_mode)
|
||||||
or sha256_file(reconciliation_artifact)
|
or sha256_file(reconciliation_artifact)
|
||||||
!= DEVICE_PLANE_MANAGER_RECONCILIATION_ARTIFACT_SHA256
|
!= DEVICE_PLANE_MANAGER_V2_RECONCILIATION_ARTIFACT_SHA256
|
||||||
):
|
):
|
||||||
die("Device Manager reconciliation applied artifact mismatch")
|
die("Device Manager reconciliation applied artifact mismatch")
|
||||||
|
|
||||||
@@ -10473,30 +10513,30 @@ def validate_device_plane_manager_activation_predecessor(payload_dir):
|
|||||||
value
|
value
|
||||||
for value in load_state(STATE_FILE)
|
for value in load_state(STATE_FILE)
|
||||||
if value.get("id")
|
if value.get("id")
|
||||||
== DEVICE_PLANE_MANAGER_RECONCILIATION_PATCH_ID
|
== DEVICE_PLANE_MANAGER_V2_RECONCILIATION_PATCH_ID
|
||||||
]
|
]
|
||||||
if len(records) != 1:
|
if len(records) != 1:
|
||||||
die("Device Manager reconciliation applied journal count mismatch")
|
die("Device Manager reconciliation applied journal count mismatch")
|
||||||
record = records[0]
|
record = records[0]
|
||||||
if (
|
if (
|
||||||
record.get("artifact")
|
record.get("artifact")
|
||||||
!= DEVICE_PLANE_MANAGER_RECONCILIATION_ARTIFACT
|
!= DEVICE_PLANE_MANAGER_V2_RECONCILIATION_ARTIFACT
|
||||||
or record.get("backup_id")
|
or record.get("backup_id")
|
||||||
!= DEVICE_PLANE_MANAGER_RECONCILIATION_APPLY_BACKUP_ID
|
!= DEVICE_PLANE_MANAGER_V2_RECONCILIATION_APPLY_BACKUP_ID
|
||||||
or record.get("component") != "device-plane"
|
or record.get("component") != "device-plane"
|
||||||
or record.get("sha256")
|
or record.get("sha256")
|
||||||
!= DEVICE_PLANE_MANAGER_RECONCILIATION_ARTIFACT_SHA256
|
!= DEVICE_PLANE_MANAGER_V2_RECONCILIATION_ARTIFACT_SHA256
|
||||||
or record.get("status") != "ok"
|
or record.get("status") != "ok"
|
||||||
):
|
):
|
||||||
die("Device Manager reconciliation applied journal mismatch")
|
die("Device Manager reconciliation applied journal mismatch")
|
||||||
|
|
||||||
backup_dir = validate_device_plane_manager_reconciliation_backup()
|
backup_dir = validate_device_plane_manager_v2_reconciliation_backup()
|
||||||
runtime = validate_device_plane_manager_reconciled_baseline(
|
runtime = validate_device_plane_manager_v2_reconciled_baseline(
|
||||||
backup_dir,
|
backup_dir,
|
||||||
marker_installed=True,
|
marker_installed=True,
|
||||||
)
|
)
|
||||||
return {
|
return {
|
||||||
"mode": "reconciled-manager-forward-activation",
|
"mode": "reconciled-v2-manager-forward-activation",
|
||||||
"descriptor": descriptor,
|
"descriptor": descriptor,
|
||||||
"reconciliationArtifact": reconciliation_artifact,
|
"reconciliationArtifact": reconciliation_artifact,
|
||||||
"reconciliationRecord": record,
|
"reconciliationRecord": record,
|
||||||
@@ -10538,7 +10578,7 @@ def validate_device_plane_manager_v2_reconciliation_backup():
|
|||||||
backup_dir / "missing-files.txt"
|
backup_dir / "missing-files.txt"
|
||||||
))
|
))
|
||||||
validate_backup_partition(
|
validate_backup_partition(
|
||||||
DEVICE_PLANE_MANAGER_CONTROL_PLANE_ENTRIES,
|
DEVICE_PLANE_MANAGER_V2_CONTROL_PLANE_ENTRIES,
|
||||||
existing,
|
existing,
|
||||||
missing,
|
missing,
|
||||||
"Device Manager v2 reconciliation",
|
"Device Manager v2 reconciliation",
|
||||||
@@ -10584,7 +10624,10 @@ def validate_device_plane_manager_v2_reconciled_baseline(
|
|||||||
)
|
)
|
||||||
if live_source != backup_source:
|
if live_source != backup_source:
|
||||||
die("Device Manager v2 rollback source does not match backup")
|
die("Device Manager v2 rollback source does not match backup")
|
||||||
for rel in DEVICE_PLANE_MANAGER_V2_RECONCILIATION_MISSING:
|
for rel in (
|
||||||
|
*DEVICE_PLANE_MANAGER_V2_RECONCILIATION_MISSING,
|
||||||
|
DEVICE_PLANE_MANAGER_CONTROL_PLANE_REL,
|
||||||
|
):
|
||||||
path = root / rel
|
path = root / rel
|
||||||
if path.exists() or path.is_symlink():
|
if path.exists() or path.is_symlink():
|
||||||
die(
|
die(
|
||||||
@@ -10667,7 +10710,7 @@ def validate_device_plane_manager_v2_reconciliation_evidence(payload_dir):
|
|||||||
or failed_manifest.get("component") != "device-plane"
|
or failed_manifest.get("component") != "device-plane"
|
||||||
or failed_manifest.get("type") != "app-overlay"
|
or failed_manifest.get("type") != "app-overlay"
|
||||||
or tuple(failed_entries)
|
or tuple(failed_entries)
|
||||||
!= DEVICE_PLANE_MANAGER_CONTROL_PLANE_ENTRIES
|
!= DEVICE_PLANE_MANAGER_V2_CONTROL_PLANE_ENTRIES
|
||||||
):
|
):
|
||||||
die("Device Manager v2 failed artifact contract mismatch")
|
die("Device Manager v2 failed artifact contract mismatch")
|
||||||
|
|
||||||
@@ -18119,11 +18162,11 @@ def plan_artifact(artifact):
|
|||||||
)
|
)
|
||||||
print(
|
print(
|
||||||
"device_plane_predecessor_patch="
|
"device_plane_predecessor_patch="
|
||||||
f"{DEVICE_PLANE_MANAGER_RECONCILIATION_PATCH_ID}"
|
f"{DEVICE_PLANE_MANAGER_V2_RECONCILIATION_PATCH_ID}"
|
||||||
)
|
)
|
||||||
print(
|
print(
|
||||||
"device_plane_predecessor_artifact_sha256="
|
"device_plane_predecessor_artifact_sha256="
|
||||||
f"{DEVICE_PLANE_MANAGER_RECONCILIATION_ARTIFACT_SHA256}"
|
f"{DEVICE_PLANE_MANAGER_V2_RECONCILIATION_ARTIFACT_SHA256}"
|
||||||
)
|
)
|
||||||
print(
|
print(
|
||||||
"device_plane_runtime_mutation="
|
"device_plane_runtime_mutation="
|
||||||
|
|||||||
@@ -239,21 +239,28 @@ class DeviceManagerControlPlaneArtifactsTest(unittest.TestCase):
|
|||||||
)
|
)
|
||||||
runtime_acceptance.assert_called_once_with()
|
runtime_acceptance.assert_called_once_with()
|
||||||
|
|
||||||
def test_v2_activation_requires_exact_applied_reconciliation(self):
|
def test_v3_activation_requires_exact_applied_v2_reconciliation(self):
|
||||||
with tempfile.TemporaryDirectory(
|
with tempfile.TemporaryDirectory(
|
||||||
prefix="nodedc-device-manager-v2-predecessor-",
|
prefix="nodedc-device-manager-v3-predecessor-",
|
||||||
) as directory:
|
) as directory:
|
||||||
root = Path(directory)
|
root = Path(directory)
|
||||||
artifact = root / RUNNER.DEVICE_PLANE_MANAGER_RECONCILIATION_ARTIFACT
|
artifact = (
|
||||||
|
root
|
||||||
|
/ RUNNER.DEVICE_PLANE_MANAGER_V2_RECONCILIATION_ARTIFACT
|
||||||
|
)
|
||||||
artifact_bytes = b"reviewed-reconciliation-artifact"
|
artifact_bytes = b"reviewed-reconciliation-artifact"
|
||||||
artifact.write_bytes(artifact_bytes)
|
artifact.write_bytes(artifact_bytes)
|
||||||
state_file = root / "applied.jsonl"
|
state_file = root / "applied.jsonl"
|
||||||
state_file.write_text(
|
state_file.write_text(
|
||||||
json.dumps({
|
json.dumps({
|
||||||
"id": RUNNER.DEVICE_PLANE_MANAGER_RECONCILIATION_PATCH_ID,
|
"id": (
|
||||||
"artifact": RUNNER.DEVICE_PLANE_MANAGER_RECONCILIATION_ARTIFACT,
|
RUNNER.DEVICE_PLANE_MANAGER_V2_RECONCILIATION_PATCH_ID
|
||||||
|
),
|
||||||
|
"artifact": (
|
||||||
|
RUNNER.DEVICE_PLANE_MANAGER_V2_RECONCILIATION_ARTIFACT
|
||||||
|
),
|
||||||
"backup_id": (
|
"backup_id": (
|
||||||
RUNNER.DEVICE_PLANE_MANAGER_RECONCILIATION_APPLY_BACKUP_ID
|
RUNNER.DEVICE_PLANE_MANAGER_V2_RECONCILIATION_APPLY_BACKUP_ID
|
||||||
),
|
),
|
||||||
"component": "device-plane",
|
"component": "device-plane",
|
||||||
"sha256": hashlib.sha256(artifact_bytes).hexdigest(),
|
"sha256": hashlib.sha256(artifact_bytes).hexdigest(),
|
||||||
@@ -267,7 +274,7 @@ class DeviceManagerControlPlaneArtifactsTest(unittest.TestCase):
|
|||||||
mock.patch.object(RUNNER, "STATE_FILE", state_file),
|
mock.patch.object(RUNNER, "STATE_FILE", state_file),
|
||||||
mock.patch.object(
|
mock.patch.object(
|
||||||
RUNNER,
|
RUNNER,
|
||||||
"DEVICE_PLANE_MANAGER_RECONCILIATION_ARTIFACT_SHA256",
|
"DEVICE_PLANE_MANAGER_V2_RECONCILIATION_ARTIFACT_SHA256",
|
||||||
hashlib.sha256(artifact_bytes).hexdigest(),
|
hashlib.sha256(artifact_bytes).hexdigest(),
|
||||||
),
|
),
|
||||||
mock.patch.object(
|
mock.patch.object(
|
||||||
@@ -279,12 +286,12 @@ class DeviceManagerControlPlaneArtifactsTest(unittest.TestCase):
|
|||||||
) as payload,
|
) as payload,
|
||||||
mock.patch.object(
|
mock.patch.object(
|
||||||
RUNNER,
|
RUNNER,
|
||||||
"validate_device_plane_manager_reconciliation_backup",
|
"validate_device_plane_manager_v2_reconciliation_backup",
|
||||||
return_value=backup,
|
return_value=backup,
|
||||||
),
|
),
|
||||||
mock.patch.object(
|
mock.patch.object(
|
||||||
RUNNER,
|
RUNNER,
|
||||||
"validate_device_plane_manager_reconciled_baseline",
|
"validate_device_plane_manager_v2_reconciled_baseline",
|
||||||
return_value={"accepted": True},
|
return_value={"accepted": True},
|
||||||
) as baseline,
|
) as baseline,
|
||||||
):
|
):
|
||||||
@@ -296,7 +303,7 @@ class DeviceManagerControlPlaneArtifactsTest(unittest.TestCase):
|
|||||||
|
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
result["mode"],
|
result["mode"],
|
||||||
"reconciled-manager-forward-activation",
|
"reconciled-v2-manager-forward-activation",
|
||||||
)
|
)
|
||||||
payload.assert_called_once_with(root / "payload")
|
payload.assert_called_once_with(root / "payload")
|
||||||
baseline.assert_called_once_with(backup, marker_installed=True)
|
baseline.assert_called_once_with(backup, marker_installed=True)
|
||||||
|
|||||||
@@ -221,6 +221,15 @@ class DeviceManagerControlPlaneReconciliationArtifactTest(unittest.TestCase):
|
|||||||
{"id": "different"},
|
{"id": "different"},
|
||||||
RUNNER.DEVICE_PLANE_MANAGER_V2_FAILED_ARTIFACT_SHA256,
|
RUNNER.DEVICE_PLANE_MANAGER_V2_FAILED_ARTIFACT_SHA256,
|
||||||
)
|
)
|
||||||
|
with self.assertRaisesRegex(
|
||||||
|
RUNNER.DeployError,
|
||||||
|
"exact v2 reconciliation successor",
|
||||||
|
):
|
||||||
|
RUNNER.reject_terminal_device_plane_manager_artifact(
|
||||||
|
{"id": "different", "component": "device-plane"},
|
||||||
|
"1" * 64,
|
||||||
|
RUNNER.DEVICE_PLANE_MANAGER_V2_CONTROL_PLANE_ENTRIES,
|
||||||
|
)
|
||||||
|
|
||||||
def test_health_grace_waits_through_unhealthy_and_exited(self):
|
def test_health_grace_waits_through_unhealthy_and_exited(self):
|
||||||
results = [
|
results = [
|
||||||
|
|||||||
Reference in New Issue
Block a user