import { useState, useEffect } from 'react'; import { Upload, Check, Trash2, FileCode, FlaskConical } from 'lucide-react'; import { Button, Card, CardHeader, CardTitle, CardContent, Badge } from '@/components/ui'; import { uploadKubeconfigCmd, listKubeconfigsCmd, activateKubeconfigCmd, deleteKubeconfigCmd, connectClusterFromKubeconfigCmd, testKubectlConnectionCmd, type KubeconfigInfo, } from '@/lib/tauriCommands'; export default function KubeconfigManager() { const [configs, setConfigs] = useState([]); const [isLoading, setIsLoading] = useState(false); const [uploadContent, setUploadContent] = useState(''); const [uploadName, setUploadName] = useState(''); const [error, setError] = useState(''); const [testResult, setTestResult] = useState<{ id: string; output: string } | null>(null); const [testingId, setTestingId] = useState(null); const loadConfigs = async () => { try { const data = await listKubeconfigsCmd(); setConfigs(data); } catch (err) { setError(String(err)); } }; useEffect(() => { loadConfigs(); }, []); const handleFileUpload = async (e: React.ChangeEvent) => { const file = e.target.files?.[0]; if (!file) return; const reader = new FileReader(); reader.onload = async (event) => { const content = event.target?.result as string; setUploadContent(content); setUploadName(file.name.replace(/\.(yaml|yml)$/, '')); }; reader.readAsText(file); }; const handleUpload = async () => { if (!uploadContent || !uploadName) { setError('Please select a file and provide a name'); return; } setIsLoading(true); setError(''); try { await uploadKubeconfigCmd(uploadName, uploadContent); setUploadContent(''); setUploadName(''); await loadConfigs(); } catch (err) { setError(String(err)); } finally { setIsLoading(false); } }; const handleActivate = async (id: string) => { setIsLoading(true); setError(''); try { await activateKubeconfigCmd(id); await loadConfigs(); } catch (err) { setError(String(err)); } finally { setIsLoading(false); } }; const handleDelete = async (id: string) => { if (!confirm('Are you sure you want to delete this kubeconfig?')) return; setIsLoading(true); setError(''); try { await deleteKubeconfigCmd(id); await loadConfigs(); } catch (err) { setError(String(err)); } finally { setIsLoading(false); } }; const handleTestConnection = async (id: string) => { setTestingId(id); setTestResult(null); setError(''); try { // Ensure the cluster is loaded into the session first await connectClusterFromKubeconfigCmd(id).catch(() => {}); const output = await testKubectlConnectionCmd(id); setTestResult({ id, output }); } catch (err) { setTestResult({ id, output: String(err) }); } finally { setTestingId(null); } }; return (

Kubeconfig Manager

Upload and manage multiple Kubernetes cluster configurations for kubectl commands

{error && (
{error}
)} {/* Upload Section */} Upload Kubeconfig
{uploadContent && ( <>
setUploadName(e.target.value)} placeholder="e.g., production-cluster" className="w-full px-3 py-2 border rounded-md" />
{uploadContent.substring(0, 500)}...
)}
{/* Configs List */} Configured Clusters ({configs.length}) {configs.length === 0 ? (

No kubeconfig files uploaded yet

) : (
{configs.map((config) => (

{config.name}

{config.is_active && ( Active )}
Context: {config.context}
{config.cluster_url && (
Cluster: {config.cluster_url}
)}
{!config.is_active && ( )}
{/* Test result for this config */} {testResult?.id === config.id && (
{testResult.output}
)}
))}
)}
{/* Info Card */} About Kubeconfig Files

Kubeconfig files contain authentication credentials and cluster connection details for kubectl commands.

  • Upload your cluster's kubeconfig file (usually ~/.kube/config)
  • Multiple clusters can be configured and switched between
  • The active configuration is used for kubectl commands
  • All kubeconfig files are encrypted using AES-256-GCM
  • Use the Test button to diagnose connection issues
); }