feat(k8s): A1 K8s 双路由体系统一 — code 路由为主, ID 路由标记 deprecated
后端: - 新增 4 条 all-NS code 路由: services/ingresses/cronjobs/nodes - ListNodes 改用 getK8sClientByCode (兼容 ID+code) - ID 域资源路由标记 // Deprecated 前端: - clusterApi/nodeApi/workloadApi 资源方法迁移到 code 路由 - KubernetesClusterDetail/TopologyView/KubernetesNodes 组件从 cluster.id 迁移到 cluster.code - 修复潜在 bug: ClusterOverviewPage 曾将 code 传给 ID-based getNodes 验证: 16/16 API 测试通过 (7 新 code 路由 + 3 旧 ID 兼容 + 6 回归) go build=✅ tsc -b=✅ npm build=✅
This commit is contained in:
1 parent
bb2b91ebe0
commit
00a98e210d
13 files changed
+241
-39
No files matched your search
@@ -8,10 +8,11 @@ export const clusterApi = {
|
||||
createCluster: async (data: Record<string, unknown>) => http.post('/kubernetes-clusters', data),
|
||||
updateCluster: async (id: number | string, data: Record<string, unknown>) => http.put(`/kubernetes-clusters/${id}`, data),
|
||||
deleteCluster: async (id: number | string) => http.delete(`/kubernetes-clusters/${id}`),
|
||||
getPods: async (clusterId: number | string) => http.get(`/kubernetes-clusters/${clusterId}/pods`),
|
||||
getDeployments: async (clusterId: number | string) => http.get(`/kubernetes-clusters/${clusterId}/deployments`),
|
||||
getServices: async (clusterId: number | string) => http.get(`/kubernetes-clusters/${clusterId}/services`),
|
||||
getIngresses: async (clusterId: number | string) => http.get(`/kubernetes-clusters/${clusterId}/ingresses`),
|
||||
// 资源列举 — 统一使用 Kuboard code 路由 (ROADMAP A1)
|
||||
getPods: async (clusterCode: string) => http.get(`/kubernetes/${clusterCode}/pods`),
|
||||
getDeployments: async (clusterCode: string) => http.get(`/kubernetes/${clusterCode}/deployments`),
|
||||
getServices: async (clusterCode: string) => http.get(`/kubernetes/${clusterCode}/services`),
|
||||
getIngresses: async (clusterCode: string) => http.get(`/kubernetes/${clusterCode}/ingresses`),
|
||||
syncCluster: async (clusterId: number | string) => http.post(`/kubernetes-clusters/${clusterId}/sync`),
|
||||
exportAllResources: async (clusterCode: string) =>
|
||||
http.download(`/kubernetes/${clusterCode}/export`, `cluster-${clusterCode}-resources.tar.gz`),
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
import { http } from '@/utils/request';
|
||||
|
||||
export const nodeApi = {
|
||||
getNodes: async (clusterId: number | string) => http.get(`/kubernetes-clusters/${clusterId}/nodes`),
|
||||
// 统一使用 Kuboard code 路由 (ROADMAP A1)
|
||||
getNodes: async (clusterCode: string) => http.get(`/kubernetes/${clusterCode}/nodes`),
|
||||
// 别名 — 保持向后兼容(旧代码可能调用 getClusterNodes)
|
||||
getClusterNodes: async (clusterCode: string) => http.get(`/kubernetes/${clusterCode}/nodes`),
|
||||
getNodeDetail: async (clusterCode: string, nodeName: string) =>
|
||||
http.get(`/kubernetes/${clusterCode}/nodes/${encodeURIComponent(nodeName)}`),
|
||||
|
||||
@@ -42,7 +42,7 @@ export const workloadApi = {
|
||||
http.delete(`/kubernetes/${clusterCode}/namespace/${namespace}/hpas/${name}`),
|
||||
getCronJobs: async (clusterCode: string, namespace?: string) => {
|
||||
if (namespace) return http.get(`/kubernetes/${clusterCode}/namespace/${namespace}/cronjobs`);
|
||||
return http.get(`/kubernetes-clusters/${clusterCode}/cronjobs`);
|
||||
return http.get(`/kubernetes/${clusterCode}/cronjobs`);
|
||||
},
|
||||
createCronJob: async (
|
||||
clusterCode: string,
|
||||
|
||||
@@ -67,15 +67,16 @@ export function KubernetesClusterDetail({ cluster, onClose }: { cluster?: JsonDa
|
||||
];
|
||||
}, [clusterMetrics]);
|
||||
|
||||
const loadClusterDetail = async (clusterId: string) => {
|
||||
const loadClusterDetail = async (clusterCode: string) => {
|
||||
try {
|
||||
// 后端 ListNodes/ListPods/etc 返回 data 直接为数组(非 {list,total})
|
||||
// 统一使用 Kuboard code 路由 (ROADMAP A1)
|
||||
const [nodesRes, podsRes, depRes, svcRes, ingRes] = await Promise.all([
|
||||
kubernetesApi.getNodes(clusterId).catch(() => []),
|
||||
kubernetesApi.getPods(clusterId).catch(() => []),
|
||||
kubernetesApi.getDeployments(clusterId).catch(() => []),
|
||||
kubernetesApi.getServices(clusterId).catch(() => []),
|
||||
kubernetesApi.getIngresses(clusterId).catch(() => []),
|
||||
kubernetesApi.getNodes(clusterCode).catch(() => []),
|
||||
kubernetesApi.getPods(clusterCode).catch(() => []),
|
||||
kubernetesApi.getDeployments(clusterCode).catch(() => []),
|
||||
kubernetesApi.getServices(clusterCode).catch(() => []),
|
||||
kubernetesApi.getIngresses(clusterCode).catch(() => []),
|
||||
]);
|
||||
const toArray = (v: JsonData) => (Array.isArray(v) ? v : (v?.list || []));
|
||||
setNodes(toArray(nodesRes));
|
||||
@@ -89,10 +90,10 @@ export function KubernetesClusterDetail({ cluster, onClose }: { cluster?: JsonDa
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (cluster?.id) {
|
||||
loadClusterDetail(cluster.id);
|
||||
if (cluster?.code) {
|
||||
loadClusterDetail(cluster.code);
|
||||
}
|
||||
}, [cluster?.id]);
|
||||
}, [cluster?.code]);
|
||||
|
||||
return (
|
||||
<Card className="bg-slate-900 border-slate-800">
|
||||
|
||||
@@ -26,7 +26,7 @@ export function KubernetesNodes() {
|
||||
const res: JsonData = await kubernetesApi.getClusters();
|
||||
const list = res?.list || [];
|
||||
setClusters(list);
|
||||
if (list.length > 0 && !selectedCluster) setSelectedCluster(String(list[0].id));
|
||||
if (list.length > 0 && !selectedCluster) setSelectedCluster(String(list[0].code || list[0].id));
|
||||
} catch { setClusters([]); }
|
||||
}, []);
|
||||
|
||||
@@ -72,7 +72,7 @@ export function KubernetesNodes() {
|
||||
</SelectTrigger>
|
||||
<SelectContent className="bg-slate-800 border-slate-700">
|
||||
{clusters.map((c) => (
|
||||
<SelectItem key={c.id} value={String(c.id)}>{c.name}</SelectItem>
|
||||
<SelectItem key={c.id} value={String(c.code || c.id)}>{c.name}</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
|
||||
@@ -96,14 +96,16 @@ export function TopologyView() {
|
||||
setLoading(true);
|
||||
try {
|
||||
const toArray = ( v: any) => (Array.isArray(v) ? v : (v?.list || []));
|
||||
const [nodesRes, svcRes, depRes, ingRes, podRes] = await Promise.all([
|
||||
kubernetesApi.getNodes(selectedClusterId).catch(() => []),
|
||||
kubernetesApi.getServices(selectedClusterId).catch(() => []),
|
||||
kubernetesApi.getDeployments(selectedClusterId).catch(() => []),
|
||||
kubernetesApi.getIngresses(selectedClusterId).catch(() => []),
|
||||
kubernetesApi.getPods(selectedClusterId).catch(() => []),
|
||||
]);
|
||||
const cluster = clusters.find((c) => String(c.id) === selectedClusterId) || {};
|
||||
// 统一使用 Kuboard code 路由获取资源 (ROADMAP A1)
|
||||
const clusterCode = (cluster as any).code || selectedClusterId;
|
||||
const [nodesRes, svcRes, depRes, ingRes, podRes] = await Promise.all([
|
||||
kubernetesApi.getNodes(clusterCode).catch(() => []),
|
||||
kubernetesApi.getServices(clusterCode).catch(() => []),
|
||||
kubernetesApi.getDeployments(clusterCode).catch(() => []),
|
||||
kubernetesApi.getIngresses(clusterCode).catch(() => []),
|
||||
kubernetesApi.getPods(clusterCode).catch(() => []),
|
||||
]);
|
||||
const built = buildTopology(cluster, toArray(ingRes), toArray(svcRes), toArray(depRes), toArray(nodesRes), toArray(podRes));
|
||||
|
||||
// 合并已保存布局
|
||||
|
||||
Reference in new issue
Block a user