feat(k8s): 统一 YAML 查看编辑并补齐 Pod/导出能力
- 抽取 YamlCodeMirror/YamlEditorToolbar,修复弹窗滚动与固定高度布局 - 对齐集群导出精简规则(Service/Ingress/Workload/PVC 注解等) - Deployment/Pod/Service/Ingress 分资源配置:Pod 只读,支持单文件下载 - 修复 Deployment Pod YAML 弹窗未渲染,补全 PodsTab 与详情页 YAML 入口 - 命名空间列表页新增导出 YAML(tar.gz),与集群导出 API 一致
This commit is contained in:
1 parent
eeba677850
commit
fd7b04b9d6
15 files changed
+651
-150
No files matched your search
@@ -22,10 +22,10 @@ export function cleanYAML(yaml: string): string {
|
||||
// ===== 移除配置 =====
|
||||
const METADATA_LINE_KEYS = new Set([
|
||||
'uid', 'resourceVersion', 'creationTimestamp', 'generation',
|
||||
'selfLink', 'clusterName', 'generateName',
|
||||
'selfLink', 'clusterName', 'generateName', 'deletionTimestamp',
|
||||
// managedFields 走 METADATA_BLOCK_KEYS 整块删除(含同级数组项)// Logan.Li
|
||||
]);
|
||||
const METADATA_BLOCK_KEYS = new Set(['managedFields', 'ownerReferences']);
|
||||
const METADATA_BLOCK_KEYS = new Set(['managedFields', 'ownerReferences', 'finalizers']);
|
||||
|
||||
// K8s 默认值 → 值匹配时移除
|
||||
const SPEC_DEFAULTS: Record<string, string[]> = {
|
||||
@@ -35,21 +35,42 @@ export function cleanYAML(yaml: string): string {
|
||||
terminationGracePeriodSeconds: ['30'],
|
||||
serviceAccountName: ['default'],
|
||||
enableServiceLinks: ['true'],
|
||||
automountServiceAccountToken: ['true'],
|
||||
progressDeadlineSeconds: ['600'],
|
||||
revisionHistoryLimit: ['10'],
|
||||
sessionAffinity: ['None'],
|
||||
externalTrafficPolicy: ['Cluster'],
|
||||
internalTrafficPolicy: ['Cluster'],
|
||||
ipFamilyPolicy: ['SingleStack'],
|
||||
allocateLoadBalancerNodePorts: ['true'],
|
||||
preemptionPolicy: ['PreemptLowerPriority'],
|
||||
priority: ['0'],
|
||||
};
|
||||
const CONTAINER_DEFAULTS: Record<string, string[]> = {
|
||||
imagePullPolicy: ['Always', 'IfNotPresent'],
|
||||
terminationMessagePath: ['/dev/termination-log'],
|
||||
terminationMessagePolicy: ['File'],
|
||||
stdin: ['false'],
|
||||
tty: ['false'],
|
||||
stdinOnce: ['false'],
|
||||
};
|
||||
const SERVICE_RUNTIME_KEYS = new Set([
|
||||
'clusterIP', 'clusterIPs', 'ipFamilies', 'healthCheckNodePort',
|
||||
]);
|
||||
const ALWAYS_REMOVE_ANNOTATIONS = new Set([
|
||||
'kubectl.kubernetes.io/last-applied-configuration',
|
||||
'kubectl.kubernetes.io/change-cause',
|
||||
'deployment.kubernetes.io/revision',
|
||||
'deployment.kubernetes.io/desired-replicas',
|
||||
'deployment.kubernetes.io/max-replicas',
|
||||
'kubectl.kubernetes.io/restartedAt',
|
||||
'control-plane.alpha.kubernetes.io/leader',
|
||||
'autoscaling.alpha.kubernetes.io/conditions',
|
||||
'kubernetes.io/config.hash',
|
||||
'pv.kubernetes.io/bind-completed',
|
||||
'pv.kubernetes.io/bound-by-controller',
|
||||
]);
|
||||
const STRIP_LABEL_KEYS = new Set(['pod-template-hash', 'controller-revision-hash']);
|
||||
const SYSTEM_VOLUME_PREFIXES = ['kube-api-access-', 'default-token-', 'kube-'];
|
||||
const SYSTEM_MOUNT_PATHS = ['/var/run/secrets/kubernetes.io/serviceaccount'];
|
||||
|
||||
@@ -167,9 +188,10 @@ export function cleanYAML(yaml: string): string {
|
||||
inAnnotations = false;
|
||||
}
|
||||
|
||||
// labels 下的 pod-template-hash
|
||||
// labels 下控制器自动标签
|
||||
if (indent >= metaIndent && indent <= metaIndent + 2) {
|
||||
if (trimmed.startsWith('pod-template-hash') && trimmed.includes(':')) {
|
||||
const labelKey = extractKey(line);
|
||||
if (labelKey && STRIP_LABEL_KEYS.has(labelKey)) {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
@@ -230,13 +252,19 @@ export function cleanYAML(yaml: string): string {
|
||||
// spec.selector — 不动(关键字段)
|
||||
// spec.strategy — 不动
|
||||
|
||||
// spec 下的 K8s 默认值
|
||||
if (indent === 2 && key && SPEC_DEFAULTS[key]) {
|
||||
const afterColon = trimmed.split(':').slice(1).join(':').trim();
|
||||
if (SPEC_DEFAULTS[key].includes(afterColon)) {
|
||||
i++;
|
||||
// spec 下的 K8s 默认值 / Service 运行时字段
|
||||
if (indent === 2 && key) {
|
||||
if (SERVICE_RUNTIME_KEYS.has(key)) {
|
||||
if (hasInlineValue(line)) i++; else skipBlock(indent);
|
||||
continue;
|
||||
}
|
||||
if (SPEC_DEFAULTS[key]) {
|
||||
const afterColon = trimmed.split(':').slice(1).join(':').trim();
|
||||
if (SPEC_DEFAULTS[key].includes(afterColon)) {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// spec 下的 nodeName(运行时分配)
|
||||
@@ -245,6 +273,28 @@ export function cleanYAML(yaml: string): string {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Deployment 默认滚动策略整块移除 // Logan.Li
|
||||
if (indent === 2 && key === 'strategy') {
|
||||
const blockLines: string[] = [];
|
||||
let j = i;
|
||||
while (j < lines.length) {
|
||||
const l = lines[j];
|
||||
const t = l.trimStart();
|
||||
if (t === '' || t.startsWith('#')) { blockLines.push(l); j++; continue; }
|
||||
if (j > i && getIndent(l) <= indent) break;
|
||||
blockLines.push(l);
|
||||
j++;
|
||||
}
|
||||
const blockText = blockLines.join('\n');
|
||||
const isDefaultRolling = blockText.includes('type: RollingUpdate')
|
||||
&& (blockText.includes('maxUnavailable: 25%') || blockText.includes('maxUnavailable: 0'))
|
||||
&& (blockText.includes('maxSurge: 25%') || blockText.includes('maxSurge: 1'));
|
||||
if (isDefaultRolling) {
|
||||
i = j;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// template.spec 内部
|
||||
if (indent === 2 && key === 'spec') {
|
||||
// 这是 template.spec 的开始
|
||||
|
||||
Reference in new issue
Block a user