feat(worker): define unified agent image artifact
This commit is contained in:
@@ -0,0 +1,277 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import re
|
||||
from pathlib import Path
|
||||
from typing import cast
|
||||
|
||||
from k1link.observatory import portable_lab_v1_local_runners as local_runners
|
||||
|
||||
REPOSITORY_ROOT = Path(__file__).resolve().parents[1]
|
||||
ARTIFACT_ROOT = (
|
||||
REPOSITORY_ROOT / "experiments" / "perception" / "worker" / "observatory_portable"
|
||||
)
|
||||
DOCKERFILE = ARTIFACT_ROOT / "Dockerfile.worker-006-agent"
|
||||
CONTEXT_MANIFEST = ARTIFACT_ROOT / "worker-006-agent-build-context.json"
|
||||
INSTALL_PLAN = ARTIFACT_ROOT / "worker-006-agent-install-plan.template.json"
|
||||
BASE_SHA256 = "58df7489c3f2276f9591d500a012dee03e23d35543ce3c390b4c001e6bf90794"
|
||||
BASE_REFERENCE = f"nvcr.io/nvidia/tritonserver:26.06-py3@sha256:{BASE_SHA256}"
|
||||
ENTRYPOINT = ["python3", "-m", "k1link.observatory.m49_worker_container_main"]
|
||||
AUTHORITY = {
|
||||
"commands_enabled": False,
|
||||
"actuation_allowed": False,
|
||||
"navigation_or_safety_accepted": False,
|
||||
"production_accepted": False,
|
||||
}
|
||||
|
||||
|
||||
def _document(path: Path) -> dict[str, object]:
|
||||
value: object = json.loads(path.read_text(encoding="utf-8"))
|
||||
assert isinstance(value, dict)
|
||||
return cast(dict[str, object], value)
|
||||
|
||||
|
||||
def test_agent_dockerfile_is_offline_commit_bound_and_model_free() -> None:
|
||||
payload = DOCKERFILE.read_text(encoding="utf-8")
|
||||
|
||||
assert payload.splitlines()[0] == f"FROM {BASE_REFERENCE}"
|
||||
assert "ARG NODEDC_SOURCE_REVISION" in payload
|
||||
assert "ARG NODEDC_BUILD_CONTEXT_SHA256" in payload
|
||||
assert "ARG SOURCE_DATE_EPOCH" in payload
|
||||
assert "org.opencontainers.image.revision=\"${NODEDC_SOURCE_REVISION}\"" in payload
|
||||
assert "com.nodedc.build-context.sha256=\"${NODEDC_BUILD_CONTEXT_SHA256}\"" in payload
|
||||
assert "com.nodedc.models=\"external\"" in payload
|
||||
assert "PYTHONPATH=/opt/nodedc/mission-core/src" in payload
|
||||
assert 'ENTRYPOINT ["python3", "-m", "k1link.observatory.m49_worker_container_main"]' in payload
|
||||
assert "CMD []" in payload
|
||||
assert "COPY src/k1link ./src/k1link" in payload
|
||||
assert "COPY config ./config" in payload
|
||||
assert "COPY . ." not in payload
|
||||
assert re.search(r"(?im)^\s*(?:run\s+)?(?:apt|apk|yum|dnf|pip|uv)\b", payload) is None
|
||||
assert "curl " not in payload.lower()
|
||||
assert "wget " not in payload.lower()
|
||||
assert "git clone" not in payload.lower()
|
||||
|
||||
|
||||
def test_build_context_is_only_repo_source_configuration_and_artifact_contract() -> None:
|
||||
document = _document(CONTEXT_MANIFEST)
|
||||
|
||||
assert document["schema_version"] == "missioncore.observatory-worker-agent-build-context/v1"
|
||||
assert document["worker_id"] == "worker-006"
|
||||
assert document["authority"] == AUTHORITY
|
||||
source = cast(dict[str, object], document["source_contract"])
|
||||
assert source == {
|
||||
"required_state": "clean-committed-snapshot",
|
||||
"revision_format": "full-git-sha1",
|
||||
"materialization": "git-archive",
|
||||
"timestamp_source": "selected-commit-committer-epoch",
|
||||
"uncommitted_files_allowed": False,
|
||||
}
|
||||
context_digest = cast(dict[str, object], document["context_digest"])
|
||||
assert context_digest == {
|
||||
"algorithm": "sha256",
|
||||
"subject": "git-archive-tar-bytes",
|
||||
"archive_format": "tar",
|
||||
"path_order": "git-archive-native-order",
|
||||
}
|
||||
base = cast(dict[str, object], document["base_image"])
|
||||
assert base == {
|
||||
"reference": BASE_REFERENCE,
|
||||
"sha256": BASE_SHA256,
|
||||
"pull_allowed": False,
|
||||
}
|
||||
|
||||
entries = cast(list[dict[str, object]], document["context_entries"])
|
||||
paths = [cast(str, row["path"]) for row in entries]
|
||||
assert paths == [
|
||||
"src/k1link",
|
||||
"config",
|
||||
"experiments/perception/worker/observatory_portable/Dockerfile.worker-006-agent",
|
||||
"experiments/perception/worker/observatory_portable/worker-006-agent-build-context.json",
|
||||
]
|
||||
for relative in paths:
|
||||
assert (REPOSITORY_ROOT / relative).exists()
|
||||
assert not any(
|
||||
token in relative.lower()
|
||||
for relative in paths
|
||||
for token in ("model", "weight", "session", "credential", "runtime")
|
||||
)
|
||||
|
||||
required = cast(list[str], document["required_configuration"])
|
||||
assert required == [
|
||||
"config/observatory-portable-run-definitions.json",
|
||||
"config/observatory-worker-runtime-candidates.json",
|
||||
"config/perception/m49-tgs-portable-v2.json",
|
||||
"config/perception/lab-v1-eomt-ddrnet-portable-v2.json",
|
||||
]
|
||||
assert all((REPOSITORY_ROOT / relative).is_file() for relative in required)
|
||||
runtime = cast(dict[str, object], document["runtime"])
|
||||
assert runtime["entrypoint"] == ENTRYPOINT
|
||||
assert runtime["composition_module"] == "k1link.observatory.m49_worker_service"
|
||||
assert runtime["models_baked_into_image"] is False
|
||||
assert runtime["executor_releases_baked_into_image"] is False
|
||||
|
||||
|
||||
def test_install_plan_requires_offline_build_hardening_smoke_and_unfilled_receipt() -> None:
|
||||
document = _document(INSTALL_PLAN)
|
||||
|
||||
assert document["schema_version"] == "missioncore.observatory-worker-agent-install-plan/v1"
|
||||
assert document["state"] == "planned-not-built"
|
||||
build = cast(dict[str, object], document["build"])
|
||||
assert build["source_revision"] is None
|
||||
assert build["source_date_epoch"] is None
|
||||
assert build["build_context_sha256"] is None
|
||||
materialization = cast(dict[str, object], build["materialization"])
|
||||
assert materialization == {
|
||||
"method": "git archive",
|
||||
"include_only_context_manifest_entries": True,
|
||||
"reject_dirty_worktree": True,
|
||||
"archive_format": "tar",
|
||||
"archive_paths_source": "context manifest context_entries in declared order",
|
||||
"build_context_sha256_subject": "exact git-archive tar bytes",
|
||||
}
|
||||
base = cast(dict[str, object], build["base_image"])
|
||||
assert base["reference"] == BASE_REFERENCE
|
||||
assert base["sha256"] == BASE_SHA256
|
||||
assert base["must_exist_locally"] is True
|
||||
assert base["pull_allowed"] is False
|
||||
docker_build = cast(dict[str, object], build["docker_build"])
|
||||
assert docker_build == {
|
||||
"network": "none",
|
||||
"pull": False,
|
||||
"no_cache": True,
|
||||
"provenance": False,
|
||||
"platform": "linux/amd64",
|
||||
"context_input": "exact git-archive tar bytes",
|
||||
"required_build_args": [
|
||||
"NODEDC_SOURCE_REVISION",
|
||||
"NODEDC_BUILD_CONTEXT_SHA256",
|
||||
"SOURCE_DATE_EPOCH",
|
||||
],
|
||||
}
|
||||
assert build["required_preflight"] == [
|
||||
"Git worktree and index are clean",
|
||||
"selected revision resolves to exactly one commit",
|
||||
"selected revision equals HEAD",
|
||||
"base image inspect ID equals the pinned SHA-256",
|
||||
"context archive contains exactly the context manifest entries",
|
||||
]
|
||||
|
||||
acceptance = cast(dict[str, object], document["build_acceptance"])
|
||||
labels = cast(dict[str, str], acceptance["required_labels"])
|
||||
assert labels["org.opencontainers.image.revision"] == "<source-revision>"
|
||||
assert labels["com.nodedc.base-image.sha256"] == BASE_SHA256
|
||||
assert labels["com.nodedc.models"] == "external"
|
||||
smoke = cast(dict[str, object], acceptance["smoke"])
|
||||
assert smoke["network"] == "none"
|
||||
assert smoke["read_only_rootfs"] is True
|
||||
assert smoke["platform"] == "linux/amd64"
|
||||
assert smoke["expected_result"] == "exit-0"
|
||||
|
||||
runtime = cast(dict[str, object], document["runtime"])
|
||||
environment = cast(dict[str, str], runtime["fixed_environment"])
|
||||
assert environment == {
|
||||
"MISSIONCORE_OBSERVATORY_WORKER_BASE_URL": "http://127.0.0.1:18080",
|
||||
"MISSIONCORE_OBSERVATORY_WORKER_TOKEN_FILE": "/run/secrets/observatory-worker.token",
|
||||
"MISSIONCORE_OBSERVATORY_WORKER_WORK_ROOT": "/work",
|
||||
"MISSIONCORE_OBSERVATORY_WORKER_DEFINITIONS_FILE": (
|
||||
"/opt/nodedc/mission-core/config/observatory-portable-run-definitions.json"
|
||||
),
|
||||
"MISSIONCORE_OBSERVATORY_WORKER_RUNTIME_REGISTRY_FILE": (
|
||||
"/opt/nodedc/mission-core/config/observatory-worker-runtime-candidates.json"
|
||||
),
|
||||
"MISSIONCORE_OBSERVATORY_M49_INSTALLATION_RECEIPT_FILE": (
|
||||
"/release/worker-installation-receipt.json"
|
||||
),
|
||||
}
|
||||
user = cast(dict[str, object], runtime["user"])
|
||||
assert (user["uid"], user["gid"]) == (0, 0)
|
||||
assert cast(str, user["reason"]).strip()
|
||||
hardening = cast(dict[str, object], runtime["hardening"])
|
||||
assert hardening["read_only_rootfs"] is True
|
||||
assert hardening["cap_drop"] == ["ALL"]
|
||||
assert hardening["no_new_privileges"] is True
|
||||
assert hardening["published_ports"] == []
|
||||
assert hardening["device_requests"] == []
|
||||
assert "docker_socket_mount" not in hardening
|
||||
assert '"docker_socket_mount": false' not in INSTALL_PLAN.read_text(encoding="utf-8")
|
||||
|
||||
docker_control = cast(dict[str, object], runtime["docker_engine_control"])
|
||||
assert docker_control["transport"] == (
|
||||
"Docker Engine HTTP API over Unix domain socket; Docker CLI is not used"
|
||||
)
|
||||
assert docker_control["authority"] == "host-equivalent Docker Engine control"
|
||||
assert "compromised Worker agent" in cast(str, docker_control["risk"])
|
||||
socket_mount = cast(dict[str, object], docker_control["socket_mount"])
|
||||
assert socket_mount == {
|
||||
"type": "bind",
|
||||
"host_path": str(local_runners._DOCKER_SOCKET),
|
||||
"container_path": str(local_runners._DOCKER_SOCKET),
|
||||
"mode": "read-write",
|
||||
"exception_to_read_only_mount_policy": True,
|
||||
}
|
||||
assert docker_control["allowed_operations"] == [
|
||||
"inspect exact installed image identity",
|
||||
"create one sealed LAB V1 sibling",
|
||||
"start exact created container ID",
|
||||
"wait exact created container ID",
|
||||
"read bounded tail logs for failed exact created container ID",
|
||||
"force-delete exact created container ID",
|
||||
]
|
||||
fences = cast(dict[str, object], docker_control["sibling_runtime_fences"])
|
||||
assert fences["exact_image_sha256s"] == {
|
||||
"eomt": local_runners._EOMT_IMAGE_SHA256,
|
||||
"ddrnet": local_runners._DDRNET_IMAGE_SHA256,
|
||||
}
|
||||
assert local_runners._EOMT_IMAGE_SHA256 == BASE_SHA256
|
||||
assert "queued job" in cast(str, fences["commands_and_entrypoints"])
|
||||
assert "exact Worker-host asset roots" in cast(str, fences["bind_sources"])
|
||||
assert fences["network"] == "none"
|
||||
assert fences["read_only_rootfs"] is True
|
||||
assert fences["cap_drop"] == ["ALL"]
|
||||
assert fences["no_new_privileges"] is True
|
||||
assert fences["privileged"] is False
|
||||
assert fences["pids_limit"] == 512
|
||||
assert fences["memory_swap_equals_memory"] is True
|
||||
assert fences["gpu_request"] == {
|
||||
"driver": "nvidia",
|
||||
"count": 1,
|
||||
"capabilities": [["gpu"]],
|
||||
}
|
||||
assert fences["required_unique_labels"] == [
|
||||
"com.nodedc.authority=observation-only",
|
||||
"com.nodedc.component=<eomt-or-ddrnet>",
|
||||
"com.nodedc.definition-sha256=<installed-definition-sha256>",
|
||||
"com.nodedc.managed-by=mission-core-worker",
|
||||
"com.nodedc.request-sha256=<sealed-request-sha256>",
|
||||
"com.nodedc.product=mission-core",
|
||||
"com.nodedc.release-candidate-sha256=<installed-release-candidate-sha256>",
|
||||
"com.nodedc.stack=observatory",
|
||||
]
|
||||
assert cast(str, fences["cleanup"]).endswith(
|
||||
"exact 64-hex container ID returned by the successful create response"
|
||||
)
|
||||
external = cast(dict[str, object], runtime["external_assets"])
|
||||
assert external["baked_into_agent_image"] is False
|
||||
assert external["queued_jobs_may_select_paths_or_commands"] is False
|
||||
lab_v1_input = cast(dict[str, object], runtime["lab_v1_runner_installation_input"])
|
||||
assert lab_v1_input == {
|
||||
"state": "loader-contract-not-yet-defined",
|
||||
"environment_variable": None,
|
||||
"container_path": None,
|
||||
"reason": (
|
||||
"the current local runner module defines an in-memory sealed installation "
|
||||
"receipt but no environment loader or installed receipt path"
|
||||
),
|
||||
}
|
||||
|
||||
receipt = cast(dict[str, object], document["receipt_skeleton"])
|
||||
assert receipt["receipt_state"] == "not-built"
|
||||
assert receipt["source_revision"] is None
|
||||
assert receipt["source_date_epoch"] is None
|
||||
assert receipt["build_context_sha256"] is None
|
||||
assert receipt["base_image_sha256"] == BASE_SHA256
|
||||
image = cast(dict[str, object], receipt["image"])
|
||||
assert image == {"tag": None, "id": None, "size_bytes": None}
|
||||
assert receipt["models_baked_into_image"] is False
|
||||
assert receipt["authority"] == AUTHORITY
|
||||
Reference in New Issue
Block a user