feat(lab): install thin adapter layers offline
This commit is contained in:
+253
@@ -0,0 +1,253 @@
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[ValidatePattern("^[a-f0-9]{40}$")]
|
||||
[string]$SourceRevision
|
||||
)
|
||||
|
||||
Set-StrictMode -Version Latest
|
||||
$ErrorActionPreference = "Stop"
|
||||
$ProgressPreference = "SilentlyContinue"
|
||||
|
||||
$RuntimeRoot = [IO.Path]::GetFullPath("D:\NDC_MISSIONCORE\runtime").TrimEnd("\")
|
||||
$BuildRoot = Join-Path $RuntimeRoot "staging\observatory-lab-v1-build-$SourceRevision"
|
||||
$SharedAdapterSha256 = "fb208c6cd337153827147006cd26bf4c1c00963f91eb801280485dbc7213d08b"
|
||||
$BuildMethod = "docker-commit-exact-layer-v1"
|
||||
$MaximumLayerBytes = [int64](16MB)
|
||||
|
||||
$Components = [ordered]@{
|
||||
"eomt" = [pscustomobject]@{
|
||||
base_image_sha256 = "58df7489c3f2276f9591d500a012dee03e23d35543ce3c390b4c001e6bf90794"
|
||||
adapter_name = "run_portable_lab_v1_eomt_component.py"
|
||||
adapter_sha256 = "b48ef255403abcfd177a6550688410a52b0fbd29d2a54c8417cb5a0daa330ad5"
|
||||
python_check = "python3 -B -m py_compile"
|
||||
entrypoint = '["python3"]'
|
||||
command = '["/opt/nodedc/adapter/run_portable_lab_v1_eomt_component.py"]'
|
||||
environment = @(
|
||||
"HF_HUB_OFFLINE=1",
|
||||
"TRANSFORMERS_OFFLINE=1",
|
||||
"PYTHONNOUSERSITE=1",
|
||||
"PYTHONDONTWRITEBYTECODE=1",
|
||||
"PYTHONUNBUFFERED=1"
|
||||
)
|
||||
}
|
||||
"ddrnet" = [pscustomobject]@{
|
||||
base_image_sha256 = "591cb382c099eeb05e7ec16e2371e0b2da54d2bb5c49ec0f4ac88dbf72b0f0cd"
|
||||
adapter_name = "run_portable_lab_v1_ddrnet_component.py"
|
||||
adapter_sha256 = "d2af887b065b0f63890768d59247114e49b70ad490c027f20eefd98682636c3c"
|
||||
python_check = "conda run --no-capture-output --name goose python -B -m py_compile"
|
||||
entrypoint = '["conda","run","--no-capture-output","--name","goose","python"]'
|
||||
command = '["/opt/nodedc/adapter/run_portable_lab_v1_ddrnet_component.py"]'
|
||||
environment = @(
|
||||
"PYTHONDONTWRITEBYTECODE=1",
|
||||
"PYTHONUNBUFFERED=1"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
function Get-FileSha256 {
|
||||
param([string]$Path)
|
||||
|
||||
$item = Get-Item -LiteralPath $Path -Force
|
||||
if (
|
||||
-not ($item -is [IO.FileInfo]) -or
|
||||
($item.Attributes -band [IO.FileAttributes]::ReparsePoint)
|
||||
) {
|
||||
throw "LAB V1 adapter source is not a regular file"
|
||||
}
|
||||
return (Get-FileHash -LiteralPath $item.FullName -Algorithm SHA256).Hash.ToLowerInvariant()
|
||||
}
|
||||
|
||||
function Get-ImageInspection {
|
||||
param([string]$Reference)
|
||||
|
||||
$payload = docker image inspect $Reference
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "LAB V1 component image is unavailable: $Reference"
|
||||
}
|
||||
$rows = @($payload | ConvertFrom-Json)
|
||||
if ($rows.Count -ne 1 -or [string]$rows[0].Id -notmatch "^sha256:[a-f0-9]{64}$") {
|
||||
throw "LAB V1 component image inspection is invalid"
|
||||
}
|
||||
return $rows[0]
|
||||
}
|
||||
|
||||
function Assert-ComponentSource {
|
||||
param(
|
||||
[string]$ComponentRoot,
|
||||
[object]$Descriptor
|
||||
)
|
||||
|
||||
$shared = Join-Path $ComponentRoot "portable_lab_v1_component_adapter.py"
|
||||
$component = Join-Path $ComponentRoot $Descriptor.adapter_name
|
||||
if ((Get-FileSha256 $shared) -cne $SharedAdapterSha256) {
|
||||
throw "Shared LAB V1 component adapter identity changed"
|
||||
}
|
||||
if ((Get-FileSha256 $component) -cne [string]$Descriptor.adapter_sha256) {
|
||||
throw "LAB V1 component adapter identity changed"
|
||||
}
|
||||
}
|
||||
|
||||
function Invoke-InstalledImageSmoke {
|
||||
param(
|
||||
[string]$Tag,
|
||||
[object]$Descriptor
|
||||
)
|
||||
|
||||
$script = (
|
||||
"set -eu; " +
|
||||
"test `$(sha256sum /opt/nodedc/adapter/portable_lab_v1_component_adapter.py " +
|
||||
"| cut -d' ' -f1) = $SharedAdapterSha256; " +
|
||||
"test `$(sha256sum /opt/nodedc/adapter/$($Descriptor.adapter_name) " +
|
||||
"| cut -d' ' -f1) = $($Descriptor.adapter_sha256)"
|
||||
)
|
||||
docker run `
|
||||
--rm `
|
||||
--network none `
|
||||
--cap-drop ALL `
|
||||
--security-opt no-new-privileges `
|
||||
--entrypoint /bin/sh `
|
||||
$Tag `
|
||||
-c $script
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "Installed LAB V1 component image smoke failed"
|
||||
}
|
||||
}
|
||||
|
||||
function Install-ComponentImage {
|
||||
param(
|
||||
[string]$Component,
|
||||
[object]$Descriptor
|
||||
)
|
||||
|
||||
$componentRoot = Join-Path $BuildRoot $Component
|
||||
if (-not (Test-Path -LiteralPath $componentRoot -PathType Container)) {
|
||||
throw "LAB V1 component build source is unavailable"
|
||||
}
|
||||
Assert-ComponentSource $componentRoot $Descriptor
|
||||
$baseReference = "sha256:$($Descriptor.base_image_sha256)"
|
||||
$base = Get-ImageInspection $baseReference
|
||||
if ([string]$base.Id -cne $baseReference) {
|
||||
throw "LAB V1 component base image identity changed"
|
||||
}
|
||||
$shortRevision = $SourceRevision.Substring(0, 12)
|
||||
$tag = "ndc/mission-core-lab-v1-$Component-adapter:$shortRevision"
|
||||
$existing = docker image inspect $tag 2>$null
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
$image = @($existing | ConvertFrom-Json)[0]
|
||||
$labels = $image.Config.Labels
|
||||
if (
|
||||
[string]$labels."org.opencontainers.image.revision" -cne $SourceRevision -or
|
||||
[string]$labels."com.nodedc.base-image.sha256" -cne
|
||||
[string]$Descriptor.base_image_sha256 -or
|
||||
[string]$labels."com.nodedc.shared-adapter.sha256" -cne
|
||||
$SharedAdapterSha256 -or
|
||||
[string]$labels."com.nodedc.component-adapter.sha256" -cne
|
||||
[string]$Descriptor.adapter_sha256 -or
|
||||
[string]$labels."com.nodedc.build-method" -cne $BuildMethod
|
||||
) {
|
||||
throw "Existing LAB V1 component image label identity changed"
|
||||
}
|
||||
Invoke-InstalledImageSmoke $tag $Descriptor
|
||||
return [ordered]@{
|
||||
component = $Component
|
||||
status = "already-installed"
|
||||
tag = $tag
|
||||
base_image_sha256 = [string]$Descriptor.base_image_sha256
|
||||
derived_image_sha256 = ([string]$image.Id).Substring(7)
|
||||
build_method = $BuildMethod
|
||||
}
|
||||
}
|
||||
|
||||
$containerName = "ndc-lab-v1-$Component-image-build-$shortRevision"
|
||||
$existingContainer = docker ps -a --filter "name=^/$containerName$" --format "{{.ID}}"
|
||||
if ($existingContainer) {
|
||||
throw "LAB V1 temporary build container name is already occupied"
|
||||
}
|
||||
$copyScript = (
|
||||
"set -eu; " +
|
||||
"mkdir -p /opt/nodedc/adapter; " +
|
||||
"cp /nodedc-build-source/portable_lab_v1_component_adapter.py " +
|
||||
"/opt/nodedc/adapter/portable_lab_v1_component_adapter.py; " +
|
||||
"cp /nodedc-build-source/$($Descriptor.adapter_name) " +
|
||||
"/opt/nodedc/adapter/$($Descriptor.adapter_name); " +
|
||||
"test `$(sha256sum /opt/nodedc/adapter/portable_lab_v1_component_adapter.py " +
|
||||
"| cut -d' ' -f1) = $SharedAdapterSha256; " +
|
||||
"test `$(sha256sum /opt/nodedc/adapter/$($Descriptor.adapter_name) " +
|
||||
"| cut -d' ' -f1) = $($Descriptor.adapter_sha256); " +
|
||||
"chmod 0444 /opt/nodedc/adapter/*.py; " +
|
||||
"$($Descriptor.python_check) " +
|
||||
"/opt/nodedc/adapter/portable_lab_v1_component_adapter.py " +
|
||||
"/opt/nodedc/adapter/$($Descriptor.adapter_name); " +
|
||||
"rm -rf /opt/nodedc/adapter/__pycache__"
|
||||
)
|
||||
$mount = "type=bind,source=$componentRoot,target=/nodedc-build-source,readonly"
|
||||
$containerId = docker create `
|
||||
--name $containerName `
|
||||
--network none `
|
||||
--cap-drop ALL `
|
||||
--security-opt no-new-privileges `
|
||||
--mount $mount `
|
||||
--entrypoint /bin/sh `
|
||||
$baseReference `
|
||||
-c $copyScript
|
||||
if ($LASTEXITCODE -ne 0 -or $containerId -notmatch "^[a-f0-9]{64}$") {
|
||||
throw "LAB V1 temporary component build container creation failed"
|
||||
}
|
||||
try {
|
||||
docker start --attach $containerId
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "LAB V1 component adapter installation command failed"
|
||||
}
|
||||
$changes = @(
|
||||
"--change", "ENTRYPOINT $($Descriptor.entrypoint)",
|
||||
"--change", "CMD $($Descriptor.command)",
|
||||
"--change", "LABEL org.opencontainers.image.revision=$SourceRevision",
|
||||
"--change", "LABEL com.nodedc.product=mission-core",
|
||||
"--change", "LABEL com.nodedc.stack=observatory",
|
||||
"--change", "LABEL com.nodedc.component=lab-v1-$Component",
|
||||
"--change", "LABEL com.nodedc.authority=observation-only",
|
||||
"--change", "LABEL com.nodedc.base-image.sha256=$($Descriptor.base_image_sha256)",
|
||||
"--change", "LABEL com.nodedc.shared-adapter.sha256=$SharedAdapterSha256",
|
||||
"--change", "LABEL com.nodedc.component-adapter.sha256=$($Descriptor.adapter_sha256)",
|
||||
"--change", "LABEL com.nodedc.build-method=$BuildMethod"
|
||||
)
|
||||
foreach ($value in $Descriptor.environment) {
|
||||
$changes += @("--change", "ENV $value")
|
||||
}
|
||||
docker commit @changes $containerId $tag | Out-Null
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "LAB V1 component image commit failed"
|
||||
}
|
||||
}
|
||||
finally {
|
||||
docker rm -f $containerId | Out-Null
|
||||
}
|
||||
|
||||
$image = Get-ImageInspection $tag
|
||||
if (
|
||||
[int64]$image.Size -lt [int64]$base.Size -or
|
||||
([int64]$image.Size - [int64]$base.Size) -gt $MaximumLayerBytes
|
||||
) {
|
||||
throw "LAB V1 adapter image is not a thin layer"
|
||||
}
|
||||
Invoke-InstalledImageSmoke $tag $Descriptor
|
||||
return [ordered]@{
|
||||
component = $Component
|
||||
status = "installed"
|
||||
tag = $tag
|
||||
base_image_sha256 = [string]$Descriptor.base_image_sha256
|
||||
derived_image_sha256 = ([string]$image.Id).Substring(7)
|
||||
build_method = $BuildMethod
|
||||
}
|
||||
}
|
||||
|
||||
if (-not (Test-Path -LiteralPath $BuildRoot -PathType Container)) {
|
||||
throw "LAB V1 component build root is unavailable"
|
||||
}
|
||||
|
||||
$outputs = New-Object "Collections.Generic.List[object]"
|
||||
foreach ($component in $Components.Keys) {
|
||||
$outputs.Add((Install-ComponentImage $component $Components[$component]))
|
||||
}
|
||||
$outputs.ToArray() | ConvertTo-Json -Compress -Depth 5
|
||||
@@ -0,0 +1,50 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
REPOSITORY_ROOT = Path(__file__).resolve().parents[1]
|
||||
INSTALLER = (
|
||||
REPOSITORY_ROOT
|
||||
/ "experiments/perception/worker/observatory_portable"
|
||||
/ "Install-LabV1ComponentAdapterImages.ps1"
|
||||
)
|
||||
|
||||
|
||||
def test_component_image_installer_is_exact_local_and_offline() -> None:
|
||||
script = INSTALLER.read_text(encoding="utf-8")
|
||||
|
||||
assert '"docker-commit-exact-layer-v1"' in script
|
||||
assert "--network none" in script
|
||||
assert "--cap-drop ALL" in script
|
||||
assert "--security-opt no-new-privileges" in script
|
||||
assert "target=/nodedc-build-source,readonly" in script
|
||||
assert "Get-FileSha256" in script
|
||||
assert "Invoke-InstalledImageSmoke" in script
|
||||
assert "docker commit @changes $containerId $tag" in script
|
||||
assert "docker rm -f $containerId" in script
|
||||
assert "com.nodedc.build-method" in script
|
||||
|
||||
lowered = script.lower()
|
||||
assert "docker pull" not in lowered
|
||||
assert "invoke-webrequest" not in lowered
|
||||
assert "start-bitstransfer" not in lowered
|
||||
assert "curl " not in lowered
|
||||
assert "wget " not in lowered
|
||||
assert "smb" not in lowered
|
||||
|
||||
|
||||
def test_component_image_installer_binds_bases_and_adapter_sources() -> None:
|
||||
script = INSTALLER.read_text(encoding="utf-8")
|
||||
|
||||
for digest in (
|
||||
"58df7489c3f2276f9591d500a012dee03e23d35543ce3c390b4c001e6bf90794",
|
||||
"591cb382c099eeb05e7ec16e2371e0b2da54d2bb5c49ec0f4ac88dbf72b0f0cd",
|
||||
"fb208c6cd337153827147006cd26bf4c1c00963f91eb801280485dbc7213d08b",
|
||||
"b48ef255403abcfd177a6550688410a52b0fbd29d2a54c8417cb5a0daa330ad5",
|
||||
"d2af887b065b0f63890768d59247114e49b70ad490c027f20eefd98682636c3c",
|
||||
):
|
||||
assert digest in script
|
||||
assert 'entrypoint = \'["python3"]\'' in script
|
||||
assert '"goose","python"' in script
|
||||
assert 'command = \'["/opt/nodedc/adapter/run_portable_lab_v1_eomt_component.py"]\'' in script
|
||||
assert 'command = \'["/opt/nodedc/adapter/run_portable_lab_v1_ddrnet_component.py"]\'' in script
|
||||
Reference in New Issue
Block a user