fix: add yaml runtime image build for d518
This commit is contained in:
@@ -33,7 +33,7 @@ import { isCommandSuccess, nodeRuntimeGitopsRoot, runNodeK3sArgs, runNodeK3sScri
|
||||
import { nodeRuntimeCicdWaitWarning } from "./git-mirror";
|
||||
import { parseNodeScopedDelegatedOptions } from "./plan";
|
||||
import { nodeRuntimePipelineFailureSummary, nodeRuntimePipelineRunDiagnostics } from "./render";
|
||||
import { compactRuntimeCommand, runNodeHostScript } from "./runtime-common";
|
||||
import { compactRuntimeCommand, runNodeHostScript, runNodeHostScriptAsync } from "./runtime-common";
|
||||
import { assertLane, assertNodeId, keyValueLinesFromText, numericField, optionValue, optionalStringValue, positiveIntegerOption, positiveIntegerValue, record, requiredOption, shellQuote, statusText, stringValue, stripOptions } from "./utils";
|
||||
import { discoverWebObserveIndexEntry, readWebObserveIndexEntry } from "./web-observe-render";
|
||||
import { assertKnownOptions, nodeWebProbeAutoCommandTimeoutSeconds, nodeWebProbeDefaultUrl, normalizeNodeWebProbeObserveArgs, parseNodeWebProbeObserveOptions, parseNodeWebProbeSentinelOptions, parseWebProbeBrowserProxyMode } from "./web-probe-observe";
|
||||
@@ -95,6 +95,7 @@ export function nodeRuntimeRenderOverlay(spec: HwlabRuntimeLaneSpec): Record<str
|
||||
observability: spec.observability,
|
||||
runtimeStore: spec.runtimeStore,
|
||||
runtimeImageRewrites: spec.runtimeImageRewrites,
|
||||
runtimeImageBuilds: spec.runtimeImageBuilds,
|
||||
registryPrefix: spec.registryPrefix,
|
||||
buildkitSidecarImage: spec.buildkit?.sidecarImage,
|
||||
publicWebUrl: spec.publicWebUrl,
|
||||
@@ -809,24 +810,54 @@ interface NodeRuntimeImageDependency {
|
||||
id: string;
|
||||
target: string;
|
||||
source: string;
|
||||
mode: "pull" | "build-moonbridge";
|
||||
sourceRepo?: string;
|
||||
sourceRef?: string;
|
||||
builderImage?: string;
|
||||
goProxy?: string;
|
||||
dockerNetworkMode?: "default" | "host";
|
||||
}
|
||||
|
||||
function nodeRuntimeImageDependencies(spec: HwlabRuntimeLaneSpec): NodeRuntimeImageDependency[] {
|
||||
const images: NodeRuntimeImageDependency[] = [
|
||||
{ id: "base", target: spec.baseImage, source: spec.baseImageSource ?? "" },
|
||||
{ id: "base", target: spec.baseImage, source: spec.baseImageSource ?? "", mode: "pull" },
|
||||
];
|
||||
if (spec.buildkit !== undefined) {
|
||||
images.push({ id: "buildkit", target: spec.buildkit.sidecarImage, source: spec.buildkit.sourceImage });
|
||||
images.push({ id: "buildkit", target: spec.buildkit.sidecarImage, source: spec.buildkit.sourceImage, mode: "pull" });
|
||||
}
|
||||
spec.runtimeImageRewrites.forEach((rewrite, index) => {
|
||||
images.push({ id: `rewrite-${index + 1}`, target: rewrite.target, source: rewrite.source });
|
||||
images.push({ id: `rewrite-${index + 1}`, target: rewrite.target, source: rewrite.source, mode: "pull" });
|
||||
});
|
||||
spec.runtimeImageBuilds.forEach((build) => {
|
||||
images.push({
|
||||
id: build.id,
|
||||
target: build.target,
|
||||
source: `${build.sourceRepo}#${build.sourceRef}`,
|
||||
mode: "build-moonbridge",
|
||||
sourceRepo: build.sourceRepo,
|
||||
sourceRef: build.sourceRef,
|
||||
builderImage: build.builderImage,
|
||||
goProxy: build.goProxy,
|
||||
dockerNetworkMode: build.dockerNetworkMode,
|
||||
});
|
||||
});
|
||||
return images;
|
||||
}
|
||||
|
||||
function nodeRuntimeImageCalls(spec: HwlabRuntimeLaneSpec, functionName: string): string {
|
||||
return nodeRuntimeImageDependencies(spec)
|
||||
.map((image) => `${functionName} ${shellQuote(image.id)} ${shellQuote(image.target)} ${shellQuote(image.source)}`)
|
||||
.map((image) => [
|
||||
functionName,
|
||||
image.id,
|
||||
image.target,
|
||||
image.source,
|
||||
image.mode,
|
||||
image.sourceRepo ?? "",
|
||||
image.sourceRef ?? "",
|
||||
image.builderImage ?? "",
|
||||
image.goProxy ?? "",
|
||||
image.dockerNetworkMode ?? "",
|
||||
].map(shellQuote).join(" "))
|
||||
.join("\n");
|
||||
}
|
||||
|
||||
@@ -845,7 +876,7 @@ export function nodeRuntimeBaseImageStatus(spec: HwlabRuntimeLaneSpec, timeoutSe
|
||||
const script = [
|
||||
"set -eu",
|
||||
"check_image() {",
|
||||
" id=\"$1\"; target=\"$2\"; source=\"$3\"",
|
||||
" id=\"$1\"; target=\"$2\"; source=\"$3\"; mode=\"$4\"",
|
||||
" repo_tag=${target#*/}",
|
||||
" repo=${repo_tag%:*}",
|
||||
" tag=${repo_tag##*:}",
|
||||
@@ -856,12 +887,12 @@ export function nodeRuntimeBaseImageStatus(spec: HwlabRuntimeLaneSpec, timeoutSe
|
||||
" target_present=false",
|
||||
" if docker image inspect \"$target\" >/dev/null 2>&1; then target_present=true; fi",
|
||||
" source_present=false",
|
||||
" if [ -n \"$source\" ] && docker image inspect \"$source\" >/dev/null 2>&1; then source_present=true; fi",
|
||||
" if [ \"$mode\" = build-moonbridge ]; then source_present=true; elif [ -n \"$source\" ] && docker image inspect \"$source\" >/dev/null 2>&1; then source_present=true; fi",
|
||||
" source_configured=false",
|
||||
" if [ -n \"$source\" ]; then source_configured=true; fi",
|
||||
" python3 - \"$id\" \"$target\" \"$source\" \"$source_configured\" \"$registry_url\" \"$registry_present\" \"$target_present\" \"$source_present\" <<'PY'",
|
||||
" python3 - \"$id\" \"$target\" \"$source\" \"$mode\" \"$source_configured\" \"$registry_url\" \"$registry_present\" \"$target_present\" \"$source_present\" <<'PY'",
|
||||
"import json, sys",
|
||||
"keys=['id','target','source','sourceConfigured','registryUrl','registryTagPresent','targetImagePresent','sourceImagePresent']",
|
||||
"keys=['id','target','source','mode','sourceConfigured','registryUrl','registryTagPresent','targetImagePresent','sourceImagePresent']",
|
||||
"data=dict(zip(keys, sys.argv[1:]))",
|
||||
"for key in ['sourceConfigured','registryTagPresent','targetImagePresent','sourceImagePresent']:",
|
||||
" data[key] = data[key] == 'true'",
|
||||
@@ -893,9 +924,57 @@ export function ensureNodeBaseImage(spec: HwlabRuntimeLaneSpec, dryRun: boolean,
|
||||
"set -eu",
|
||||
`dry_run=${shellQuote(dryRun ? "true" : "false")}`,
|
||||
`pull_retries=${shellQuote(String(Math.max(1, spec.downloadProfile.docker.pullRetries)))}`,
|
||||
`build_http_proxy=${shellQuote(spec.networkProfile.dockerBuildProxy.http)}`,
|
||||
`build_https_proxy=${shellQuote(spec.networkProfile.dockerBuildProxy.https)}`,
|
||||
`build_all_proxy=${shellQuote(spec.networkProfile.dockerBuildProxy.all)}`,
|
||||
`build_no_proxy=${shellQuote(spec.networkProfile.dockerBuildProxy.noProxy.join(","))}`,
|
||||
"resolve_host_proxy_url() {",
|
||||
" raw_url=\"$1\"",
|
||||
" if [ -z \"$raw_url\" ]; then printf '\\n'; return 0; fi",
|
||||
" info=$(python3 - \"$raw_url\" <<'PY'",
|
||||
"from urllib.parse import urlparse",
|
||||
"import sys",
|
||||
"url = sys.argv[1]",
|
||||
"parsed = urlparse(url)",
|
||||
"host = parsed.hostname or ''",
|
||||
"port = parsed.port",
|
||||
"scheme = parsed.scheme or 'http'",
|
||||
"parts = host.split('.')",
|
||||
"if len(parts) >= 4 and parts[2] == 'svc':",
|
||||
" print('\\t'.join(['service', scheme, parts[0], parts[1], str(port or 80)]))",
|
||||
"else:",
|
||||
" print('\\t'.join(['literal', url]))",
|
||||
"PY",
|
||||
" )",
|
||||
" kind=$(printf '%s' \"$info\" | cut -f1)",
|
||||
" service_cluster_ip() {",
|
||||
" service_namespace=\"$1\"; service_name=\"$2\"",
|
||||
" cluster_ip=\"\"",
|
||||
" if command -v kubectl >/dev/null 2>&1; then",
|
||||
" cluster_ip=$(kubectl -n \"$service_namespace\" get svc \"$service_name\" -o jsonpath='{.spec.clusterIP}' 2>/dev/null || true)",
|
||||
" fi",
|
||||
" if { [ -z \"$cluster_ip\" ] || [ \"$cluster_ip\" = None ]; } && command -v k3s >/dev/null 2>&1; then",
|
||||
" cluster_ip=$(k3s kubectl -n \"$service_namespace\" get svc \"$service_name\" -o jsonpath='{.spec.clusterIP}' 2>/dev/null || true)",
|
||||
" fi",
|
||||
" printf '%s\\n' \"$cluster_ip\"",
|
||||
" }",
|
||||
" if [ \"$kind\" = service ]; then",
|
||||
" scheme=$(printf '%s' \"$info\" | cut -f2)",
|
||||
" service_name=$(printf '%s' \"$info\" | cut -f3)",
|
||||
" service_namespace=$(printf '%s' \"$info\" | cut -f4)",
|
||||
" service_port=$(printf '%s' \"$info\" | cut -f5)",
|
||||
" cluster_ip=$(service_cluster_ip \"$service_namespace\" \"$service_name\")",
|
||||
" if [ -n \"$cluster_ip\" ] && [ \"$cluster_ip\" != None ]; then printf '%s://%s:%s\\n' \"$scheme\" \"$cluster_ip\" \"$service_port\"; else printf '%s\\n' \"$raw_url\"; fi",
|
||||
" else",
|
||||
" printf '%s\\n' \"$raw_url\"",
|
||||
" fi",
|
||||
"}",
|
||||
"build_http_proxy=$(resolve_host_proxy_url \"$build_http_proxy\")",
|
||||
"build_https_proxy=$(resolve_host_proxy_url \"$build_https_proxy\")",
|
||||
"build_all_proxy=$(resolve_host_proxy_url \"$build_all_proxy\")",
|
||||
"failed=false",
|
||||
"ensure_image() {",
|
||||
" id=\"$1\"; target=\"$2\"; source=\"$3\"",
|
||||
" id=\"$1\"; target=\"$2\"; source=\"$3\"; mode=\"$4\"; source_repo=\"$5\"; source_ref=\"$6\"; builder_image=\"$7\"; go_proxy=\"$8\"; docker_network_mode=\"$9\"",
|
||||
" repo_tag=${target#*/}",
|
||||
" repo=${repo_tag%:*}",
|
||||
" tag=${repo_tag##*:}",
|
||||
@@ -910,13 +989,47 @@ export function ensureNodeBaseImage(spec: HwlabRuntimeLaneSpec, dryRun: boolean,
|
||||
" if [ \"$present\" = false ]; then",
|
||||
" action=seed",
|
||||
" if [ \"$dry_run\" = false ]; then",
|
||||
" if [ \"$mode\" = build-moonbridge ]; then",
|
||||
" action=build",
|
||||
" source_present_before=build-source",
|
||||
" tmpdir=$(mktemp -d /tmp/hwlab-node-runtime-image-$id.XXXXXX)",
|
||||
" dockerfile=\"$tmpdir/Dockerfile\"",
|
||||
" cat > \"$dockerfile\" <<'DOCKERFILE'",
|
||||
"ARG BUILDER_IMAGE",
|
||||
"FROM ${BUILDER_IMAGE} AS builder",
|
||||
"ARG MOONBRIDGE_REPO",
|
||||
"ARG MOONBRIDGE_REF",
|
||||
"ARG GOPROXY_VALUE",
|
||||
"ENV GOPROXY=${GOPROXY_VALUE}",
|
||||
"WORKDIR /src",
|
||||
"RUN git clone --filter=blob:none \"${MOONBRIDGE_REPO}\" moon-bridge",
|
||||
"WORKDIR /src/moon-bridge",
|
||||
"RUN git checkout \"${MOONBRIDGE_REF}\" \\",
|
||||
" && go mod download \\",
|
||||
" && CGO_ENABLED=0 GOOS=linux go build -trimpath -ldflags=\"-s -w\" -o /out/moonbridge ./cmd/moonbridge",
|
||||
"FROM scratch",
|
||||
"WORKDIR /app",
|
||||
"COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt",
|
||||
"COPY --from=builder /out/moonbridge /app/moonbridge",
|
||||
"EXPOSE 4001",
|
||||
"USER 65532:65532",
|
||||
"ENTRYPOINT [\"/app/moonbridge\"]",
|
||||
"DOCKERFILE",
|
||||
" if env HTTP_PROXY=\"$build_http_proxy\" HTTPS_PROXY=\"$build_https_proxy\" ALL_PROXY=\"$build_all_proxy\" NO_PROXY=\"$build_no_proxy\" http_proxy=\"$build_http_proxy\" https_proxy=\"$build_https_proxy\" all_proxy=\"$build_all_proxy\" no_proxy=\"$build_no_proxy\" docker build --network \"$docker_network_mode\" --build-arg BUILDER_IMAGE=\"$builder_image\" --build-arg MOONBRIDGE_REPO=\"$source_repo\" --build-arg MOONBRIDGE_REF=\"$source_ref\" --build-arg GOPROXY_VALUE=\"$go_proxy\" --build-arg HTTP_PROXY=\"$build_http_proxy\" --build-arg HTTPS_PROXY=\"$build_https_proxy\" --build-arg ALL_PROXY=\"$build_all_proxy\" --build-arg NO_PROXY=\"$build_no_proxy\" -t \"$target\" -f \"$dockerfile\" \"$tmpdir\" >/tmp/hwlab-node-runtime-image-$id-build.out 2>&1; then",
|
||||
" docker push \"$target\" >/tmp/hwlab-node-runtime-image-$id-push.out 2>&1 || { cat /tmp/hwlab-node-runtime-image-$id-push.out >&2 2>/dev/null || true; failed=true; }",
|
||||
" else",
|
||||
" cat /tmp/hwlab-node-runtime-image-$id-build.out >&2 2>/dev/null || true",
|
||||
" failed=true",
|
||||
" fi",
|
||||
" rm -rf \"$tmpdir\"",
|
||||
" else",
|
||||
" source_present_before=true",
|
||||
" if ! docker image inspect \"$source\" >/dev/null 2>&1; then",
|
||||
" source_present_before=false",
|
||||
" attempt=1",
|
||||
" while [ \"$attempt\" -le \"$pull_retries\" ]; do",
|
||||
" pull_attempts=$attempt",
|
||||
" if docker pull \"$source\" >/tmp/hwlab-node-runtime-image-$id-pull.out 2>&1; then pulled_source=true; break; fi",
|
||||
" if env HTTP_PROXY=\"$build_http_proxy\" HTTPS_PROXY=\"$build_https_proxy\" ALL_PROXY=\"$build_all_proxy\" NO_PROXY=\"$build_no_proxy\" http_proxy=\"$build_http_proxy\" https_proxy=\"$build_https_proxy\" all_proxy=\"$build_all_proxy\" no_proxy=\"$build_no_proxy\" docker pull \"$source\" >/tmp/hwlab-node-runtime-image-$id-pull.out 2>&1; then pulled_source=true; break; fi",
|
||||
" attempt=$((attempt + 1))",
|
||||
" sleep 2",
|
||||
" done",
|
||||
@@ -930,13 +1043,14 @@ export function ensureNodeBaseImage(spec: HwlabRuntimeLaneSpec, dryRun: boolean,
|
||||
" failed=true",
|
||||
" fi",
|
||||
" fi",
|
||||
" fi",
|
||||
" fi",
|
||||
" fi",
|
||||
" after=false",
|
||||
" if curl -fsS \"$registry_url\" 2>/dev/null | grep -q '\"'\"$tag\"'\"'; then after=true; fi",
|
||||
" python3 - \"$id\" \"$target\" \"$source\" \"$dry_run\" \"$present\" \"$after\" \"$action\" \"$pull_retries\" \"$source_present_before\" \"$pulled_source\" \"$pull_attempts\" <<'PY'",
|
||||
" python3 - \"$id\" \"$target\" \"$source\" \"$mode\" \"$dry_run\" \"$present\" \"$after\" \"$action\" \"$pull_retries\" \"$source_present_before\" \"$pulled_source\" \"$pull_attempts\" <<'PY'",
|
||||
"import json, sys",
|
||||
"keys=['id','target','source','dryRun','presentBefore','presentAfter','action','pullRetries','sourcePresentBefore','pulledSource','pullAttempts']",
|
||||
"keys=['id','target','source','mode','dryRun','presentBefore','presentAfter','action','pullRetries','sourcePresentBefore','pulledSource','pullAttempts']",
|
||||
"data=dict(zip(keys, sys.argv[1:]))",
|
||||
"for key in ['dryRun','presentBefore','presentAfter','pulledSource']:",
|
||||
" data[key] = data[key] == 'true'",
|
||||
@@ -949,7 +1063,10 @@ export function ensureNodeBaseImage(spec: HwlabRuntimeLaneSpec, dryRun: boolean,
|
||||
nodeRuntimeImageCalls(spec, "ensure_image"),
|
||||
"if [ \"$failed\" = true ]; then exit 1; fi",
|
||||
].join("\n");
|
||||
const result = runNodeHostScript(spec, script, Math.min(timeoutSeconds, 300));
|
||||
const hasBuild = nodeRuntimeImageDependencies(spec).some((image) => image.mode === "build-moonbridge");
|
||||
const result = hasBuild && !dryRun
|
||||
? runNodeHostScriptAsync(spec, script, Math.min(timeoutSeconds, 600), "runtime-image-build")
|
||||
: runNodeHostScript(spec, script, Math.min(timeoutSeconds, 300));
|
||||
const imageRows = parseNodeRuntimeImageRows(statusText(result));
|
||||
const base = imageRows.find((image) => image.id === "base") ?? {};
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user