deploy: configure NC01 HWLAB monitor exposure
This commit is contained in:
@@ -45,6 +45,7 @@ export function parseSecretSyncOptions(args: string[]): SecretSyncOptions {
|
||||
const base = parseConfirmOptions(args);
|
||||
let node: string | null = null;
|
||||
let lane: string | null = null;
|
||||
const secretIds: string[] = [];
|
||||
for (let index = 0; index < args.length; index += 1) {
|
||||
const arg = args[index];
|
||||
if (arg === "--confirm" || arg === "--dry-run") continue;
|
||||
@@ -62,9 +63,17 @@ export function parseSecretSyncOptions(args: string[]): SecretSyncOptions {
|
||||
index += 1;
|
||||
continue;
|
||||
}
|
||||
if (arg === "--secret-id") {
|
||||
const value = args[index + 1];
|
||||
if (value === undefined || value.startsWith("--")) throw new Error("--secret-id requires a value");
|
||||
if (!/^[A-Za-z0-9._-]+$/u.test(value)) throw new Error("--secret-id must be a simple YAML secret id");
|
||||
if (!secretIds.includes(value)) secretIds.push(value);
|
||||
index += 1;
|
||||
continue;
|
||||
}
|
||||
throw new Error(`unsupported secret-sync option: ${arg}`);
|
||||
}
|
||||
return { ...base, node, lane };
|
||||
return { ...base, node, lane, secretIds };
|
||||
}
|
||||
|
||||
export function parseLaneConfirmOptions(args: string[]): LaneConfirmOptions {
|
||||
|
||||
@@ -71,6 +71,7 @@ export function agentRunHelp(): unknown {
|
||||
"bun scripts/cli.ts agentrun control-plane status --node D601 --lane v02",
|
||||
"bun scripts/cli.ts agentrun control-plane secret-sync --node D601 --lane v02 --dry-run",
|
||||
"bun scripts/cli.ts agentrun control-plane secret-sync --node D601 --lane v02 --confirm",
|
||||
"bun scripts/cli.ts agentrun control-plane secret-sync --node D601 --lane v02 --secret-id tool-github-pr-token --confirm",
|
||||
"bun scripts/cli.ts agentrun control-plane restart --node D601 --lane v02 --dry-run",
|
||||
"bun scripts/cli.ts agentrun control-plane restart --node D601 --lane v02 --confirm",
|
||||
"bun scripts/cli.ts agentrun control-plane trigger-current --node D601 --lane v02 --dry-run",
|
||||
|
||||
@@ -219,6 +219,7 @@ export interface ConfirmOptions {
|
||||
export interface SecretSyncOptions extends ConfirmOptions {
|
||||
node: string | null;
|
||||
lane: string | null;
|
||||
secretIds: string[];
|
||||
}
|
||||
|
||||
export interface LaneConfirmOptions extends ConfirmOptions {
|
||||
|
||||
@@ -350,6 +350,7 @@ export function yamlLanePipelineRunManifest(spec: AgentRunLaneSpec, sourceCommit
|
||||
{ name: "source-branch", value: spec.source.branch },
|
||||
{ name: "gitops-branch", value: spec.gitops.branch },
|
||||
{ name: "revision", value: sourceCommit },
|
||||
...(sourceStageRef === null ? [] : [{ name: "source-stage-ref", value: sourceStageRef }]),
|
||||
{ name: "registry-prefix", value: spec.ci.registryPrefix },
|
||||
{ name: "tools-image", value: spec.ci.toolsImage },
|
||||
],
|
||||
@@ -476,6 +477,7 @@ export function yamlLaneGitMirrorSshSetupShellLines(spec: AgentRunLaneSpec): str
|
||||
const proxyHost = spec.gitMirror.githubProxy.host;
|
||||
const proxyPort = spec.gitMirror.githubProxy.port;
|
||||
const proxyUrl = `http://${proxyHost}:${proxyPort}`;
|
||||
const noProxy = "localhost,127.0.0.1,::1,.svc,.svc.cluster.local,.cluster.local,10.0.0.0/8,10.42.0.0/16,10.43.0.0/16,hyueapi.com,.hyueapi.com";
|
||||
const proxySummary = `agentrun git-mirror-egress-proxy node=${spec.nodeId} lane=${spec.lane} host=${proxyHost} port=${proxyPort} ssh=GIT_SSH-wrapper source=yaml`;
|
||||
const proxyCommand = `ProxyCommand=node /tmp/agentrun-github-proxy-connect.cjs ${proxyHost} ${proxyPort} %h %p`;
|
||||
return [
|
||||
@@ -545,6 +547,8 @@ export function yamlLaneGitMirrorSshSetupShellLines(spec: AgentRunLaneSpec): str
|
||||
`export http_proxy=${shQuote(proxyUrl)}`,
|
||||
`export https_proxy=${shQuote(proxyUrl)}`,
|
||||
`export all_proxy=${shQuote(proxyUrl)}`,
|
||||
`export NO_PROXY=${shQuote(noProxy)}`,
|
||||
`export no_proxy=${shQuote(noProxy)}`,
|
||||
"export GIT_SSH=/tmp/agentrun-git-ssh-proxy.sh",
|
||||
"unset GIT_SSH_COMMAND",
|
||||
];
|
||||
@@ -558,8 +562,8 @@ export function yamlLaneGitMirrorSyncShell(spec: AgentRunLaneSpec): string {
|
||||
`source_branch=${shQuote(spec.source.branch)}`,
|
||||
`source_stage_ref_prefix=${shQuote(agentRunSourceSnapshotStageRefPrefix(spec))}`,
|
||||
`gitops_branch=${shQuote(spec.gitops.branch)}`,
|
||||
`remote=${shQuote(spec.source.remote)}`,
|
||||
"repo=\"/cache/${repository}.git\"",
|
||||
"remote=\"ssh://git@ssh.github.com:443/${repository}.git\"",
|
||||
"mkdir -p \"$(dirname \"$repo\")\"",
|
||||
"if [ -d \"$repo/objects\" ] && [ -f \"$repo/HEAD\" ]; then",
|
||||
" git --git-dir=\"$repo\" remote set-url origin \"$remote\" || git --git-dir=\"$repo\" remote add origin \"$remote\"",
|
||||
@@ -606,8 +610,8 @@ export function yamlLaneGitMirrorFlushShell(spec: AgentRunLaneSpec): string {
|
||||
...yamlLaneGitMirrorSshSetupShellLines(spec),
|
||||
`repository=${shQuote(spec.source.repository)}`,
|
||||
`gitops_branch=${shQuote(spec.gitops.branch)}`,
|
||||
`remote=${shQuote(spec.gitMirror.writeUrl)}`,
|
||||
"repo=\"/cache/${repository}.git\"",
|
||||
"remote=\"ssh://git@ssh.github.com:443/${repository}.git\"",
|
||||
"test -d \"$repo\"",
|
||||
"git --git-dir=\"$repo\" remote set-url origin \"$remote\" || git --git-dir=\"$repo\" remote add origin \"$remote\"",
|
||||
"local_gitops=$(git --git-dir=\"$repo\" rev-parse --verify \"refs/heads/${gitops_branch}^{commit}\" 2>/dev/null || true)",
|
||||
@@ -703,6 +707,7 @@ export type LaneSecretSource = {
|
||||
sourceRef: string;
|
||||
sourceMode: "env" | "file";
|
||||
sourceKey: string | null;
|
||||
sourceFormat?: "env" | "raw-token" | null;
|
||||
targetRef: { namespace: string; name: string; key: string };
|
||||
transform?: "local-postgres-database" | "local-postgres-user" | "local-postgres-database-url";
|
||||
};
|
||||
@@ -719,8 +724,8 @@ export function readSecretSourceValue(spec: AgentRunLaneSpec, source: LaneSecret
|
||||
value = readFileSync(sourcePath, "utf8");
|
||||
} else {
|
||||
if (source.sourceKey === null) throw new Error(`secret source ${sourceRef} is missing sourceKey`);
|
||||
const values = parseEnvFile(readFileSync(sourcePath, "utf8"));
|
||||
const envValue = values.get(source.sourceKey);
|
||||
const text = readFileSync(sourcePath, "utf8");
|
||||
const envValue = source.sourceFormat === "raw-token" ? text.trim() : parseEnvFile(text).get(source.sourceKey);
|
||||
if (envValue === undefined || envValue.length === 0) throw new Error(`secret source ${sourceRef} is missing required key ${source.sourceKey}`);
|
||||
value = envValue;
|
||||
}
|
||||
@@ -837,6 +842,7 @@ export function collectLaneSecretSources(spec: AgentRunLaneSpec): LaneSecretSour
|
||||
sourceRef: secret.sourceRef,
|
||||
sourceMode: secret.sourceMode,
|
||||
sourceKey: secret.sourceKey,
|
||||
sourceFormat: secret.sourceFormat,
|
||||
targetRef: secret.targetRef,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -178,15 +178,19 @@ export async function restartYamlLane(config: UniDeskConfig, options: LaneConfir
|
||||
|
||||
export async function secretSync(config: UniDeskConfig, options: SecretSyncOptions): Promise<Record<string, unknown>> {
|
||||
const { configPath, spec } = resolveAgentRunLaneTarget(options);
|
||||
const sources = collectLaneSecretSources(spec);
|
||||
const allSources = collectLaneSecretSources(spec);
|
||||
const selectedIds = new Set(options.secretIds);
|
||||
const sources = selectedIds.size === 0 ? allSources : allSources.filter((source) => selectedIds.has(source.id));
|
||||
if (sources.length === 0) {
|
||||
return {
|
||||
ok: false,
|
||||
command: "agentrun control-plane secret-sync",
|
||||
mode: "yaml-declared-node-lane",
|
||||
configPath,
|
||||
target: agentRunLaneSummary(spec),
|
||||
target: compactAgentRunLaneStatusTarget(spec),
|
||||
degradedReason: "lane-secret-sources-not-declared",
|
||||
requestedSecretIds: options.secretIds,
|
||||
declaredSecretIds: allSources.map((source) => source.id),
|
||||
valuesPrinted: false,
|
||||
};
|
||||
}
|
||||
@@ -211,10 +215,11 @@ export async function secretSync(config: UniDeskConfig, options: SecretSyncOptio
|
||||
mode: "dry-run",
|
||||
mutation: false,
|
||||
configPath,
|
||||
target: agentRunLaneSummary(spec),
|
||||
target: compactAgentRunLaneStatusTarget(spec),
|
||||
filter: options.secretIds.length === 0 ? null : { secretIds: options.secretIds, selected: sources.map((source) => source.id) },
|
||||
plan: { secretCount: plan.length, items: plan, valuesPrinted: false },
|
||||
next: {
|
||||
confirm: `bun scripts/cli.ts agentrun control-plane secret-sync --node ${spec.nodeId} --lane ${spec.lane} --confirm`,
|
||||
confirm: `bun scripts/cli.ts agentrun control-plane secret-sync --node ${spec.nodeId} --lane ${spec.lane}${options.secretIds.map((id) => ` --secret-id ${id}`).join("")} --confirm`,
|
||||
status: `bun scripts/cli.ts agentrun control-plane status --node ${spec.nodeId} --lane ${spec.lane}`,
|
||||
},
|
||||
valuesPrinted: false,
|
||||
@@ -228,7 +233,8 @@ export async function secretSync(config: UniDeskConfig, options: SecretSyncOptio
|
||||
mode: "confirmed-sync",
|
||||
mutation: true,
|
||||
configPath,
|
||||
target: agentRunLaneSummary(spec),
|
||||
target: compactAgentRunLaneStatusTarget(spec),
|
||||
filter: options.secretIds.length === 0 ? null : { secretIds: options.secretIds, selected: sources.map((source) => source.id) },
|
||||
plan: { secretCount: plan.length, items: plan, valuesPrinted: false },
|
||||
result: payload,
|
||||
capture: compactCapture(result, { full: result.exitCode !== 0, stdoutTailChars: 3000, stderrTailChars: 3000 }),
|
||||
|
||||
@@ -128,22 +128,9 @@ export type AgentRunBridgeCaptureResult = SshCaptureResult & { bridgeExecution?:
|
||||
export let localBackendCoreStatusCache: LocalBackendCoreStatus | null = null;
|
||||
|
||||
export async function capture(config: UniDeskConfig, target: string, args: string[]): Promise<AgentRunBridgeCaptureResult> {
|
||||
const result = await runSshCommandCapture(config, target, args);
|
||||
const plan = agentRunBridgeCapturePlan(config, target);
|
||||
if (plan.backend === "remote-frontend-websocket" && plan.remoteHost !== null) {
|
||||
return await captureRemote(config, plan, target, args);
|
||||
}
|
||||
const local = attachBridgeExecution(await runSshCommandCapture(config, target, args), plan);
|
||||
const fallbackHost = agentRunBridgeRemoteHost(config);
|
||||
if (local.exitCode !== 0 && fallbackHost !== null && bridgeExecutionFailureKind(local)?.degradedReason === "capture-backend-unavailable") {
|
||||
const fallbackPlan: AgentRunBridgeCapturePlan = {
|
||||
...plan,
|
||||
backend: "remote-frontend-websocket",
|
||||
remoteHost: fallbackHost,
|
||||
reason: "local-capture-backend-unavailable",
|
||||
};
|
||||
return await captureRemote(config, fallbackPlan, target, args);
|
||||
}
|
||||
return local;
|
||||
return attachBridgeExecution(result, { ...plan, reason: `unified-ssh-capture:${plan.reason}` });
|
||||
}
|
||||
|
||||
export async function captureRemote(config: UniDeskConfig, plan: AgentRunBridgeCapturePlan, target: string, args: string[]): Promise<AgentRunBridgeCaptureResult> {
|
||||
|
||||
@@ -1242,15 +1242,18 @@ function yamlLaneK3sBuildProxyEnv(spec: AgentRunLaneSpec): Array<{ name: string;
|
||||
}
|
||||
|
||||
function yamlLaneK3sBuildSourceShell(spec: AgentRunLaneSpec, sourceCommit: string): string {
|
||||
const useDirectSourceRemote = spec.source.remote.startsWith("http://gitea-http.") || spec.source.remote.startsWith("https://gitea.");
|
||||
const readUrl = useDirectSourceRemote ? spec.source.remote : spec.gitMirror.readUrl;
|
||||
return [
|
||||
"set -eu",
|
||||
`read_url=${shQuote(spec.gitMirror.readUrl)}`,
|
||||
`read_url=${shQuote(readUrl)}`,
|
||||
`source_commit=${shQuote(sourceCommit)}`,
|
||||
`source_stage_ref=${shQuote(agentRunSourceSnapshotRef(spec, sourceCommit))}`,
|
||||
`use_direct_source_remote=${useDirectSourceRemote ? "true" : "false"}`,
|
||||
"rm -rf /workspace/repo",
|
||||
"git clone --no-checkout \"$read_url\" /workspace/repo",
|
||||
"cd /workspace/repo",
|
||||
"git fetch origin \"+$source_stage_ref:refs/remotes/origin/unidesk-source-snapshot\"",
|
||||
"if [ \"$use_direct_source_remote\" != true ]; then git fetch origin \"+$source_stage_ref:refs/remotes/origin/unidesk-source-snapshot\"; fi",
|
||||
"git checkout --detach \"$source_commit\"",
|
||||
"actual=$(git rev-parse HEAD)",
|
||||
"test \"$actual\" = \"$source_commit\"",
|
||||
|
||||
Reference in New Issue
Block a user