fix(kube): action namespace, race condition, stability, dark mode #86

Merged
sarman merged 7 commits from fix/kube-action-namespace-and-stability into master 2026-06-09 03:21:49 +00:00
Owner

Root causes fixed

1. Temp kubeconfig race condition — intermittent load failures

Every kubectl command wrote a temp kubeconfig to a static path (kubeconfig-{cluster_id}-{type}.yaml). Concurrent calls shared the same path; the first to finish deleted the file via TempFileCleanup::drop() while the second call's kubectl process was still reading it. Replaced all 74 static paths with a unique_kubeconfig_path() helper backed by an AtomicU64 counter — each call now gets a unique path. This was the root cause of "things stop loading after a few selection changes".

2. Namespace "all" in pod action commands

PodInfo lacked a namespace field (unlike every other resource type). PodList passed the UI filter prop (namespace="all") directly to kubectl for every action — logs, shell, attach, edit, delete. Added namespace: String to PodInfo (Rust struct + TypeScript interface + parser), and updated PodList to use pod.namespace in all action calls.

3. Namespace "all" in all other list component actions

18 list components (Deployment, StatefulSet, DaemonSet, Service, ConfigMap, Secret, HPA, PVC, RoleBinding, etc.) had the same bug — action handlers used the filter prop instead of item.namespace. All fixed.

4. WorkloadOverview always showed 0

loadResourceData had an early-return for workloads_overview, so WorkloadOverview always received empty arrays. Now fetches pods + deployments + statefulsets + daemonsets + jobs + cronjobs in parallel via Promise.allSettled when that section is active.

5. Double connectClusterFromKubeconfigCmd on mount

loadInitialData closed over selectedClusterId in its useCallback deps. Calling setSelectedCluster() inside it recreated the callback and re-fired the effect, triggering a second connect. Fixed with an initializedRef guard.

6. Silent cluster connection errors

Connection failures were swallowed with .catch(() => {}). Now captured and surfaced as a dismissible error banner.

7. Dark mode contrast

PortForwardList status badge and WorkloadOverview dot indicator used non-adaptive text-gray-* / bg-gray-* classes that vanished on dark backgrounds. Replaced with semantic Tailwind vars (text-muted-foreground, bg-muted).

Test plan

  • cargo test → 364 pass
  • npm run test:run → 325 pass (40 files)
  • npx tsc --noEmit → 0 errors
  • npx eslint . --max-warnings 0 → 0 warnings
  • cargo fmt --check → clean
  • cargo clippy -- -D warnings → 0 warnings
  • Manual: rapid section/namespace switching no longer causes data to stop loading
  • Manual: pod Logs shows correct output (not "namespaces all not found")
  • Manual: pod Shell, Attach, Edit modals open and target the correct namespace
  • Manual: Workloads → Overview shows actual resource counts
  • Manual: connection error banner appears when kubeconfig is invalid
  • Manual: dark mode — all text readable, status indicators visible
