refactor: split control-plane cli modules
This commit is contained in:
@@ -0,0 +1,145 @@
|
||||
// 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)),
|
||||
],
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user