refactor: split control-plane cli modules
This commit is contained in:
@@ -0,0 +1,320 @@
|
||||
// SPEC: PJ2026-01060307 控制面模块化 draft-2026-06-25-p0. trace-script module for scripts/src/platform-infra-observability.ts.
|
||||
|
||||
// Moved mechanically from scripts/src/platform-infra-observability.ts:1575-1813 for #903.
|
||||
|
||||
// SPEC: PJ2026-01060501 OTel追踪 draft-2026-06-19-p0.
|
||||
// Responsibility: YAML-first platform-infra OpenTelemetry tracing control commands.
|
||||
import { Buffer } from "node:buffer";
|
||||
import { readFileSync } from "node:fs";
|
||||
import type { UniDeskConfig } from "../config";
|
||||
import { rootPath } from "../config";
|
||||
import type { RenderedCliResult } from "../output";
|
||||
import {
|
||||
compactCapture,
|
||||
createYamlFieldReader,
|
||||
numberField,
|
||||
parseJsonOutput,
|
||||
redactSensitiveUnknown,
|
||||
shQuote,
|
||||
capture,
|
||||
} from "../platform-infra-ops-library";
|
||||
|
||||
import type { ObservabilityConfig, ObservabilityTarget } from "./types";
|
||||
import { tempoService } from "./search-script";
|
||||
import { imageReference, indent } from "./summary";
|
||||
|
||||
export function asArray(value: unknown): unknown[] {
|
||||
return Array.isArray(value) ? value : [];
|
||||
}
|
||||
|
||||
export function limitArray(value: unknown, limit: number): unknown[] {
|
||||
return asArray(value).slice(0, limit);
|
||||
}
|
||||
|
||||
export function renderManifest(observability: ObservabilityConfig, target: ObservabilityTarget): string {
|
||||
const collectorImage = imageReference(observability.images.collector);
|
||||
const tempoImage = imageReference(observability.images.tempo);
|
||||
return [
|
||||
target.createNamespace ? namespaceManifest(target) : "",
|
||||
allowAllNetworkPolicy(target),
|
||||
collectorConfigMap(observability, target),
|
||||
collectorDeployment(observability, target, collectorImage),
|
||||
collectorService(observability, target),
|
||||
tempoConfigMap(observability, target),
|
||||
tempoDeployment(observability, target, tempoImage),
|
||||
tempoService(observability, target),
|
||||
].filter((item) => item.trim().length > 0).join("\n---\n");
|
||||
}
|
||||
|
||||
export function namespaceManifest(target: ObservabilityTarget): string {
|
||||
return `apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: ${target.namespace}
|
||||
labels:
|
||||
app.kubernetes.io/part-of: platform-infra
|
||||
app.kubernetes.io/managed-by: unidesk
|
||||
unidesk.ai/runtime-node: ${target.id}
|
||||
`;
|
||||
}
|
||||
|
||||
export function allowAllNetworkPolicy(target: ObservabilityTarget): string {
|
||||
return `apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: allow-all
|
||||
namespace: ${target.namespace}
|
||||
labels:
|
||||
app.kubernetes.io/part-of: platform-infra
|
||||
app.kubernetes.io/managed-by: unidesk
|
||||
spec:
|
||||
podSelector: {}
|
||||
policyTypes:
|
||||
- Ingress
|
||||
- Egress
|
||||
ingress:
|
||||
- {}
|
||||
egress:
|
||||
- {}
|
||||
`;
|
||||
}
|
||||
|
||||
export function collectorConfigMap(observability: ObservabilityConfig, target: ObservabilityTarget): string {
|
||||
const config = `receivers:
|
||||
otlp:
|
||||
protocols:
|
||||
grpc:
|
||||
endpoint: 0.0.0.0:${observability.collector.otlp.grpcPort}
|
||||
http:
|
||||
endpoint: 0.0.0.0:${observability.collector.otlp.httpPort}
|
||||
processors:
|
||||
batch: {}
|
||||
exporters:
|
||||
otlp/tempo:
|
||||
endpoint: ${observability.traceBackend.serviceName}.${target.namespace}.svc.cluster.local:${observability.traceBackend.otlp.grpcPort}
|
||||
tls:
|
||||
insecure: true
|
||||
extensions:
|
||||
health_check:
|
||||
endpoint: 0.0.0.0:${observability.collector.healthPort}
|
||||
service:
|
||||
extensions: [health_check]
|
||||
pipelines:
|
||||
traces:
|
||||
receivers: [otlp]
|
||||
processors: [batch]
|
||||
exporters: [otlp/tempo]
|
||||
`;
|
||||
return `apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: ${observability.collector.configMapName}
|
||||
namespace: ${target.namespace}
|
||||
labels:
|
||||
app.kubernetes.io/name: ${observability.collector.deploymentName}
|
||||
app.kubernetes.io/component: tracing
|
||||
app.kubernetes.io/part-of: platform-infra
|
||||
app.kubernetes.io/managed-by: unidesk
|
||||
annotations:
|
||||
unidesk.ai/spec: "${observability.metadata.spec}"
|
||||
data:
|
||||
collector.yaml: |
|
||||
${indent(config, 4)}
|
||||
`;
|
||||
}
|
||||
|
||||
export function collectorDeployment(observability: ObservabilityConfig, target: ObservabilityTarget, image: string): string {
|
||||
return `apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: ${observability.collector.deploymentName}
|
||||
namespace: ${target.namespace}
|
||||
labels:
|
||||
app.kubernetes.io/name: ${observability.collector.deploymentName}
|
||||
app.kubernetes.io/component: tracing
|
||||
app.kubernetes.io/part-of: platform-infra
|
||||
app.kubernetes.io/managed-by: unidesk
|
||||
spec:
|
||||
replicas: ${observability.collector.replicas}
|
||||
strategy:
|
||||
type: RollingUpdate
|
||||
rollingUpdate:
|
||||
maxSurge: 0
|
||||
maxUnavailable: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: ${observability.collector.deploymentName}
|
||||
app.kubernetes.io/component: tracing
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/name: ${observability.collector.deploymentName}
|
||||
app.kubernetes.io/component: tracing
|
||||
app.kubernetes.io/part-of: platform-infra
|
||||
annotations:
|
||||
unidesk.ai/spec: "${observability.metadata.spec}"
|
||||
spec:
|
||||
containers:
|
||||
- name: collector
|
||||
image: ${image}
|
||||
imagePullPolicy: ${observability.images.collector.pullPolicy}
|
||||
args:
|
||||
- --config=/etc/otelcol/collector.yaml
|
||||
ports:
|
||||
- name: otlp-grpc
|
||||
containerPort: ${observability.collector.otlp.grpcPort}
|
||||
- name: otlp-http
|
||||
containerPort: ${observability.collector.otlp.httpPort}
|
||||
- name: health
|
||||
containerPort: ${observability.collector.healthPort}
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: health
|
||||
volumeMounts:
|
||||
- name: config
|
||||
mountPath: /etc/otelcol/collector.yaml
|
||||
subPath: collector.yaml
|
||||
readOnly: true
|
||||
volumes:
|
||||
- name: config
|
||||
configMap:
|
||||
name: ${observability.collector.configMapName}
|
||||
`;
|
||||
}
|
||||
|
||||
export function collectorService(observability: ObservabilityConfig, target: ObservabilityTarget): string {
|
||||
return `apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: ${observability.collector.serviceName}
|
||||
namespace: ${target.namespace}
|
||||
labels:
|
||||
app.kubernetes.io/name: ${observability.collector.deploymentName}
|
||||
app.kubernetes.io/component: tracing
|
||||
app.kubernetes.io/part-of: platform-infra
|
||||
app.kubernetes.io/managed-by: unidesk
|
||||
spec:
|
||||
type: ClusterIP
|
||||
selector:
|
||||
app.kubernetes.io/name: ${observability.collector.deploymentName}
|
||||
app.kubernetes.io/component: tracing
|
||||
ports:
|
||||
- name: otlp-grpc
|
||||
port: ${observability.collector.otlp.grpcPort}
|
||||
targetPort: otlp-grpc
|
||||
- name: otlp-http
|
||||
port: ${observability.collector.otlp.httpPort}
|
||||
targetPort: otlp-http
|
||||
- name: health
|
||||
port: ${observability.collector.healthPort}
|
||||
targetPort: health
|
||||
`;
|
||||
}
|
||||
|
||||
export function tempoConfigMap(observability: ObservabilityConfig, _target: ObservabilityTarget): string {
|
||||
const config = `server:
|
||||
http_listen_port: ${observability.traceBackend.httpPort}
|
||||
distributor:
|
||||
receivers:
|
||||
otlp:
|
||||
protocols:
|
||||
grpc:
|
||||
endpoint: 0.0.0.0:${observability.traceBackend.otlp.grpcPort}
|
||||
http:
|
||||
endpoint: 0.0.0.0:${observability.traceBackend.otlp.httpPort}
|
||||
ingester:
|
||||
trace_idle_period: 10s
|
||||
max_block_duration: 5m
|
||||
compactor:
|
||||
compaction:
|
||||
block_retention: ${observability.traceBackend.storage.retention}
|
||||
storage:
|
||||
trace:
|
||||
backend: local
|
||||
wal:
|
||||
path: /var/tempo/wal
|
||||
local:
|
||||
path: /var/tempo/traces
|
||||
`;
|
||||
return `apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: ${observability.traceBackend.configMapName}
|
||||
namespace: ${_target.namespace}
|
||||
labels:
|
||||
app.kubernetes.io/name: ${observability.traceBackend.deploymentName}
|
||||
app.kubernetes.io/component: trace-backend
|
||||
app.kubernetes.io/part-of: platform-infra
|
||||
app.kubernetes.io/managed-by: unidesk
|
||||
annotations:
|
||||
unidesk.ai/spec: "${observability.metadata.spec}"
|
||||
data:
|
||||
tempo.yaml: |
|
||||
${indent(config, 4)}
|
||||
`;
|
||||
}
|
||||
|
||||
export function tempoDeployment(observability: ObservabilityConfig, target: ObservabilityTarget, image: string): string {
|
||||
return `apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: ${observability.traceBackend.deploymentName}
|
||||
namespace: ${target.namespace}
|
||||
labels:
|
||||
app.kubernetes.io/name: ${observability.traceBackend.deploymentName}
|
||||
app.kubernetes.io/component: trace-backend
|
||||
app.kubernetes.io/part-of: platform-infra
|
||||
app.kubernetes.io/managed-by: unidesk
|
||||
spec:
|
||||
replicas: ${observability.traceBackend.replicas}
|
||||
strategy:
|
||||
type: RollingUpdate
|
||||
rollingUpdate:
|
||||
maxSurge: 0
|
||||
maxUnavailable: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: ${observability.traceBackend.deploymentName}
|
||||
app.kubernetes.io/component: trace-backend
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/name: ${observability.traceBackend.deploymentName}
|
||||
app.kubernetes.io/component: trace-backend
|
||||
app.kubernetes.io/part-of: platform-infra
|
||||
annotations:
|
||||
unidesk.ai/spec: "${observability.metadata.spec}"
|
||||
spec:
|
||||
containers:
|
||||
- name: tempo
|
||||
image: ${image}
|
||||
imagePullPolicy: ${observability.images.tempo.pullPolicy}
|
||||
args:
|
||||
- -config.file=/etc/tempo/tempo.yaml
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: ${observability.traceBackend.httpPort}
|
||||
- name: otlp-grpc
|
||||
containerPort: ${observability.traceBackend.otlp.grpcPort}
|
||||
- name: otlp-http
|
||||
containerPort: ${observability.traceBackend.otlp.httpPort}
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: ${observability.probes.readinessPath}
|
||||
port: http
|
||||
volumeMounts:
|
||||
- name: config
|
||||
mountPath: /etc/tempo/tempo.yaml
|
||||
subPath: tempo.yaml
|
||||
readOnly: true
|
||||
- name: data
|
||||
mountPath: /var/tempo
|
||||
volumes:
|
||||
- name: config
|
||||
configMap:
|
||||
name: ${observability.traceBackend.configMapName}
|
||||
- name: data
|
||||
emptyDir: {}
|
||||
`;
|
||||
}
|
||||
Reference in New Issue
Block a user