NODEDC_PLATFORM/infra/deploy-runner/test_engine_composite_provi...

158 lines
6.7 KiB
Python

import hashlib
import importlib.machinery
import importlib.util
import json
import os
from pathlib import Path
import subprocess
import tarfile
import tempfile
import unittest
from unittest import mock
SCRIPT_DIR = Path(__file__).resolve().parent
RUNNER_PATH = SCRIPT_DIR / "nodedc-deploy"
BUILDER_PATH = SCRIPT_DIR / "build-engine-composite-provider-v4-artifact.mjs"
ENGINE_ROOT = SCRIPT_DIR.parent.parent.parent / "NODEDC_ENGINE_INFRA"
PATCH_ID = "engine-composite-provider-v4-20991231-999"
def load_runner():
loader = importlib.machinery.SourceFileLoader(
"nodedc_engine_composite_provider_v4",
str(RUNNER_PATH),
)
spec = importlib.util.spec_from_loader(loader.name, loader)
module = importlib.util.module_from_spec(spec)
loader.exec_module(module)
return module
RUNNER = load_runner()
class EngineCompositeProviderV4Test(unittest.TestCase):
def test_predecessor_map_matches_the_applied_release_order(self):
self.assertEqual(
RUNNER.ENGINE_COMPOSITE_PROVIDER_V4_PREDECESSOR_SHA256,
{
"nodedc-source/server/assets/provider-packages/v1/catalog.json":
"992159fc457ec76ce1f45aad337604c8a72b29252d44fbccda515f0fd6ea6428",
"nodedc-source/server/dataProductPublishGrant/providerCatalog.js":
"901b8fad80018ce177b34ced804b39cb140a47e831414057f484296b373c651d",
"nodedc-source/server/dataProductPublishGrant/service.js":
"6a417b25b080c05b40c771df4e2dca163491af2c9083ff73dc7e54ad3b360241",
"nodedc-source/server/dataProductPublishGrant/store.js":
"a92303b2732e21f68c1ac732fa26e4983cbadf3515741cee983b916a283d754c",
},
)
def build(self, artifact_dir):
environment = os.environ.copy()
environment["NODEDC_ENGINE_SOURCE_ROOT"] = str(ENGINE_ROOT)
environment["NODEDC_DEPLOY_ARTIFACT_DIR"] = str(artifact_dir)
completed = subprocess.run(
["node", str(BUILDER_PATH), PATCH_ID],
check=True,
capture_output=True,
text=True,
env=environment,
)
return json.loads(completed.stdout)
def test_builder_is_deterministic_and_emits_exact_backend_only_slice(self):
current_sha256 = {
relative_path: hashlib.sha256((ENGINE_ROOT / relative_path).read_bytes()).hexdigest()
for relative_path in RUNNER.ENGINE_COMPOSITE_PROVIDER_V4_ARTIFACT_ENTRIES
}
if current_sha256 != RUNNER.ENGINE_COMPOSITE_PROVIDER_V4_TARGET_SHA256:
self.skipTest("historical v4 builder source has advanced to its exact successor")
with tempfile.TemporaryDirectory(prefix="nodedc-engine-composite-v4-") as directory:
root = Path(directory)
first = self.build(root / "first")
second = self.build(root / "second")
first_artifact = Path(first["artifact"])
second_artifact = Path(second["artifact"])
self.assertEqual(first_artifact.read_bytes(), second_artifact.read_bytes())
self.assertEqual(
first["sha256"],
hashlib.sha256(first_artifact.read_bytes()).hexdigest(),
)
self.assertEqual(first["services"], ["nodedc-backend"])
self.assertEqual(first["credentialValues"], "preserved")
self.assertEqual(
tuple(first["entries"]),
RUNNER.ENGINE_COMPOSITE_PROVIDER_V4_ARTIFACT_ENTRIES,
)
extract = root / "extract"
with tarfile.open(first_artifact, "r:gz") as archive:
archive.extractall(extract, filter="data")
entries = tuple(
(extract / "files.txt").read_text(encoding="utf-8").splitlines()
)
payload = extract / "payload"
self.assertTrue(RUNNER.is_engine_composite_provider_v4_slice("engine", entries))
self.assertEqual(RUNNER.component_services("engine", entries), ("nodedc-backend",))
self.assertEqual(
RUNNER.component_healthchecks("engine", entries, ("nodedc-backend",)),
("http://127.0.0.1:3001/health",),
)
RUNNER.validate_engine_composite_provider_v4_slice(payload, entries)
for relative_path, expected in RUNNER.ENGINE_COMPOSITE_PROVIDER_V4_TARGET_SHA256.items():
self.assertEqual(
hashlib.sha256((payload / relative_path).read_bytes()).hexdigest(),
expected,
)
def test_preflight_requires_every_exact_predecessor_and_immutable_backend(self):
with tempfile.TemporaryDirectory(prefix="nodedc-engine-composite-v4-preflight-") as directory:
root = Path(directory)
for relative_path in RUNNER.ENGINE_COMPOSITE_PROVIDER_V4_ARTIFACT_ENTRIES:
path = root / relative_path
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text("predecessor\n", encoding="utf-8")
def exact_sha(path):
relative_path = Path(path).relative_to(root).as_posix()
return RUNNER.ENGINE_COMPOSITE_PROVIDER_V4_PREDECESSOR_SHA256[relative_path]
with (
mock.patch.object(RUNNER, "component_root", return_value=root),
mock.patch.object(RUNNER, "sha256_file", side_effect=exact_sha),
mock.patch.object(
RUNNER,
"preflight_engine_credential_backend_runtime",
return_value={"mode": "verified-derived-retry"},
),
):
result = RUNNER.preflight_engine_composite_provider_v4_predecessor()
self.assertEqual(result["mode"], "exact-composite-provider-v3-to-v4")
self.assertEqual(
result["predecessor_sha256"],
RUNNER.ENGINE_COMPOSITE_PROVIDER_V4_PREDECESSOR_SHA256,
)
self.assertEqual(
result["target_sha256"],
RUNNER.ENGINE_COMPOSITE_PROVIDER_V4_TARGET_SHA256,
)
drift_path = root / RUNNER.ENGINE_COMPOSITE_PROVIDER_V4_ARTIFACT_ENTRIES[1]
def drift_sha(path):
if Path(path) == drift_path:
return "0" * 64
return exact_sha(path)
with (
mock.patch.object(RUNNER, "component_root", return_value=root),
mock.patch.object(RUNNER, "sha256_file", side_effect=drift_sha),
):
with self.assertRaises(RUNNER.DeployError):
RUNNER.preflight_engine_composite_provider_v4_predecessor()
if __name__ == "__main__":
unittest.main(verbosity=2)