diff --git a/scripts/src/hwlab-node-web-sentinel-cicd.ts b/scripts/src/hwlab-node-web-sentinel-cicd.ts index c4aeb367..106824e1 100644 --- a/scripts/src/hwlab-node-web-sentinel-cicd.ts +++ b/scripts/src/hwlab-node-web-sentinel-cicd.ts @@ -834,19 +834,28 @@ function probeImageRegistry(state: SentinelCicdState, timeoutSeconds: number): R const repoTag = state.image.ref.replace(`${endpoint}/`, ""); const repo = repoTag.slice(0, repoTag.lastIndexOf(":")); const tag = repoTag.slice(repoTag.lastIndexOf(":") + 1); - const route = stringAt(state.controlPlaneNode, "route"); + const registryMode = stringAtNullable(state.controlPlaneNode, "registry.mode") ?? "host-docker"; + const endpointIsLoopback = endpoint === "127.0.0.1:5000" || endpoint.startsWith("127.0.0.1:"); + const probeMode = registryMode === "k8s-workload" && !endpointIsLoopback ? "k8s-service" : "node-loopback"; + const url = probeMode === "k8s-service" + ? `http://${stringAt(state.controlPlaneNode, "registry.serviceName")}.${stringAt(state.controlPlaneNode, "registry.namespace")}.svc.cluster.local:${numberAtNullable(state.controlPlaneNode, "registry.containerPort") ?? 5000}/v2/${repo}/manifests/${tag}` + : `http://${endpoint}/v2/${repo}/manifests/${tag}`; const script = [ "set +e", - `url=${shellQuote(`http://${endpoint}/v2/${repo}/manifests/${tag}`)}`, + `url=${shellQuote(url)}`, + `probe_mode=${shellQuote(probeMode)}`, "headers=$(mktemp)", - "if command -v curl >/dev/null 2>&1 && curl -fsSI --max-time 5 \"$url\" >\"$headers\" 2>/tmp/web-probe-sentinel-image.err; then present=true; else present=false; fi", + "accept='application/vnd.oci.image.manifest.v1+json, application/vnd.oci.image.index.v1+json, application/vnd.docker.distribution.manifest.v2+json, application/vnd.docker.distribution.manifest.list.v2+json'", + "if command -v curl >/dev/null 2>&1 && curl -fsSI -H \"Accept: $accept\" --max-time 5 \"$url\" >\"$headers\" 2>/tmp/web-probe-sentinel-image.err; then present=true; else present=false; fi", "digest=$(awk 'BEGIN{IGNORECASE=1} /^docker-content-digest:/ {gsub(/\\r/,\"\",$2); print $2; exit}' \"$headers\" 2>/dev/null)", - "python3 - \"$present\" \"$digest\" \"$url\" <<'PY'", + "python3 - \"$present\" \"$digest\" \"$url\" \"$probe_mode\" <<'PY'", "import json, sys", - "print(json.dumps({'present': sys.argv[1] == 'true', 'digest': sys.argv[2] or None, 'url': sys.argv[3], 'valuesRedacted': True}))", + "print(json.dumps({'present': sys.argv[1] == 'true', 'digest': sys.argv[2] or None, 'url': sys.argv[3], 'mode': sys.argv[4], 'valuesRedacted': True}))", "PY", ].join("\n"); - const result = runCommand(["trans", route, "sh", "--", script], repoRoot, { timeoutMs: Math.min(timeoutSeconds, 60) * 1000 }); + const result = probeMode === "k8s-service" + ? runCommand(["trans", stringAt(state.controlPlaneNode, "kubeRoute"), "kubectl", "-n", stringAt(state.cicd, "builder.namespace"), "exec", "deploy/git-mirror-http", "--", "sh", "-lc", script], repoRoot, { timeoutMs: Math.min(timeoutSeconds, 60) * 1000 }) + : runCommand(["trans", stringAt(state.controlPlaneNode, "route"), "sh", "--", script], repoRoot, { timeoutMs: Math.min(timeoutSeconds, 60) * 1000 }); return { ok: result.exitCode === 0, probe: parseJsonObject(result.stdout), @@ -1345,7 +1354,7 @@ function sentinelSourceMirrorSyncJobManifest(state: SentinelCicdState, jobName: spec: { restartPolicy: "Never", volumes: [ - { name: "cache", hostPath: { path: stringAt(state.controlPlaneTarget, "gitMirror.cacheHostPath"), type: "DirectoryOrCreate" } }, + sentinelGitMirrorCacheVolume(state), { name: "git-ssh", secret: { secretName: stringAt(state.cicd, "builder.gitSshSecretName"), defaultMode: 256 } }, ], containers: [{ @@ -1607,7 +1616,7 @@ function sentinelPublishJobManifest(state: SentinelCicdState, jobName: string, p spec: { restartPolicy: "Never", volumes: [ - { name: "cache", hostPath: { path: stringAt(state.controlPlaneTarget, "gitMirror.cacheHostPath"), type: "DirectoryOrCreate" } }, + sentinelGitMirrorCacheVolume(state), { name: "git-ssh", secret: { secretName: stringAt(state.cicd, "builder.gitSshSecretName"), defaultMode: 256 } }, { name: "docker-sock", hostPath: { path: stringAt(state.cicd, "builder.dockerSocketPath"), type: "Socket" } }, ], @@ -1628,6 +1637,12 @@ function sentinelPublishJobManifest(state: SentinelCicdState, jobName: string, p }; } +function sentinelGitMirrorCacheVolume(state: SentinelCicdState): Record { + const hostPath = nonEmptyString(valueAtPath(state.controlPlaneTarget, "gitMirror.cacheHostPath")); + if (hostPath !== null) return { name: "cache", hostPath: { path: hostPath, type: "DirectoryOrCreate" } }; + return { name: "cache", persistentVolumeClaim: { claimName: stringAt(state.controlPlaneTarget, "gitMirror.cachePvcName") } }; +} + function sentinelPublishShell(state: SentinelCicdState, jobName: string, publishGitops: boolean): string { const gitopsFiles = publishGitops ? sentinelGitopsFiles(state) : []; const filesB64 = Buffer.from(JSON.stringify(gitopsFiles.map((file) => ({