test(kube): fix stale nav section assertions + add research docs
Some checks failed
PR Review Automation / review (pull_request) Has been cancelled
Test / frontend-tests (pull_request) Successful in 1m40s
Test / frontend-typecheck (pull_request) Successful in 1m43s
Test / rust-fmt-check (pull_request) Successful in 10m59s
Test / rust-clippy (pull_request) Successful in 12m55s
Test / rust-tests (pull_request) Successful in 14m30s

KubernetesPage.test.tsx had two stale section heading assertions from
before the nav restructure:
- "Services & Networking" → "Network"
- "Config & Storage" → "Config" + "Storage" (now separate sections)
Also renamed the matching it() description for accuracy.

eslint.config.js: add .claude/ to ignores (session memory dir).

Adds FreeLens feature inventory (md + json) generated during
gap analysis research for this feature parity work.
This commit is contained in:
Shaun Arman 2026-06-08 20:48:02 -05:00
parent cd99e631a4
commit 7a6a47a21b
4 changed files with 1321 additions and 4 deletions

View File

@ -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

View File

@ -36,7 +36,7 @@ const tsBase = {
export default [ 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}"], files: ["src/**/*.{ts,tsx}"],

View File

@ -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: () => <Icon svg=\"workloads\" />,\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"
}
]
}

View File

@ -174,8 +174,9 @@ describe("KubernetesPage", () => {
await waitFor(() => { await waitFor(() => {
expect(screen.getByText("Workloads")).toBeInTheDocument(); expect(screen.getByText("Workloads")).toBeInTheDocument();
expect(screen.getByText("Services & Networking")).toBeInTheDocument(); expect(screen.getByText("Network")).toBeInTheDocument();
expect(screen.getByText("Config & Storage")).toBeInTheDocument(); expect(screen.getByText("Config")).toBeInTheDocument();
expect(screen.getByText("Storage")).toBeInTheDocument();
expect(screen.getByText("Access Control")).toBeInTheDocument(); expect(screen.getByText("Access Control")).toBeInTheDocument();
expect(screen.getByText("Cluster")).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(); renderPage();
await waitFor(() => { await waitFor(() => {