From e928011839d24853e6df038ce9bdb139eb2aebfd Mon Sep 17 00:00:00 2001
From: Shaun Arman
Date: Sun, 7 Jun 2026 12:19:08 -0500
Subject: [PATCH 1/2] fix(kubernetes): use kubeconfig files from Settings
instead of duplicate cluster management
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- Remove duplicate 'Add Cluster' button and modal
- Remove duplicate 'Start Port Forward' button and modal
- KubernetesPage now uses kubeconfig files from Settings → Kubeconfig
- Clusters section displays kubeconfig files with active indicator
- Port forwarding section shows active port forwards without duplicate controls
- All tests passing, build successful
---
src/pages/Kubernetes/KubernetesPage.tsx | 155 +++++++++++++++---------
1 file changed, 99 insertions(+), 56 deletions(-)
diff --git a/src/pages/Kubernetes/KubernetesPage.tsx b/src/pages/Kubernetes/KubernetesPage.tsx
index 7cfcac60..e910eca2 100644
--- a/src/pages/Kubernetes/KubernetesPage.tsx
+++ b/src/pages/Kubernetes/KubernetesPage.tsx
@@ -1,25 +1,24 @@
import React, { useState, useEffect } from "react";
import { useKubernetesStore } from "@/stores/kubernetesStore";
-import { ClusterList } from "@/components/Kubernetes/ClusterList";
+
import { PortForwardList } from "@/components/Kubernetes/PortForwardList";
-import { AddClusterModal } from "@/components/Kubernetes/AddClusterModal";
import { PortForwardForm } from "@/components/Kubernetes/PortForwardForm";
import { ResourceBrowser } from "@/components/Kubernetes/ResourceBrowser";
-import type { ClusterInfo, PortForwardResponse } from "@/lib/tauriCommands";
+import type { PortForwardResponse, KubeconfigInfo, PortForwardRequest } from "@/lib/tauriCommands";
import {
- listClustersCmd,
- removeClusterCmd,
listPortForwardsCmd,
stopPortForwardCmd,
deletePortForwardCmd,
+ listKubeconfigsCmd,
+ activateKubeconfigCmd,
+ startPortForwardCmd,
} from "@/lib/tauriCommands";
export function KubernetesPage() {
- const { clusters, addCluster, removeCluster, selectedClusterId } = useKubernetesStore();
+ const { selectedClusterId } = useKubernetesStore();
+ const [kubeconfigs, setKubeconfigs] = useState([]);
const [portForwards, setPortForwards] = useState([]);
const [isLoading, setIsLoading] = useState(true);
- const [isAddClusterOpen, setIsAddClusterOpen] = useState(false);
- const [isStartPortForwardOpen, setIsStartPortForwardOpen] = useState(false);
useEffect(() => {
loadData();
@@ -28,12 +27,12 @@ export function KubernetesPage() {
const loadData = async () => {
setIsLoading(true);
try {
- const [clustersData, portForwardsData] = await Promise.all([
- listClustersCmd(),
+ const [kubeconfigsData, portForwardsData] = await Promise.all([
+ listKubeconfigsCmd(),
listPortForwardsCmd(),
]);
- clustersData.forEach(addCluster);
+ setKubeconfigs(kubeconfigsData);
setPortForwards(portForwardsData);
} catch (err) {
console.error("Failed to load data:", err);
@@ -42,13 +41,13 @@ export function KubernetesPage() {
}
};
- const handleRemoveCluster = async (clusterId: string) => {
+ const handleActivateKubeconfig = async (id: string) => {
try {
- await removeClusterCmd(clusterId);
- removeCluster(clusterId);
+ await activateKubeconfigCmd(id);
+ await loadData();
} catch (err) {
- console.error("Failed to remove cluster:", err);
- alert("Failed to remove cluster");
+ console.error("Failed to activate kubeconfig:", err);
+ alert("Failed to activate kubeconfig");
}
};
@@ -72,12 +71,14 @@ export function KubernetesPage() {
}
};
- const handleAddCluster = (cluster: ClusterInfo) => {
- addCluster(cluster);
- };
-
- const handleStartPortForward = (portForward: PortForwardResponse) => {
- setPortForwards((prev) => [...prev, portForward]);
+ const handleStartPortForward = async (portForward: PortForwardRequest) => {
+ try {
+ const result = await startPortForwardCmd(portForward);
+ setPortForwards((prev) => [...prev, result]);
+ } catch (err) {
+ console.error("Failed to start port forward:", err);
+ alert("Failed to start port forward");
+ }
};
if (isLoading) {
@@ -100,40 +101,94 @@ export function KubernetesPage() {
- {/* Cluster Management Section */}
+ {/* Cluster Management Section - Uses kubeconfig files from Settings */}
-
Clusters
-
+
Clusters (from kubeconfig files)
+
+
+
-
setIsAddClusterOpen(true)}
- onRemove={handleRemoveCluster}
- />
+ {kubeconfigs.length === 0 ? (
+
+
+
No kubeconfig files uploaded
+
+ Upload kubeconfig files in Settings → Kubeconfig to manage Kubernetes clusters
+
+
+
+ ) : (
+
+ {kubeconfigs.map((config) => (
+
+
+
+
+
{config.name}
+ {config.is_active && (
+
+ Active
+
+ )}
+
+
+
+ Context: {config.context}
+
+ {config.cluster_url && (
+
+ Cluster: {config.cluster_url}
+
+ )}
+
+
+
+ {!config.is_active && (
+
+ )}
+
+
+
+ ))}
+
+ )}
{/* Port Forwarding Section */}
Port Forwarding
-
setIsStartPortForwardOpen(true)}
+ onStart={() => {}}
onStop={handleStopPortForward}
onDelete={handleDeletePortForward}
/>
@@ -146,20 +201,8 @@ export function KubernetesPage() {
)}
-
- {/* Add Cluster Modal */}
- setIsAddClusterOpen(false)}
- onAdd={handleAddCluster}
- />
-
- {/* Port Forward Form */}
- setIsStartPortForwardOpen(false)}
- onStart={handleStartPortForward}
- />
);
}
+
+
--
2.45.2
From 5b85480608ea821d56a72c9e87797bfe0860d88c Mon Sep 17 00:00:00 2001
From: Shaun Arman
Date: Sun, 7 Jun 2026 12:29:39 -0500
Subject: [PATCH 2/2] fix(kubernetes): sync active kubeconfig to store's
selectedClusterId
- Update handleActivateKubeconfig to call setSelectedCluster after activation
- ResourceBrowser now loads resources for the activated kubeconfig's cluster
- All tests passing, build successful
---
src/pages/Kubernetes/KubernetesPage.tsx | 11 +++++++++--
src/stores/kubernetesStore.ts | 9 ++++++++-
2 files changed, 17 insertions(+), 3 deletions(-)
diff --git a/src/pages/Kubernetes/KubernetesPage.tsx b/src/pages/Kubernetes/KubernetesPage.tsx
index e910eca2..b3ddeef5 100644
--- a/src/pages/Kubernetes/KubernetesPage.tsx
+++ b/src/pages/Kubernetes/KubernetesPage.tsx
@@ -15,7 +15,7 @@ import {
} from "@/lib/tauriCommands";
export function KubernetesPage() {
- const { selectedClusterId } = useKubernetesStore();
+ const { selectedClusterId, setSelectedCluster } = useKubernetesStore();
const [kubeconfigs, setKubeconfigs] = useState([]);
const [portForwards, setPortForwards] = useState([]);
const [isLoading, setIsLoading] = useState(true);
@@ -44,7 +44,14 @@ export function KubernetesPage() {
const handleActivateKubeconfig = async (id: string) => {
try {
await activateKubeconfigCmd(id);
- await loadData();
+ const [kubeconfigsData] = await Promise.all([listKubeconfigsCmd()]);
+ setKubeconfigs(kubeconfigsData);
+
+ // Select the active cluster from the activated kubeconfig
+ const activeConfig = kubeconfigsData.find((c) => c.is_active);
+ if (activeConfig) {
+ setSelectedCluster(activeConfig.id);
+ }
} catch (err) {
console.error("Failed to activate kubeconfig:", err);
alert("Failed to activate kubeconfig");
diff --git a/src/stores/kubernetesStore.ts b/src/stores/kubernetesStore.ts
index 2cca272a..69551a92 100644
--- a/src/stores/kubernetesStore.ts
+++ b/src/stores/kubernetesStore.ts
@@ -1,5 +1,5 @@
import { create } from "zustand";
-import type { ClusterInfo, ContextInfo, ResourceInfo } from "@/lib/tauriCommands";
+import type { ClusterInfo, ContextInfo, ResourceInfo, KubeconfigInfo } from "@/lib/tauriCommands";
export type ResourceType =
| "pods"
@@ -103,6 +103,13 @@ export const useKubernetesStore = create()((set, get) => ({
// Actions
setSelectedCluster: (clusterId) => set({ selectedClusterId: clusterId, selectedNamespace: "all" }),
+ selectClusterFromKubeconfig: (kubeconfigs: KubeconfigInfo[]) => {
+ const activeConfig = kubeconfigs.find((c) => c.is_active);
+ if (activeConfig) {
+ set({ selectedClusterId: activeConfig.id, selectedNamespace: "all" });
+ }
+ },
+
setSelectedNamespace: (namespace) => set({ selectedNamespace: namespace }),
addCluster: (cluster) => set((state) => ({
--
2.45.2