146 lines
4.4 KiB
TypeScript
146 lines
4.4 KiB
TypeScript
// SPEC: PJ2026-01060307 控制面模块化 draft-2026-06-25-p0. bundle module for scripts/src/artifact-registry.ts.
|
|
|
|
// Moved mechanically from scripts/src/artifact-registry.ts:979-1080 for #903.
|
|
|
|
import { createHash } from "node:crypto";
|
|
import { existsSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
import { join } from "node:path";
|
|
import { runCommand, type CommandResult } from "../command";
|
|
import { readConfig, type UniDeskConfig, repoRoot, rootPath } from "../config";
|
|
import { startJob } from "../jobs";
|
|
import {
|
|
compareDeployJsonExecutorMirrors,
|
|
deployJsonCommitImage,
|
|
deployJsonDriftResult,
|
|
deployJsonSourceOfTruth,
|
|
hasDeployJsonExecutorContract,
|
|
k3sManifestExecutorMirror,
|
|
parseDeployJsonServiceContractBase64,
|
|
readDeployJsonServiceContractFromFile,
|
|
type DeployJsonExecutorMirror,
|
|
type DeployJsonServiceContract,
|
|
} from "../deploy-json-contract";
|
|
import { d601K3sGuardShellLines } from "../d601-k3s-guard";
|
|
import { composeRuntimeEnvValue } from "../runtime-env";
|
|
|
|
import type { ArtifactRegistryOptions, RenderedBundle, RenderedFile } from "./types";
|
|
|
|
export function sha256(text: string): string {
|
|
return createHash("sha256").update(text).digest("hex");
|
|
}
|
|
|
|
export function shellQuote(value: string): string {
|
|
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
}
|
|
|
|
export function d601K3sGuardScript(): string {
|
|
return d601K3sGuardShellLines().join("\n");
|
|
}
|
|
|
|
export function base64(value: string): string {
|
|
return Buffer.from(value, "utf8").toString("base64");
|
|
}
|
|
|
|
export function safeName(value: string): string {
|
|
return value.replace(/[^A-Za-z0-9_.-]/gu, "-");
|
|
}
|
|
|
|
export function rootExecPrelude(): string {
|
|
return [
|
|
"root_exec() {",
|
|
" if [ \"$(id -u)\" = \"0\" ]; then \"$@\"; return; fi",
|
|
" if sudo -n true >/dev/null 2>&1; then sudo -n \"$@\"; return; fi",
|
|
" if [ -x /mnt/c/Windows/System32/wsl.exe ]; then /mnt/c/Windows/System32/wsl.exe -u root -- \"$@\"; return; fi",
|
|
" echo 'artifact_registry_root_access=missing' >&2",
|
|
" return 1",
|
|
"}",
|
|
].join("\n");
|
|
}
|
|
|
|
export function file(path: string, content: string, mode = "0644"): RenderedFile {
|
|
return { path, mode, sha256: sha256(content), content };
|
|
}
|
|
|
|
export function registryConfig(): string {
|
|
return `version: 0.1
|
|
log:
|
|
fields:
|
|
service: unidesk-artifact-registry
|
|
storage:
|
|
filesystem:
|
|
rootdirectory: /var/lib/registry
|
|
delete:
|
|
enabled: false
|
|
http:
|
|
addr: :5000
|
|
headers:
|
|
X-Content-Type-Options: [nosniff]
|
|
health:
|
|
storagedriver:
|
|
enabled: true
|
|
interval: 10s
|
|
threshold: 3
|
|
`;
|
|
}
|
|
|
|
export function composeFile(options: ArtifactRegistryOptions): string {
|
|
return `name: ${options.composeProject}
|
|
services:
|
|
${options.serviceName}:
|
|
image: ${options.image}
|
|
container_name: ${options.containerName}
|
|
restart: unless-stopped
|
|
ports:
|
|
- "${options.host}:${options.port}:5000"
|
|
volumes:
|
|
- "${options.baseDir}/config.yml:/etc/docker/registry/config.yml:ro"
|
|
- "${options.storageDir}:/var/lib/registry"
|
|
labels:
|
|
unidesk.ai/service-id: artifact-registry
|
|
unidesk.ai/managed-by: host-systemd-docker-compose
|
|
unidesk.ai/provider-id: ${options.providerId}
|
|
`;
|
|
}
|
|
|
|
export function systemdUnit(options: ArtifactRegistryOptions): string {
|
|
return `[Unit]
|
|
Description=UniDesk D601 Artifact Registry (CNCF Distribution)
|
|
Documentation=https://github.com/pikasTech/unidesk/blob/master/docs/reference/artifact-registry.md
|
|
After=network-online.target
|
|
Wants=network-online.target
|
|
ConditionPathExists=/var/run/docker.sock
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
RemainAfterExit=yes
|
|
WorkingDirectory=${options.baseDir}
|
|
ExecStartPre=/bin/mkdir -p ${options.baseDir} ${options.storageDir}
|
|
ExecStartPre=/bin/sh -lc 'docker info >/dev/null'
|
|
ExecStart=/bin/sh -lc 'docker compose -p ${options.composeProject} -f ${options.baseDir}/compose.yml up -d --remove-orphans'
|
|
ExecStop=/bin/sh -lc 'docker compose -p ${options.composeProject} -f ${options.baseDir}/compose.yml down'
|
|
TimeoutStartSec=120
|
|
TimeoutStopSec=120
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
`;
|
|
}
|
|
|
|
export function renderBundle(options: ArtifactRegistryOptions): RenderedBundle {
|
|
const paths = {
|
|
unit: `/etc/systemd/system/${options.unitName}`,
|
|
compose: `${options.baseDir}/compose.yml`,
|
|
config: `${options.baseDir}/config.yml`,
|
|
storage: options.storageDir,
|
|
baseDir: options.baseDir,
|
|
};
|
|
return {
|
|
paths,
|
|
files: [
|
|
file(paths.config, registryConfig()),
|
|
file(paths.compose, composeFile(options)),
|
|
file(paths.unit, systemdUnit(options)),
|
|
],
|
|
};
|
|
}
|