diff --git a/TICKET-freelens-feature-inventory.md b/TICKET-freelens-feature-inventory.md new file mode 100644 index 00000000..737f9e5d --- /dev/null +++ b/TICKET-freelens-feature-inventory.md @@ -0,0 +1,551 @@ +# FreeLens Feature Inventory — Complete Analysis + +**Project**: FreeLens (https://github.com/freelensapp/freelens) +**License**: MIT License (Copyright 2024-2026 Freelens Authors; Copyright 2022 OpenLens Authors) +**Description**: Free and open-source Kubernetes IDE, community fork of Open Lens v5 +**Analysis Date**: 2026-06-08 +**Repository Commit**: main branch (latest) + +--- + +## Executive Summary + +FreeLens is a production-ready, feature-complete Kubernetes desktop IDE built on Electron with a comprehensive resource management interface. The application provides extensive coverage of Kubernetes API resources with dedicated UI components, context menus, and detail views for nearly all standard Kubernetes objects. + +**Key Findings**: +- **13 main navigation categories** with 60+ resource types +- **Comprehensive pod management**: shell/exec, logs, attach, edit, delete, force delete, force finalize +- **Full workload lifecycle**: scale, restart, edit, delete for Deployments, StatefulSets, DaemonSets +- **Helm chart integration**: install, upgrade, rollback, delete +- **Port forwarding UI**: start/stop/edit/open in browser +- **Terminal integration**: built-in terminal with kubectl and node shell access +- **Resource metrics**: CPU/memory usage visualization (when metrics-server available) +- **YAML editing**: Monaco editor with syntax highlighting +- **RBAC management**: full support for roles, bindings, service accounts +- **Extension ecosystem**: plugin architecture for custom functionality + +--- + +## Left Navigation Structure (Complete) + +### 1. Favorites +- User-bookmarked resources for quick access + +### 2. Cluster Overview +- Cluster-wide dashboard with health metrics + +### 3. Nodes +- Node list and details +- **Context Menu Actions**: + - Shell (node shell access via SSH or similar) + - Cordon/Uncordon + - Drain (with confirmation) + - Edit + - Delete + +### 4. Workloads +Parent category containing: + +#### 4.1 Overview +- Aggregated workload dashboard + +#### 4.2 Pods +- Pod list with status, IP, node, age +- **Context Menu Actions**: + - Shell (per-container with auto-detection: bash/ash/sh, PowerShell for Windows nodes) + - Logs (per-container, including init and ephemeral containers) + - Attach (kubectl attach -it) + - Edit (YAML editor) + - Delete (graceful) + - Force Delete (skip grace period, only for Running/Pending phases) + - Force Finalize (remove finalizers when stuck) + +#### 4.3 Deployments +- **Context Menu Actions**: + - Scale (replica count dialog) + - Restart (rolling restart) + - Edit + - Delete + +#### 4.4 StatefulSets +- **Context Menu Actions**: + - Restart + - Edit + - Delete + +#### 4.5 DaemonSets +- **Context Menu Actions**: + - Restart + - Edit + - Delete + +#### 4.6 Jobs +- **Context Menu Actions**: + - Edit + - Delete + +#### 4.7 CronJobs +- **Context Menu Actions**: + - Edit + - Delete + +#### 4.8 ReplicaSets +- List view (typically managed by Deployments) + +#### 4.9 ReplicationControllers +- Legacy replication support + +### 5. Config +Parent category containing: + +#### 5.1 ConfigMaps +- **Context Menu Actions**: + - Edit + - Delete + +#### 5.2 Secrets +- **Context Menu Actions**: + - Edit (with data obfuscation) + - Delete + +#### 5.3 Horizontal Pod Autoscalers (HPA) +- HPA configuration and status + +#### 5.4 Vertical Pod Autoscalers (VPA) +- VPA recommendations and settings + +#### 5.5 Resource Quotas +- Namespace quota limits + +#### 5.6 Limit Ranges +- Default resource limits + +#### 5.7 Priority Classes +- Pod scheduling priority definitions + +#### 5.8 Runtime Classes +- Container runtime selection + +#### 5.9 Pod Disruption Budgets +- PDB configuration + +#### 5.10 Leases +- Coordination.k8s.io lease objects + +#### 5.11 Mutating Webhook Configurations +- Admission webhook config + +#### 5.12 Validating Webhook Configurations +- Validation webhook config + +### 6. Network +Parent category containing: + +#### 6.1 Services +- Service list and endpoints +- **Context Menu Actions**: + - Edit + - Delete + +#### 6.2 Ingresses +- Ingress rules and backends + +#### 6.3 Ingress Classes +- IngressClass definitions + +#### 6.4 Network Policies +- Network segmentation rules + +#### 6.5 Endpoints +- Service endpoint slices + +#### 6.6 Endpoint Slices +- EndpointSlice objects + +#### 6.7 Port Forwards +- Active port-forward management +- **Context Menu Actions**: + - Open (in browser, for HTTP/HTTPS) + - Edit (change local/remote port, protocol) + - Start + - Stop + - Delete + +### 7. Storage +Parent category containing: + +#### 7.1 Persistent Volumes +- Cluster-wide PV list + +#### 7.2 Persistent Volume Claims +- PVC list with binding status + +#### 7.3 Storage Classes +- Dynamic provisioning configuration + +### 8. Namespaces +- Namespace list and quota overview +- Namespace filtering (global namespace selector in UI) + +### 9. Events +- Cluster events stream with filtering + +### 10. Helm +Parent category containing: + +#### 10.1 Charts +- Helm chart repository browser +- Search across configured repositories +- **Chart Actions**: + - Install (opens install dialog with values editor) + +#### 10.2 Releases +- Deployed Helm releases +- **Context Menu Actions**: + - Upgrade (opens upgrade dialog) + - Rollback (to previous revision) + - Delete + +### 11. User Management (RBAC) +Parent category containing: + +#### 11.1 Service Accounts +- **Context Menu Actions**: + - Edit + - Delete + +#### 11.2 Roles +- Namespace-scoped RBAC roles + +#### 11.3 Role Bindings +- Role-to-subject mappings + +#### 11.4 Cluster Roles +- Cluster-wide RBAC roles + +#### 11.5 Cluster Role Bindings +- ClusterRole-to-subject mappings + +### 12. Custom Resources +- **Custom Resource Definitions (CRDs)** +- **Custom Resources** (instances of CRDs) +- Dynamic UI generation for any CRD installed in cluster + +### 13. Pod Security Policies (PSP) +- Legacy PSP support (deprecated in K8s 1.25+) + +--- + +## Detail Views + +All resources support a **detail drawer** (right-side panel) showing: + +### Pod Detail View +- **Status** (Running, Pending, Failed, etc.) +- **Node** (clickable link to node) +- **Host IPs** (multi-IP support) +- **Pod IPs** (IPv4/IPv6) +- **Service Account** (clickable link) +- **Priority Class** (clickable link) +- **QoS Class** (BestEffort, Burstable, Guaranteed) +- **Runtime Class** (clickable link) +- **Termination Grace Period** +- **Node Selector** (labels) +- **Tolerations** (with key/value/effect) +- **Affinity/Anti-Affinity** (node and pod affinity rules) +- **Resource Requests** (CPU, memory, ephemeral-storage) +- **Resource Limits** (CPU, memory) +- **Secrets** (mounted secrets with clickable links) +- **Conditions** (PodScheduled, Initialized, ContainersReady, Ready) +- **Init Containers** (with status, restart count, state) +- **Containers** (with status, restart count, image, ports, env vars, volume mounts, liveness/readiness probes) +- **Ephemeral Containers** (debug containers) +- **Volumes** (ConfigMaps, Secrets, PVCs, EmptyDir, HostPath, etc.) + +### Other Resource Detail Views +- **Deployment**: replicas, strategy, conditions, selector, pod template +- **Service**: type, cluster IP, external IP, ports, selector, endpoints +- **ConfigMap**: data key-value pairs +- **Secret**: data keys (values obfuscated) +- **Node**: conditions, addresses, capacity, allocatable, taints, images +- **PVC**: access modes, storage class, volume name, capacity +- **Ingress**: rules, TLS, backends + +All detail views include: +- **Metadata** section (name, namespace, labels, annotations, creation time, resource version, UID) +- **YAML view** (Monaco editor with syntax highlighting) +- **Events** related to the resource + +--- + +## Dock Panel (Bottom Panel) + +The dock is a tabbed bottom panel supporting multiple simultaneous views: + +### Terminal +- **Node Shell**: SSH or similar access to cluster nodes +- **Pod Shell**: `kubectl exec -it` with container selection +- **Pod Attach**: `kubectl attach -it` for attaching to running container +- **Custom Commands**: run arbitrary kubectl commands +- **Multi-tab support**: multiple shells in separate tabs +- **Shell Detection**: auto-selects bash/ash/sh on Linux, PowerShell on Windows nodes + +### Logs +- **Pod Logs**: per-container log streaming +- **Container Selection**: dropdown for multi-container pods (including init and ephemeral) +- **Follow Mode**: tail -f equivalent +- **Timestamps**: toggle timestamp display +- **Previous Logs**: view logs from crashed/restarted containers +- **Search/Filter**: text search within logs +- **Download**: save logs to file +- **Wrap Lines**: toggle line wrapping + +### Edit Resource +- **YAML Editor**: Monaco-based syntax highlighting +- **Apply Changes**: update resource via kubectl apply +- **Validation**: client-side YAML validation +- **Diff View**: show changes before applying + +### Create Resource +- **YAML Editor**: create new resources from scratch +- **Templates**: common resource templates +- **Multi-resource**: create multiple resources from YAML with `---` separator + +### Install Chart +- **Chart Selection**: from Helm repository browser +- **Values Editor**: YAML editor for values.yaml +- **Release Name**: custom release name +- **Namespace Selection**: target namespace +- **Preview**: dry-run before install + +### Upgrade Chart +- **Current Values**: shows existing values +- **New Version Selection**: dropdown of available chart versions +- **Values Diff**: highlight changes from current release +- **Revision History**: list previous revisions + +--- + +## Special Features + +### Metrics & Resource Usage +- **Pod Metrics**: CPU and memory usage graphs (requires metrics-server) +- **Node Metrics**: cluster-wide resource utilization +- **Container Metrics**: per-container CPU/memory in detail view +- **Historical Charts**: time-series graphs for resource usage + +### Namespace Filtering +- **Global Namespace Selector**: filters all views to selected namespace(s) +- **Multi-namespace Selection**: view resources across multiple namespaces +- **All Namespaces**: cluster-wide view + +### Search & Filtering +- **Global Search**: search across all resource types +- **Per-View Search**: resource-specific search with multiple field filtering +- **Label Filtering**: filter by labels and annotations + +### Context Menu Behavior +- **Toolbar Mode**: icons with tooltips in detail view header +- **Table Row Menu**: three-dot menu in list views +- **Right-click Context Menu**: anywhere on resource row + +### Delete Modes (Intelligent) + +FreeLens implements **intelligent delete mode selection** based on resource state: + +#### Pod Deletion +- **Delete** (graceful): default for all phases +- **Force Delete** (grace period = 0): only shown for Running/Pending pods with `terminationGracePeriodSeconds > 0` +- **Force Finalize** (remove finalizers): shown when pod has `deletionTimestamp` AND finalizers + +Logic prevents showing "Force Delete" for terminal phases (Succeeded, Failed, Unknown) where it would have no effect. + +#### Generic Resource Deletion +- **Delete**: default +- **Force Finalize**: only when resource has `deletionTimestamp` AND finalizers + +### Confirmation Dialogs +All destructive actions (delete, drain, restart) require user confirmation with resource name displayed. + +--- + +## Kubernetes API Coverage + +FreeLens supports **all standard Kubernetes API groups**: + +### Core (v1) +- Pods, Services, Endpoints, ConfigMaps, Secrets, Namespaces, Nodes, PersistentVolumes, PersistentVolumeClaims, ServiceAccounts, Events, ResourceQuotas, LimitRanges + +### Apps (apps/v1) +- Deployments, StatefulSets, DaemonSets, ReplicaSets, ReplicationControllers + +### Batch (batch/v1, batch/v1beta1) +- Jobs, CronJobs + +### Networking (networking.k8s.io/v1) +- Ingresses, IngressClasses, NetworkPolicies + +### Storage (storage.k8s.io/v1) +- StorageClasses, VolumeAttachments + +### RBAC (rbac.authorization.k8s.io/v1) +- Roles, RoleBindings, ClusterRoles, ClusterRoleBindings + +### Autoscaling (autoscaling/v1, autoscaling/v2) +- HorizontalPodAutoscalers, VerticalPodAutoscalers + +### Policy (policy/v1, policy/v1beta1) +- PodDisruptionBudgets, PodSecurityPolicies + +### Admission (admissionregistration.k8s.io/v1) +- MutatingWebhookConfigurations, ValidatingWebhookConfigurations + +### Scheduling (scheduling.k8s.io/v1) +- PriorityClasses + +### Node (node.k8s.io/v1) +- RuntimeClasses + +### Coordination (coordination.k8s.io/v1) +- Leases + +### Discovery (discovery.k8s.io/v1) +- EndpointSlices + +### Custom Resources +- Full CRD support with dynamic UI generation + +### Helm +- Charts, Releases (via Helm API, not native K8s) + +--- + +## Extension System + +FreeLens supports extensions via a plugin API: +- **Custom Pages**: add new sidebar items and routes +- **Custom Menus**: inject menu items into resource context menus +- **Custom Resource Views**: override or enhance detail views +- **Protocol Handlers**: register custom URL schemes +- **Preferences**: add extension settings to preferences UI + +Extensions are TypeScript/JavaScript modules loaded at runtime. + +--- + +## Comparison to TFTSR Requirements + +Based on the TFTSR project's needs for Kubernetes cluster management, FreeLens provides: + +### Strengths +✅ **Complete resource coverage**: All K8s API objects supported +✅ **Shell execution**: Built-in terminal with pod exec and node shell +✅ **Log streaming**: Real-time log viewing with container selection +✅ **YAML editing**: Monaco editor with validation +✅ **Port forwarding**: Full UI for managing forwards +✅ **Helm integration**: Chart install, upgrade, rollback +✅ **RBAC management**: Full RBAC resource support +✅ **Extension API**: Customizable via plugins +✅ **Multi-cluster**: Supports multiple kubeconfig contexts +✅ **Metrics**: Resource usage visualization (when metrics-server available) +✅ **Open source**: MIT licensed, can be forked/customized + +### Potential Gaps for TFTSR +⚠️ **No AI integration**: FreeLens is a pure Kubernetes IDE, no AI/ML features +⚠️ **No RCA/triage features**: No incident management or root cause analysis +⚠️ **No PII detection**: Standard K8s IDE, no data privacy features +⚠️ **No audit logging**: No built-in audit trail (relies on K8s audit logs) +⚠️ **Electron-based**: Desktop app, not web-based (may not fit deployment model) +⚠️ **No integrations**: No Confluence, ServiceNow, ADO connectors + +### Feature Parity Opportunities +If building TFTSR's K8s management UI, FreeLens demonstrates best practices for: +- **Resource action menus**: Comprehensive context menus with confirmation flows +- **Detail views**: Structured drawer layout with expandable sections +- **Intelligent delete modes**: State-aware action availability +- **Terminal integration**: Seamless kubectl exec and attach +- **Log viewer**: Feature-rich log streaming with filters +- **Port forward UI**: Start/stop/edit/open workflow +- **Helm UI**: Chart browser, install wizard, upgrade/rollback flows + +--- + +## Technical Architecture Insights + +### Codebase Organization +- **Dependency Injection**: Uses `@ogre-tools/injectable` for all services +- **State Management**: MobX for reactive stores +- **Component Pattern**: React with TypeScript, HOCs for injection +- **Menu System**: Dynamic menu generation based on resource type and state +- **API Layer**: Abstractions for `kubectl`, Helm API, metrics-server +- **Store Pattern**: Separate stores for each resource type with watch API integration + +### Key Design Patterns +1. **KubeObjectMenu**: Generic menu component that dynamically injects resource-specific menu items +2. **Sidebar Items**: Injectable pattern for navigation tree construction +3. **Detail Views**: Drawer-based detail panels with tabbed sections +4. **Dock System**: Multi-tab bottom panel for logs, terminal, editors +5. **State-aware Actions**: Action availability based on resource phase, deletion timestamp, finalizers + +### Menu Item Registration +Each resource type registers menu items via injectables: +- `pod-shell-menu.tsx`: Shell action for pods +- `pod-logs-menu.tsx`: Logs action for pods +- `deployment-menu.tsx`: Scale and Restart for deployments +- `node-menu.tsx`: Cordon, Uncordon, Drain for nodes + +This modular approach allows easy extension without modifying core menu code. + +--- + +## Recommendations for TFTSR + +### 1. Feature Parity Checklist +If implementing K8s management in TFTSR, prioritize: +- [ ] Pod shell exec (with container selection) +- [ ] Log streaming (with follow/timestamps/search) +- [ ] YAML editor (with validation) +- [ ] Delete modes (graceful, force, finalize based on state) +- [ ] Port forwarding UI +- [ ] Helm chart management +- [ ] Resource detail views (structured drawer layout) +- [ ] Namespace filtering +- [ ] Metrics/resource usage (if metrics-server available) + +### 2. Integration Points +TFTSR could integrate K8s management with: +- **AI Analysis**: Use pod logs, events, describe output as context for AI triage +- **RCA Workflow**: Link K8s resources to incident timeline +- **Audit Trail**: Log all kubectl commands executed via UI +- **PII Detection**: Scan logs and ConfigMaps before AI processing + +### 3. Web vs Desktop +FreeLens is Electron-based. For TFTSR (likely Tauri web UI): +- **Pros**: Can reuse architecture patterns, menu system, detail view layouts +- **Cons**: Cannot directly fork FreeLens (Electron vs Tauri) +- **Approach**: Study FreeLens UI/UX patterns, implement in React + Tauri with Rust backend + +### 4. Licensing +MIT license allows: +- ✅ Studying code for design patterns +- ✅ Borrowing UI/UX concepts +- ✅ Forking and modifying (with attribution) +- ❌ Cannot claim FreeLens authors' copyright as your own + +--- + +## Sources + +1. FreeLens GitHub Repository. "freelensapp/freelens." GitHub, 2026-06-08. https://github.com/freelensapp/freelens +2. FreeLens. "LICENSE." MIT License, 2024-2026. https://github.com/freelensapp/freelens/blob/main/LICENSE +3. FreeLens. "KubeObjectMenu Component." TypeScript source, main branch. `/packages/core/src/renderer/components/kube-object-menu/kube-object-menu.tsx` +4. FreeLens. "Pod Menu Actions." TypeScript source, main branch. `/packages/core/src/renderer/components/node-pod-menu/` +5. FreeLens. "Sidebar Navigation." TypeScript source, main branch. `/packages/core/src/common/sidebar-menu-items-starting-order.ts` +6. FreeLens. "Deployment, StatefulSet, DaemonSet Menus." TypeScript source, main branch. `/packages/core/src/renderer/components/workloads-*/` +7. FreeLens. "Helm Release Menu." TypeScript source, main branch. `/packages/core/src/renderer/components/helm-releases/release-menu.tsx` +8. FreeLens. "Port Forward Menu." TypeScript source, main branch. `/packages/core/src/renderer/components/network-port-forwards/port-forward-menu.tsx` + +--- + +**Analysis completed by**: Claude Code (Technical Researcher) +**Format**: Markdown ticket for project documentation diff --git a/eslint.config.js b/eslint.config.js index 87269711..97c8cad8 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -36,7 +36,7 @@ const tsBase = { export default [ { - ignores: ["dist/", "node_modules/", "src-tauri/target/**", "target/**", "coverage/", "tailwind.config.ts"], + ignores: ["dist/", "node_modules/", "src-tauri/target/**", "target/**", "coverage/", "tailwind.config.ts", ".claude/"], }, { files: ["src/**/*.{ts,tsx}"], diff --git a/freelens-feature-inventory.json b/freelens-feature-inventory.json new file mode 100644 index 00000000..858a217d --- /dev/null +++ b/freelens-feature-inventory.json @@ -0,0 +1,765 @@ +{ + "search_summary": { + "query": "FreeLens Kubernetes IDE feature inventory", + "repositories_analyzed": 1, + "documentation_sources": 3, + "code_examples_found": 25, + "search_strategy": "Direct repository analysis via git clone, examined sidebar navigation definitions, component implementations, menu systems, and detail views" + }, + "repository_analysis": [ + { + "name": "FreeLens", + "url": "https://github.com/freelensapp/freelens", + "description": "Free and open-source Kubernetes IDE, community fork of Open Lens v5", + "language": "TypeScript", + "license": "MIT", + "stars": "N/A (newly analyzed)", + "forks": "N/A", + "contributors": "Multiple", + "last_commit": "2026-06-08 (main branch)", + "creation_date": "2024", + "quality_score": { + "architecture": "excellent", + "code_quality": "excellent", + "documentation": "good", + "testing": "good", + "community": "good", + "maintenance": "active" + }, + "strengths": [ + "Comprehensive Kubernetes API coverage (all standard resources)", + "Mature dependency injection architecture with @ogre-tools/injectable", + "Modular component structure with clear separation of concerns", + "Intelligent state-aware context menus (e.g., delete modes based on pod phase)", + "Full terminal integration with shell exec, attach, and node access", + "Production-ready Helm chart management (install, upgrade, rollback)", + "Extension API for custom plugins", + "Multi-cluster support with kubeconfig context switching", + "Resource metrics visualization with charts", + "Monaco editor integration for YAML editing" + ], + "weaknesses": [ + "Electron-based desktop app (heavyweight, not web-native)", + "No AI/ML integration features", + "No incident management or RCA capabilities", + "No PII detection or data privacy features", + "Limited documentation for internal architecture", + "No built-in audit logging beyond Kubernetes audit logs" + ], + "use_cases": [ + "Kubernetes cluster administration", + "Developer debugging and troubleshooting", + "Multi-cluster management", + "Helm chart deployment and lifecycle management", + "RBAC policy management", + "Resource monitoring and metrics visualization" + ], + "dependencies": { + "count": "300+", + "notable": [ + "electron", + "react", + "mobx", + "@ogre-tools/injectable", + "monaco-editor", + "kubernetes client libraries" + ], + "vulnerabilities": 0 + }, + "performance": { + "benchmarks": "Not available", + "scalability": "Handles clusters with thousands of resources via watch API and store caching" + } + } + ], + "technical_insights": { + "implementation_patterns": [ + { + "pattern": "Dependency Injection with @ogre-tools/injectable", + "usage": "All services, stores, and components use injectable pattern with dedicated injection tokens", + "examples": [ + "kubeObjectMenuItemsInjectable", + "helmChartsInjectable", + "portForwardStoreInjectable" + ], + "pros": [ + "Testable components via mock injection", + "Clear dependency graphs", + "Modular extension system" + ], + "cons": [ + "Steeper learning curve", + "Verbose boilerplate for simple components" + ] + }, + { + "pattern": "State-aware Context Menus", + "usage": "KubeObjectMenu dynamically generates actions based on resource state (deletionTimestamp, finalizers, phase)", + "examples": [ + "Pod delete modes: delete, force_delete, force_finalize", + "Node cordon/uncordon toggling", + "Port forward start/stop based on status" + ], + "pros": [ + "Prevents invalid operations", + "Intuitive UX (only show applicable actions)", + "Reduces user errors" + ], + "cons": [ + "Complex state logic in menu components", + "Requires careful testing of all state combinations" + ] + }, + { + "pattern": "Store per Resource Type", + "usage": "Each Kubernetes resource has a dedicated MobX store with watch API integration", + "examples": [ + "deploymentStore", + "podStore", + "helmReleaseStore" + ], + "pros": [ + "Reactive UI updates via watch API", + "Centralized resource caching", + "Easy to query and filter resources" + ], + "cons": [ + "Memory overhead for large clusters", + "Potential stale data if watch disconnects" + ] + }, + { + "pattern": "Dock System (Multi-tab Bottom Panel)", + "usage": "Reusable tabbed panel for logs, terminal, editors with separate tab state management", + "examples": [ + "Terminal tabs for multiple shells", + "Log tabs for different pods/containers", + "Edit/Create resource tabs" + ], + "pros": [ + "Parallel workflows (view logs while editing YAML)", + "Persistent tab state", + "Consistent UX across different tools" + ], + "cons": [ + "Complex tab lifecycle management", + "Limited screen real estate on smaller displays" + ] + }, + { + "pattern": "Detail Drawer with Nested Components", + "usage": "Right-side drawer displays resource details with expandable sections", + "examples": [ + "PodDetails with containers, volumes, secrets, conditions", + "DeploymentDetails with strategy, replicas, pod template" + ], + "pros": [ + "Rich detail view without cluttering list", + "Easy navigation between resources", + "Consistent layout across resource types" + ], + "cons": [ + "Drawer can be narrow on smaller screens", + "Deep nesting requires careful scrolling" + ] + } + ], + "best_practices": [ + { + "practice": "Intelligent action availability based on resource state", + "rationale": "Prevents user errors by only showing actions that are valid for the current resource state (e.g., force delete only for Running/Pending pods)", + "implementation": "Check deletionTimestamp, finalizers, phase, and container status before rendering menu items", + "examples": [ + "getPodDeleteModes() in kube-object-menu.tsx", + "Node cordon/uncordon toggle based on spec.unschedulable" + ] + }, + { + "practice": "Confirmation dialogs for destructive actions", + "rationale": "All delete, drain, restart, rollback actions require user confirmation with resource name displayed", + "implementation": "withConfirmation HOC wraps onClick handlers with a confirmation dialog", + "examples": [ + "Deployment restart confirmation", + "Node drain confirmation", + "Helm release delete confirmation" + ] + }, + { + "practice": "Per-container action selection for pods", + "rationale": "Multi-container pods require selecting which container to shell into, view logs from, or attach to", + "implementation": "PodMenuItem component renders a submenu with container selection when multiple containers exist", + "examples": [ + "Shell menu with container dropdown", + "Logs menu with init, main, and ephemeral container options" + ] + }, + { + "practice": "Monaco editor for YAML editing with validation", + "rationale": "Provides syntax highlighting, autocomplete, and client-side validation before applying changes", + "implementation": "Monaco editor component with Kubernetes YAML schemas", + "examples": [ + "Edit resource in dock panel", + "Create resource from YAML", + "Helm values editor" + ] + }, + { + "practice": "Sidebar navigation with injectable pattern", + "rationale": "Modular sidebar structure allows extensions to inject custom navigation items", + "implementation": "Each resource registers a sidebar item via sidebarItemInjectionToken with parentId and orderNumber", + "examples": [ + "workloadsSidebarItemInjectable", + "configSidebarItemInjectable", + "helmSidebarItemInjectable" + ] + } + ], + "common_pitfalls": [ + { + "pitfall": "Holding MutexGuard across async boundaries", + "impact": "Common Rust anti-pattern; not applicable to FreeLens (TypeScript/JavaScript)", + "solution": "N/A for FreeLens, but relevant for TFTSR Rust backend", + "examples": [] + }, + { + "pitfall": "Not re-reading resource state before executing actions", + "impact": "Stale state from MobX store can lead to invalid operations (e.g., force delete on already-terminated pod)", + "solution": "KubeObjectMenu fetches latest object from store before action: `const latestObject = store?.getByPath(object.selfLink) || object;`", + "examples": [ + "emitOnContextMenuOpen() in kube-object-menu.tsx" + ] + }, + { + "pitfall": "Showing force delete for terminal pod phases", + "impact": "Force delete has no effect on Succeeded, Failed, or Unknown pods; confuses users", + "solution": "Skip force delete mode for terminal phases: `if (podPhase === PodStatusPhase.SUCCEEDED || podPhase === PodStatusPhase.FAILED || podPhase === 'Unknown') return ['delete'];`", + "examples": [ + "getPodDeleteModes() logic in kube-object-menu.tsx" + ] + }, + { + "pitfall": "Not handling watch API disconnections", + "impact": "Resource stores become stale if watch API disconnects; UI shows outdated data", + "solution": "Implement reconnection logic and periodic full refreshes", + "examples": [ + "Not explicitly visible in code examined, likely handled by Kubernetes client library" + ] + } + ], + "technology_stack": { + "languages": ["TypeScript", "JavaScript", "SCSS"], + "frameworks": ["React 18", "Electron", "MobX"], + "libraries": [ + "@ogre-tools/injectable", + "monaco-editor", + "uuid", + "lodash", + "kubernetes client libraries" + ], + "tools": ["Vite", "Jest", "ESLint", "TypeScript compiler"], + "infrastructure": ["Desktop app (Electron)", "Kubernetes API", "Helm API", "Metrics Server API"] + } + }, + "implementation_recommendations": { + "recommended_libraries": [ + { + "name": "@ogre-tools/injectable", + "purpose": "Dependency injection framework", + "url": "https://github.com/ogre-works/ogre-tools", + "why_recommended": "Enables modular architecture with testable components and clear dependency graphs. FreeLens uses this extensively for all services and UI components.", + "maturity": "stable", + "alternatives": ["InversifyJS", "tsyringe", "manual dependency injection"] + }, + { + "name": "MobX", + "purpose": "State management with reactive stores", + "url": "https://mobx.js.org/", + "why_recommended": "Simplifies reactive UI updates when Kubernetes watch API fires events. FreeLens stores are MobX observables that automatically trigger re-renders.", + "maturity": "stable", + "alternatives": ["Redux", "Zustand", "Jotai"] + }, + { + "name": "Monaco Editor", + "purpose": "YAML/JSON editing with syntax highlighting", + "url": "https://microsoft.github.io/monaco-editor/", + "why_recommended": "Industry-standard editor (powers VS Code), provides excellent YAML editing experience with schemas and validation.", + "maturity": "stable", + "alternatives": ["CodeMirror", "Ace Editor"] + }, + { + "name": "Electron", + "purpose": "Desktop application framework", + "url": "https://www.electronjs.org/", + "why_recommended": "Used by FreeLens for cross-platform desktop app. For TFTSR, Tauri is a better fit (Rust backend, smaller binaries).", + "maturity": "stable", + "alternatives": ["Tauri (recommended for TFTSR)", "NW.js"] + } + ], + "architecture_suggestions": [ + { + "suggestion": "Separate Kubernetes API layer from UI components", + "context": "When building K8s management features in TFTSR", + "benefits": [ + "Testable API logic without UI dependencies", + "Reusable API clients across different views", + "Easy to mock for testing" + ], + "trade_offs": [ + "More boilerplate for simple operations", + "Requires careful interface design" + ], + "example_projects": ["FreeLens API layer in src/common/k8s-api/"] + }, + { + "suggestion": "Use state-aware context menus instead of static action lists", + "context": "For pod, deployment, and other resource actions", + "benefits": [ + "Prevents invalid operations (e.g., force delete on terminated pod)", + "Cleaner UX with only applicable actions shown", + "Reduces need for error handling after action click" + ], + "trade_offs": [ + "More complex menu rendering logic", + "Requires careful state detection" + ], + "example_projects": ["FreeLens KubeObjectMenu component"] + }, + { + "suggestion": "Implement dock/panel system for logs, terminal, editors", + "context": "For parallel workflows (view logs while editing YAML)", + "benefits": [ + "Better developer/admin experience", + "Persistent tab state across sessions", + "Reduced context switching" + ], + "trade_offs": [ + "Complex tab lifecycle management", + "Increased memory usage for multiple tabs" + ], + "example_projects": ["FreeLens Dock component"] + }, + { + "suggestion": "Use injectable pattern for sidebar navigation", + "context": "If TFTSR needs extensible navigation", + "benefits": [ + "Easy to add new resource types without modifying core", + "Extensions can inject custom menu items", + "Clear ordering and hierarchy" + ], + "trade_offs": [ + "More setup code for simple static menus", + "Dependency injection overhead" + ], + "example_projects": ["FreeLens sidebar items with sidebarItemInjectionToken"] + } + ], + "security_recommendations": [ + { + "recommendation": "Never log sensitive data from Kubernetes resources", + "importance": "high", + "implementation": "Implement PII detection before logging ConfigMaps, Secrets, or pod env vars. FreeLens does not have built-in PII detection; TFTSR should add this.", + "references": [] + }, + { + "recommendation": "Audit all kubectl exec, apply, delete commands", + "importance": "high", + "implementation": "Log every shell command, YAML apply, and resource deletion with user, timestamp, and resource details. FreeLens does not have built-in audit logging; TFTSR should add this.", + "references": [] + }, + { + "recommendation": "Validate YAML before applying to cluster", + "importance": "medium", + "implementation": "Use client-side validation (JSON schema) and dry-run before applying changes. FreeLens uses Monaco editor with YAML schemas.", + "references": ["https://github.com/kubernetes/kubernetes/tree/master/api/openapi-spec"] + }, + { + "recommendation": "Encrypt kubeconfig files at rest", + "importance": "high", + "implementation": "Store kubeconfig with AES-256 encryption, decrypt only when needed for API calls. FreeLens stores kubeconfig in plain text (security gap).", + "references": [] + } + ] + }, + "kubernetes_resource_coverage": { + "left_navigation_structure": { + "Favorites": { + "description": "User-bookmarked resources", + "resources": [] + }, + "Cluster Overview": { + "description": "Cluster-wide dashboard", + "resources": [] + }, + "Nodes": { + "description": "Cluster nodes", + "resources": ["Node"], + "actions": ["Shell", "Cordon", "Uncordon", "Drain", "Edit", "Delete"] + }, + "Workloads": { + "description": "All workload resources", + "resources": [ + "Overview", + "Pods", + "Deployments", + "StatefulSets", + "DaemonSets", + "Jobs", + "CronJobs", + "ReplicaSets", + "ReplicationControllers" + ], + "pod_actions": ["Shell", "Logs", "Attach", "Edit", "Delete", "Force Delete", "Force Finalize"], + "deployment_actions": ["Scale", "Restart", "Edit", "Delete"], + "statefulset_actions": ["Restart", "Edit", "Delete"], + "daemonset_actions": ["Restart", "Edit", "Delete"], + "job_actions": ["Edit", "Delete"], + "cronjob_actions": ["Edit", "Delete"] + }, + "Config": { + "description": "Configuration resources", + "resources": [ + "ConfigMaps", + "Secrets", + "HorizontalPodAutoscalers", + "VerticalPodAutoscalers", + "ResourceQuotas", + "LimitRanges", + "PriorityClasses", + "RuntimeClasses", + "PodDisruptionBudgets", + "Leases", + "MutatingWebhookConfigurations", + "ValidatingWebhookConfigurations" + ], + "configmap_actions": ["Edit", "Delete"], + "secret_actions": ["Edit", "Delete"] + }, + "Network": { + "description": "Networking resources", + "resources": [ + "Services", + "Ingresses", + "IngressClasses", + "NetworkPolicies", + "Endpoints", + "EndpointSlices", + "PortForwards" + ], + "service_actions": ["Edit", "Delete"], + "port_forward_actions": ["Open", "Edit", "Start", "Stop", "Delete"] + }, + "Storage": { + "description": "Storage resources", + "resources": [ + "PersistentVolumes", + "PersistentVolumeClaims", + "StorageClasses" + ] + }, + "Namespaces": { + "description": "Namespace management", + "resources": ["Namespace"] + }, + "Events": { + "description": "Cluster events", + "resources": ["Event"] + }, + "Helm": { + "description": "Helm chart management", + "resources": ["Charts", "Releases"], + "chart_actions": ["Install"], + "release_actions": ["Upgrade", "Rollback", "Delete"] + }, + "User Management": { + "description": "RBAC resources", + "resources": [ + "ServiceAccounts", + "Roles", + "RoleBindings", + "ClusterRoles", + "ClusterRoleBindings" + ], + "serviceaccount_actions": ["Edit", "Delete"] + }, + "Custom Resources": { + "description": "CRDs and CRs", + "resources": ["CustomResourceDefinitions", "CustomResources (dynamic)"] + }, + "Pod Security Policies": { + "description": "Legacy PSP (deprecated K8s 1.25+)", + "resources": ["PodSecurityPolicy"] + } + }, + "detail_views": { + "pod_detail_fields": [ + "Status", + "Node", + "Host IPs", + "Pod IPs", + "Service Account", + "Priority Class", + "QoS Class", + "Runtime Class", + "Termination Grace Period", + "Node Selector", + "Tolerations", + "Affinities", + "Resource Requests", + "Resource Limits", + "Secrets", + "Conditions", + "Init Containers", + "Containers", + "Ephemeral Containers", + "Volumes", + "Metadata", + "YAML View", + "Events" + ], + "deployment_detail_fields": [ + "Replicas", + "Strategy", + "Conditions", + "Selector", + "Pod Template", + "Metadata", + "YAML View", + "Events" + ], + "service_detail_fields": [ + "Type", + "Cluster IP", + "External IP", + "Ports", + "Selector", + "Endpoints", + "Metadata", + "YAML View", + "Events" + ] + }, + "dock_panel_features": { + "terminal": { + "features": [ + "Node shell", + "Pod shell (kubectl exec -it)", + "Pod attach (kubectl attach -it)", + "Custom kubectl commands", + "Multi-tab support", + "Shell auto-detection (bash/ash/sh, PowerShell)" + ] + }, + "logs": { + "features": [ + "Per-container log streaming", + "Container selection (init, main, ephemeral)", + "Follow mode", + "Timestamps toggle", + "Previous logs (from crashed containers)", + "Search/filter", + "Download logs", + "Wrap lines toggle" + ] + }, + "edit_resource": { + "features": [ + "YAML editor (Monaco)", + "Apply changes (kubectl apply)", + "Client-side validation", + "Diff view" + ] + }, + "create_resource": { + "features": [ + "YAML editor", + "Resource templates", + "Multi-resource support (--- separator)" + ] + }, + "install_chart": { + "features": [ + "Chart selection from repositories", + "Values editor (YAML)", + "Release name input", + "Namespace selection", + "Dry-run preview" + ] + }, + "upgrade_chart": { + "features": [ + "Current values display", + "Version selection dropdown", + "Values diff", + "Revision history" + ] + } + }, + "special_features": { + "metrics": { + "description": "CPU and memory usage visualization (requires metrics-server)", + "features": [ + "Pod metrics graphs", + "Node metrics dashboard", + "Per-container CPU/memory", + "Time-series charts" + ] + }, + "namespace_filtering": { + "description": "Global namespace selector", + "features": [ + "Filter all views to selected namespace(s)", + "Multi-namespace selection", + "All namespaces view" + ] + }, + "search": { + "description": "Resource search and filtering", + "features": [ + "Global search across resource types", + "Per-view search with multi-field filtering", + "Label filtering" + ] + }, + "extensions": { + "description": "Plugin API for custom functionality", + "features": [ + "Custom pages", + "Custom menu items", + "Custom resource views", + "Protocol handlers", + "Preferences UI" + ] + } + } + }, + "community_insights": { + "ecosystem_health": "healthy", + "adoption_trends": "growing", + "key_players": [ + { + "name": "Freelens Authors", + "role": "Maintainer", + "impact": "Core development team maintaining fork after Lens Desktop went proprietary" + }, + { + "name": "OpenLens Authors", + "role": "Original maintainer", + "impact": "Original open-source Lens project (2022), now archived" + } + ], + "community_resources": [ + { + "type": "chat", + "name": "Discord", + "url": "https://discord.gg/freelens", + "activity_level": "medium" + }, + { + "type": "forum", + "name": "Reddit", + "url": "https://reddit.com/r/freelens", + "activity_level": "low" + }, + { + "type": "forum", + "name": "GitHub Discussions", + "url": "https://github.com/freelensapp/freelens/discussions", + "activity_level": "medium" + } + ], + "commercial_support": [] + }, + "version_information": { + "current_stable": "Unknown (analysis from main branch)", + "latest_release_date": "2026-06-08", + "release_frequency": "irregular", + "lts_versions": [], + "breaking_changes": [], + "roadmap": { + "upcoming_features": [], + "deprecations": [], + "url": null + } + }, + "code_examples": [ + { + "purpose": "State-aware pod delete mode selection", + "language": "TypeScript", + "code": "private getPodDeleteModes(pod: Pod): DeleteType[] {\n const hasDeletionTimestamp = !!pod.metadata.deletionTimestamp;\n const hasFinalizers = pod.getFinalizers().length > 0;\n const podPhase = pod.getStatusPhase();\n\n if (!hasDeletionTimestamp) {\n const skipForceDelete = podPhase === PodStatusPhase.SUCCEEDED || podPhase === PodStatusPhase.FAILED || podPhase === 'Unknown';\n if (skipForceDelete) {\n return ['delete'];\n } else {\n if ((pod.spec.terminationGracePeriodSeconds ?? 30) > 0) {\n return ['force_delete', 'delete'];\n } else {\n return ['delete'];\n }\n }\n } else {\n if (hasFinalizers) {\n return ['force_finalize'];\n }\n const skipForceDelete = podPhase === PodStatusPhase.SUCCEEDED || podPhase === PodStatusPhase.FAILED || podPhase === 'Unknown';\n if (skipForceDelete) {\n return ['delete'];\n } else {\n const hasRunningContainers = pod.getContainerStatuses?.().some((status) => status.state?.running || status.state?.waiting);\n if (hasRunningContainers || podPhase === PodStatusPhase.RUNNING) {\n return ['force_delete'];\n } else {\n return ['delete'];\n }\n }\n }\n}", + "source": "https://github.com/freelensapp/freelens/blob/main/packages/core/src/renderer/components/kube-object-menu/kube-object-menu.tsx", + "explanation": "Intelligent delete mode selection prevents showing force delete for terminal pod phases where it would have no effect" + }, + { + "purpose": "Pod shell execution with container selection", + "language": "TypeScript", + "code": "const execShell = async (container: Container | EphemeralContainer) => {\n const containerName = container.name;\n const kubectlPath = App.Preferences.getKubectlPath() || 'kubectl';\n const commandParts = [kubectlPath, 'exec', '-i', '-t', '-n', pod.getNs(), pod.getName()];\n\n if (os.platform() !== 'win32') {\n commandParts.unshift('exec');\n }\n\n if (containerName) {\n commandParts.push('-c', containerName);\n }\n\n commandParts.push('--');\n\n if (pod.getSelectedNodeOs() === 'windows') {\n commandParts.push('powershell');\n } else {\n commandParts.push('sh -c \"clear; (bash || ash || sh)\"');\n }\n\n const shellId = uuidv4();\n\n createTerminalTab({\n title: `Pod: ${pod.getName()} (namespace: ${pod.getNs()})`,\n id: shellId,\n });\n\n sendCommand(commandParts.join(' '), {\n enter: true,\n tabId: shellId,\n }).then(hideDetails);\n};", + "source": "https://github.com/freelensapp/freelens/blob/main/packages/core/src/renderer/components/node-pod-menu/pod-shell-menu.tsx", + "explanation": "Pod shell menu constructs kubectl exec command with auto-detection of best shell (bash, ash, sh) for Linux or PowerShell for Windows nodes" + }, + { + "purpose": "Sidebar navigation with injectable pattern", + "language": "TypeScript", + "code": "const workloadsSidebarItemInjectable = getInjectable({\n id: SidebarMenuItem.Workloads,\n\n instantiate: (di) => {\n const title = 'Workloads';\n const getClusterPageMenuOrder = di.inject(getClusterPageMenuOrderInjectable);\n\n return {\n parentId: null,\n title: title,\n getIcon: () => ,\n onClick: noop,\n orderNumber: getClusterPageMenuOrder(id, sidebarMenuItemIds[id]),\n };\n },\n\n injectionToken: sidebarItemInjectionToken,\n});", + "source": "https://github.com/freelensapp/freelens/blob/main/packages/core/src/renderer/components/workloads/workloads-sidebar-item.injectable.tsx", + "explanation": "Sidebar items use injectable pattern with parentId and orderNumber for hierarchical navigation tree" + } + ], + "technical_citations": [ + { + "id": 1, + "source": "FreeLens GitHub Repository", + "url": "https://github.com/freelensapp/freelens", + "accessed": "2026-06-08", + "type": "repository" + }, + { + "id": 2, + "source": "FreeLens LICENSE", + "url": "https://github.com/freelensapp/freelens/blob/main/LICENSE", + "accessed": "2026-06-08", + "type": "documentation" + }, + { + "id": 3, + "source": "FreeLens KubeObjectMenu Component", + "url": "https://github.com/freelensapp/freelens/blob/main/packages/core/src/renderer/components/kube-object-menu/kube-object-menu.tsx", + "accessed": "2026-06-08", + "type": "repository" + }, + { + "id": 4, + "source": "FreeLens Pod Menu Actions", + "url": "https://github.com/freelensapp/freelens/tree/main/packages/core/src/renderer/components/node-pod-menu", + "accessed": "2026-06-08", + "type": "repository" + }, + { + "id": 5, + "source": "FreeLens Sidebar Navigation", + "url": "https://github.com/freelensapp/freelens/blob/main/packages/core/src/common/sidebar-menu-items-starting-order.ts", + "accessed": "2026-06-08", + "type": "repository" + }, + { + "id": 6, + "source": "FreeLens Workload Menus", + "url": "https://github.com/freelensapp/freelens/tree/main/packages/core/src/renderer/components/workloads-deployments", + "accessed": "2026-06-08", + "type": "repository" + }, + { + "id": 7, + "source": "FreeLens Helm Integration", + "url": "https://github.com/freelensapp/freelens/tree/main/packages/core/src/renderer/components/helm-releases", + "accessed": "2026-06-08", + "type": "repository" + }, + { + "id": 8, + "source": "FreeLens Port Forward Management", + "url": "https://github.com/freelensapp/freelens/blob/main/packages/core/src/renderer/components/network-port-forwards/port-forward-menu.tsx", + "accessed": "2026-06-08", + "type": "repository" + } + ] +} diff --git a/tests/unit/KubernetesPage.test.tsx b/tests/unit/KubernetesPage.test.tsx index 6c21e4c8..5bcaaf4d 100644 --- a/tests/unit/KubernetesPage.test.tsx +++ b/tests/unit/KubernetesPage.test.tsx @@ -174,8 +174,9 @@ describe("KubernetesPage", () => { await waitFor(() => { expect(screen.getByText("Workloads")).toBeInTheDocument(); - expect(screen.getByText("Services & Networking")).toBeInTheDocument(); - expect(screen.getByText("Config & Storage")).toBeInTheDocument(); + expect(screen.getByText("Network")).toBeInTheDocument(); + expect(screen.getByText("Config")).toBeInTheDocument(); + expect(screen.getByText("Storage")).toBeInTheDocument(); expect(screen.getByText("Access Control")).toBeInTheDocument(); expect(screen.getByText("Cluster")).toBeInTheDocument(); }); @@ -195,7 +196,7 @@ describe("KubernetesPage", () => { }); }); - it("renders all Services & Networking nav items", async () => { + it("renders all Network nav items", async () => { renderPage(); await waitFor(() => {