Blockers: - Replace serde_yaml::from_str with serde_json::from_str in all 6 parse_*_json functions (parse_namespaces, parse_pods, parse_services, parse_deployments, parse_statefulsets, parse_daemonsets). Update .as_sequence() → .as_array(), .as_mapping() → .as_object(), and mapping iterator patterns throughout. Explicitly type serde_yaml::Value in extract_context/extract_server_url which legitimately parse YAML. Warnings: - Add containers: Vec<String> to PodInfo struct; parse from spec.containers[].name in parse_pods_json - Fix PodList.tsx to use selectedPod.containers instead of [selectedPod.name] - Fix exec_pod: add optional shell param with allowlist validation (sh/bash/ash/dash); correct arg ordering — -c container now placed before -- separator - Handle empty namespace with --all-namespaces in all 5 list commands - Fix dialog overflow: overflow-hidden → overflow-y-auto on inner div - Memoize namespace options with useMemo in ResourceBrowser Lint cleanup (all pre-existing, surfaced by eslint config fix): - Deduplicate eslint.config.js (was doubled to 272 lines); move ignores to standalone global object; allow console.log in cli section - Remove stale .eslintignore (migrated to eslint.config.js) - Remove unused Card/CardTitle imports from Kubernetes list components - Rename unused props to _clusterId/_namespace in DaemonSetList, ServiceList, StatefulSetList - Fix useEffect/useCallback missing deps in Triage and LogUpload - Remove debug console.log from App.tsx provider auto-test - Rename unused hover prop to _hover in TableRow (ui/index.tsx) - Add #[allow(unused_variables)] to Phase 3 stub Tauri commands - Restore get_pod_logs, scale_deployment, restart_deployment, delete_resource, exec_pod to lib.rs handler registration (were accidentally dropped in Phase 3 expansion) All checks pass: cargo clippy -D warnings, tsc --noEmit, eslint --max-warnings 0, 331 Rust tests, 98 frontend tests.
6.2 KiB
Kubernetes UI PR Review Fixes
Description
Resolved all findings from the automated PR review (qwen3-coder-next) of the Kubernetes resource discovery and management feature. The review identified two blockers and several warnings across Rust backend and React frontend.
Root cause of blockers: All six JSON parsing functions in kube.rs imported and used serde_yaml::Value / serde_yaml::from_str against kubectl's JSON output (-o json), causing parse failures or incorrect data at runtime. YAML is a superset of JSON and sometimes parses silently incorrectly; the correct parser is serde_json.
Secondary issues: PodInfo lacked container name data, so the log viewer could only show the pod name as the container selector. The exec_pod command had an incorrect kubectl argument order (container -c flag placed after --, so it was passed to the shell inside the pod rather than to kubectl). The "All Namespaces" filter passed an empty string to kubectl -n "" which is invalid.
Acceptance Criteria
- All six
parse_*_jsonfunctions useserde_json::from_strandserde_json::ValueAPI (as_array,as_object) PodInfostruct carriescontainers: Vec<String>; container names parsed fromspec.containers[*].namePodList.tsxcontainer selector populates fromselectedPod.containersexec_podcontainer-cflag is placed before--separator (correct kubectl syntax)exec_podaccepts optionalshellparameter with allowlist validation (sh,bash,ash,dash)- Empty namespace string routes to
--all-namespacesin all five list commands - Dialog inner div uses
overflow-y-autoto handle content overflow on small screens getNamespaceOptionsmemoized withuseMemoeslint.config.jsdeduplicated (was 272 lines, duplicate blocks removed), global ignore fixed- Unused imports removed from all Kubernetes list components
cargo clippy -- -D warnings: zero warningstsc --noEmit: zero errorseslint . --max-warnings 0: zero warnings- 331 Rust tests passing, 98 frontend tests passing
Work Implemented
src-tauri/src/commands/kube.rs
- Replaced
use serde_yaml::Valuewithuse serde_json::Value extract_contextandextract_server_url: explicitly typed asserde_yaml::Value(these legitimately parse YAML kubeconfig files)PodInfostruct: addedcontainers: Vec<String>fieldparse_pods_json: switched toserde_json::from_str,as_array(); added container name extraction fromspec.containers[].nameparse_namespaces_json,parse_services_json,parse_deployments_json,parse_statefulsets_json,parse_daemonsets_json: switched toserde_json::from_str,as_array(),as_object(); updated mapping iterators (serde_json object keys areString, notValue)parse_services_json: fixed.as_sequence()→.as_array()inexternal_ipingress chainlist_pods,list_services,list_deployments,list_statefulsets,list_daemonsets: handle emptynamespacewith--all-namespacesexec_pod: added optionalshell: Option<String>parameter; allowlist validates against["sh","bash","ash","dash","/bin/sh","/bin/bash","/bin/ash","/bin/dash"]; fixed argument order so-c containerappears before--- Phase 3 stub commands: added
#[allow(unused_variables)]to suppress Clippy warnings on unimplemented stubs
src/lib/tauriCommands.ts
PodInfointerface: addedcontainers: string[]execPodCmd: added optionalshell?: stringparameter, passed through to IPC
src/components/Kubernetes/PodList.tsx
- Fixed:
const containers = selectedPod ? [selectedPod.name] : []→selectedPod?.containers ?? [] - Fixed:
overflow-hidden→overflow-y-autoon inner dialog content div - Removed unused imports:
Card,CardContent,CardHeader,CardTitle
src/components/Kubernetes/ResourceBrowser.tsx
- Added
useCallbackimport; wrappedloadDatainuseCallback([clusterId, selectedNamespace]) useEffectdeps updated to[loadData, resourceType]- Removed unused
CardTitleimport getNamespaceOptionsconverted to memoizednamespaceOptionsviauseMemo
src/components/Kubernetes/DaemonSetList.tsx, ServiceList.tsx, StatefulSetList.tsx
- Removed unused
Card,CardContent,CardHeader,CardTitleimports - Renamed unused props:
clusterId: _clusterId,namespace: _namespace
src/components/Kubernetes/DeploymentList.tsx
- Removed unused
Card,CardContent,CardHeader,CardTitleimports
src/components/ui/index.tsx
TableRow: renamed unusedhoverprop to_hover
src/App.tsx
- Removed two debug
console.logcalls (auto-testing provider connection)
src/pages/Triage/index.tsx
useEffect: addedaddMessage,setActiveDomain,startSessionto dependency array (stable Zustand store actions)
src/pages/LogUpload/index.tsx
handleImagesUpload: wrapped inuseCallback([id])and moved beforehandleImageDropto resolve declaration-order issuehandleImageDrop: updated deps from[id]to[handleImagesUpload]
eslint.config.js
- Removed duplicate config block (file was doubled to 272 lines)
- Fixed global ignore: moved
ignoresarray to a standalone config object (was incorrectly paired withfiles) - CLI section: added
"log"to allowed console methods (CLI tool output)
.eslintignore
- Deleted — content migrated to
eslint.config.jsglobal ignore
Testing Needed
- Connect a real kubeconfig and verify pod/namespace/service/deployment/statefulset/daemonset lists render correctly with JSON from kubectl
- Select "All Namespaces" — verify
--all-namespacesis used and resources from all namespaces appear - Open pod log dialog — verify container dropdown shows actual container names (not pod name)
- Fetch logs for a multi-container pod — verify correct container logs are returned
- Test
exec_podvia UI withsh(default) andbash— verify both work - Test
exec_podwith an invalid shell name (e.g.,zsh) — verify it returns an error - Verify "All Namespaces" view does not trigger empty-namespace kubectl error
- Smoke test triage and log upload flows to verify
useEffect/useCallbackhook changes have no regressions