## Root causes fixed ### 1. Temp kubeconfig race condition — intermittent load failures Every kubectl command wrote a temp kubeconfig to a static path (`kubeconfig-{cluster_id}-{type}.yaml`). Concurrent calls shared the same path; the first to finish deleted the file via `TempFileCleanup::drop()` while the second call's kubectl process was still reading it. Replaced all 74 static paths with a `unique_kubeconfig_path()` helper backed by an `AtomicU64` counter — each call now gets a unique path. **This was the root cause of "things stop loading after a few selection changes".** ### 2. Namespace `"all"` in pod action commands `PodInfo` lacked a `namespace` field (unlike every other resource type). `PodList` passed the UI filter prop (`namespace="all"`) directly to kubectl for every action — logs, shell, attach, edit, delete. Added `namespace: String` to `PodInfo` (Rust struct + TypeScript interface + parser), and updated `PodList` to use `pod.namespace` in all action calls. ### 3. Namespace `"all"` in all other list component actions 18 list components (Deployment, StatefulSet, DaemonSet, Service, ConfigMap, Secret, HPA, PVC, RoleBinding, etc.) had the same bug — action handlers used the filter prop instead of `item.namespace`. All fixed. ### 4. WorkloadOverview always showed 0 `loadResourceData` had an early-return for `workloads_overview`, so WorkloadOverview always received empty arrays. Now fetches pods + deployments + statefulsets + daemonsets + jobs + cronjobs in parallel via `Promise.allSettled` when that section is active. ### 5. Double `connectClusterFromKubeconfigCmd` on mount `loadInitialData` closed over `selectedClusterId` in its `useCallback` deps. Calling `setSelectedCluster()` inside it recreated the callback and re-fired the effect, triggering a second connect. Fixed with an `initializedRef` guard. ### 6. Silent cluster connection errors Connection failures were swallowed with `.catch(() => {})`. Now captured and surfaced as a dismissible error banner. ### 7. Dark mode contrast `PortForwardList` status badge and `WorkloadOverview` dot indicator used non-adaptive `text-gray-*` / `bg-gray-*` classes that vanished on dark backgrounds. Replaced with semantic Tailwind vars (`text-muted-foreground`, `bg-muted`). ## Test plan - [ ] `cargo test` → 364 pass - [ ] `npm run test:run` → 325 pass (40 files) - [ ] `npx tsc --noEmit` → 0 errors - [ ] `npx eslint . --max-warnings 0` → 0 warnings - [ ] `cargo fmt --check` → clean - [ ] `cargo clippy -- -D warnings` → 0 warnings - [ ] Manual: rapid section/namespace switching no longer causes data to stop loading - [ ] Manual: pod Logs shows correct output (not "namespaces all not found") - [ ] Manual: pod Shell, Attach, Edit modals open and target the correct namespace - [ ] Manual: Workloads → Overview shows actual resource counts - [ ] Manual: connection error banner appears when kubeconfig is invalid - [ ] Manual: dark mode — all text readable, status indicators visible
sarman added 6 commits 2026-06-09 03:04:19 +00:00
Each kubectl command now uses a globally unique temp kubeconfig path via
an AtomicU64 counter, preventing TempFileCleanup from deleting a file that
a concurrent call is still using.
Non-adaptive text-gray-* and bg-white classes replaced with text-foreground,
text-muted-foreground, bg-card, bg-background — ensuring readable contrast
in both light and dark themes.
- workloads_overview now fetches pods/deployments/statefulsets/daemonsets/jobs/
  cronjobs in parallel via Promise.allSettled
- loadInitialData initializedRef guard prevents double connectClusterFromKubeconfig
- connection errors now surface as a dismissible banner instead of being swallowed
Pod actions (logs, shell, attach, edit, delete) were receiving namespace='all'
from the UI filter prop and passing it to kubectl as -n all. Fixes by adding
namespace field to PodInfo (Rust + TypeScript) and using pod.namespace in all
action command calls in PodList.
Service/Ingress/ConfigMap/Secret/HPA/PVC/ServiceAccount/Role/RoleBinding/
NetworkPolicy/ResourceQuota/LimitRange action handlers now use the resource's
own .namespace field instead of the UI filter namespace='all'. Removes the
now-unused ns local variable from CronJobList/JobList/ReplicaSetList.

24 new TDD tests verify the correct namespace is passed to getResourceYamlCmd
and deleteResourceCmd for each of the 12 affected components.
fix(kube): workload list actions use item.namespace not filter prop
Some checks failed
PR Review Automation / review (pull_request) Has been cancelled
Test / rust-fmt-check (pull_request) Has been cancelled
Test / rust-clippy (pull_request) Has been cancelled
Test / frontend-typecheck (pull_request) Has been cancelled
Test / rust-tests (pull_request) Has been cancelled
Test / frontend-tests (pull_request) Has been cancelled
7dfda91cd8
Deployment/StatefulSet/DaemonSet action handlers were passing
namespace='all' to kubectl when All Namespaces was selected.
Actions now use the resource's own .namespace field for openEdit,
handleRestart, handleRollback, handleDelete, ScaleModal, and
EditResourceModal.

Adds 21 TDD tests in WorkloadListActions.test.tsx covering all
action handlers across DeploymentList, StatefulSetList, DaemonSetList,
ReplicaSetList, JobList, and CronJobList. Tests verify IPC calls
receive the item's actual namespace even when the filter prop is 'all'.
sarman added 1 commit 2026-06-09 03:04:58 +00:00
docs: add ticket summary for kube action namespace and stability fixes
All checks were successful
Test / frontend-tests (pull_request) Successful in 1m40s
Test / frontend-typecheck (pull_request) Successful in 1m49s
PR Review Automation / review (pull_request) Successful in 4m12s
Test / rust-fmt-check (pull_request) Successful in 11m49s
Test / rust-clippy (pull_request) Successful in 13m6s
Test / rust-tests (pull_request) Successful in 14m36s
5f4ca1291a
sarman reviewed 2026-06-09 03:09:47 +00:00
sarman left a comment
Author
Owner

Automated PR Review (qwen3-coder-next via liteLLM):\n\nSummary
The PR addresses critical race conditions, namespace handling bugs, and dark mode issues in the Kubernetes interface. A comprehensive refactor introduced unique temp kubeconfig paths and propagated namespace from resource data in both Rust structs and TypeScript components. The changes are extensive and well-tested, but two high-severity issues remain: the discover_pods function incorrectly uses a hardcoded namespace parameter instead of respecting "all""" conversion, and list_namespaces_resource lacks namespace filtering.

Findings

  • [BLOCKER] src-tauri/src/commands/kube.rs:484 - discover_pods passes namespace directly to kubectl -n {namespace} without converting "all""", causing kubectl -n all failures
    Evidence: kubectl_cmd.arg("-n").arg(&namespace); in discover_pods (lines 482–485 in full file) and no handling of "all" case
    Fix: Replace kubectl_cmd.arg("-n").arg(&namespace); with logic that appends --all-namespaces when namespace == "all" or namespace.is_empty().

  • [WARNING] src-tauri/src/commands/kube.rs:1238 - list_namespaces_resource returns namespace names but accepts no namespace filter; caller confusion likely
    Evidence: list_namespaces_resource (lines 1227–1306 in full file) runs kubectl get namespaces -o json with no -n or --all-namespaces — correct, but the NamespaceResourceInfo struct and UI expectation (e.g., in WorkloadOverview) may imply filtering by namespace when it does not exist
    Fix: Document that list_namespaces_resource is cluster-scoped and distinct from per-namespace listing; consider adding optional namespace filter if UI truly expects per-namespace resource listing.

Verdict: REQUEST CHANGES

Automated PR Review (qwen3-coder-next via liteLLM):\n\n**Summary** The PR addresses critical race conditions, namespace handling bugs, and dark mode issues in the Kubernetes interface. A comprehensive refactor introduced unique temp kubeconfig paths and propagated `namespace` from resource data in both Rust structs and TypeScript components. The changes are extensive and well-tested, but two high-severity issues remain: the `discover_pods` function incorrectly uses a hardcoded `namespace` parameter instead of respecting `"all"` → `""` conversion, and `list_namespaces_resource` lacks `namespace` filtering. **Findings** - [BLOCKER] src-tauri/src/commands/kube.rs:484 - `discover_pods` passes `namespace` directly to `kubectl -n {namespace}` without converting `"all"` → `""`, causing `kubectl -n all` failures Evidence: `kubectl_cmd.arg("-n").arg(&namespace);` in `discover_pods` (lines 482–485 in full file) and no handling of `"all"` case Fix: Replace `kubectl_cmd.arg("-n").arg(&namespace);` with logic that appends `--all-namespaces` when `namespace == "all"` or `namespace.is_empty()`. - [WARNING] src-tauri/src/commands/kube.rs:1238 - `list_namespaces_resource` returns namespace *names* but accepts no namespace filter; caller confusion likely Evidence: `list_namespaces_resource` (lines 1227–1306 in full file) runs `kubectl get namespaces -o json` with no `-n` or `--all-namespaces` — correct, but the `NamespaceResourceInfo` struct and UI expectation (e.g., in `WorkloadOverview`) may imply filtering by namespace when it does not exist Fix: Document that `list_namespaces_resource` is cluster-scoped and distinct from per-namespace listing; consider adding optional namespace filter if UI truly expects per-namespace resource listing. **Verdict**: REQUEST CHANGES
sarman merged commit 1d61e7ceb3 into master 2026-06-09 03:21:49 +00:00
sarman deleted branch fix/kube-action-namespace-and-stability 2026-06-09 03:21:49 +00:00
Sign in to join this conversation.
No reviewers
No Milestone
No project
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: sarman/tftsr-devops_investigation#86
No description provided.