Files
Chris Farhood 24033ca977 docs: remove incorrect watchPlugins: false references
Remove all references to the incorrect `config.watchPlugins: false`
requirement that was believed necessary for Headlamp v0.39.0+.

Investigation revealed that plugins work correctly with the default
`watchPlugins: true` setting. The earlier documentation was based on
a misunderstanding of the plugin loading mechanism.

Changes:
- Remove watchPlugins: false from all YAML configuration examples
- Remove warning sections about watchPlugins requirement
- Update troubleshooting guides to focus on actual issues
- Simplify installation instructions by removing unnecessary config

Files updated:
- README.md (main installation docs and troubleshooting table)
- docs/DEPLOYMENT.md
- docs/TROUBLESHOOTING.md
- docs/getting-started/* (quick-start, installation, prerequisites)
- docs/deployment/* (helm, production)
- docs/troubleshooting/* (common-issues, README)
- Multiple other doc files formatted by prettier

This cleanup ensures ArtifactHub and GitHub documentation show
correct, simplified installation instructions.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
2026-02-13 09:54:15 -05:00

334 lines
13 KiB
Markdown

# Architecture Overview
High-level architecture of the Headlamp Polaris Plugin.
## Overview
The Headlamp Polaris Plugin is a **read-only dashboard** that surfaces Fairwinds Polaris audit results within the Headlamp UI. It fetches data from the Polaris dashboard API via the Kubernetes service proxy and presents it in a hierarchical navigation structure.
**Key Characteristics:**
- **Read-only:** No write operations to cluster or Polaris
- **Service proxy based:** Uses K8s API server proxy to reach Polaris
- **React Context for state:** Shared data fetch across components
- **Headlamp plugin API:** Integrates via official plugin system
- **Type-safe:** Full TypeScript with strict mode
## System Architecture
```
┌─────────────────────────────────────────────────────────────┐
│ Headlamp UI (React) │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ App Bar │ │ Sidebar │ │ Routes │ │
│ │ (Badge) │ │ (Navigation)│ │ (Views) │ │
│ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │
│ │ │ │ │
│ └──────────────────┼──────────────────┘ │
│ │ │
│ ┌────────▼────────┐ │
│ │ Plugin Registry │ │
│ └────────┬────────┘ │
│ │ │
│ ┌─────────────▼──────────────┐ │
│ │ Polaris Plugin │ │
│ ├────────────────────────────┤ │
│ │ • registerSidebarEntry │ │
│ │ • registerRoute │ │
│ │ • registerAppBarAction │ │
│ │ • registerPluginSettings │ │
│ │ • registerDetailsViewSection│ │
│ └─────────────┬──────────────┘ │
│ │ │
│ ┌─────────────▼──────────────┐ │
│ │ PolarisDataContext │ │
│ │ (React Context Provider) │ │
│ └─────────────┬──────────────┘ │
│ │ │
│ ┌──────────────────┼──────────────────┐ │
│ │ │ │ │
│ ┌────▼─────┐ ┌──────▼──────┐ ┌──────▼──────┐ │
│ │Dashboard │ │ Namespaces │ │ Namespace │ │
│ │View │ │ ListView │ │ Detail │ │
│ └──────────┘ └─────────────┘ └─────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
┌───────▼────────┐
│ ApiProxy │
│ (Headlamp) │
└───────┬────────┘
┌───────▼────────┐
│ Kubernetes │
│ API Server │
└───────┬────────┘
┌───────▼────────┐
│ Service Proxy │
│ /api/v1/ns/ │
│ polaris/svcs/ │
│ polaris- │
│ dashboard/ │
│ proxy/ │
└───────┬────────┘
┌───────▼────────┐
│ Polaris │
│ Dashboard │
│ (ClusterIP) │
└───────┬────────┘
┌───────▼────────┐
│ results.json │
│ (AuditData) │
└────────────────┘
```
## Component Hierarchy
### Plugin Entry Point
**`src/index.tsx`**
- Registers sidebar entries (Polaris → Overview, Namespaces)
- Registers routes (`/polaris`, `/polaris/namespaces`)
- Registers app bar action (score badge)
- Registers plugin settings page
- Registers details view section (inline audit)
### Data Layer
**`src/api/PolarisDataContext.tsx`**
- React Context Provider for shared data
- Fetches AuditData from Polaris dashboard
- Handles auto-refresh based on user settings
- Provides `{ data, loading, error, refresh }` to consumers
**`src/api/polaris.ts`**
- TypeScript types for AuditData schema
- Utility functions: `countResults()`, `computeScore()`
- Settings management: `getRefreshInterval()`, `setRefreshInterval()`
- Constants: `DASHBOARD_URL_DEFAULT`, `INTERVAL_OPTIONS`
**`src/api/checkMapping.ts`**
- Maps Polaris check IDs to human-readable names
- Used for display in UI (e.g., "hostIPCSet" → "Host IPC")
**`src/api/topIssues.ts`**
- Aggregates failing checks across cluster
- Groups by check ID and severity
- Used for top issues dashboard
### View Components
**`src/components/DashboardView.tsx`**
- **Route:** `/polaris`
- **Purpose:** Cluster-wide overview
- **Features:**
- Cluster score (percentage)
- Check distribution (pass/warning/danger/skipped)
- Cluster info (Polaris version, last audit time)
- Refresh button
- **Data:** Uses `usePolarisDataContext()`
**`src/components/NamespacesListView.tsx`**
- **Route:** `/polaris/namespaces`
- **Purpose:** List all namespaces with scores
- **Features:**
- Table with namespace, score, pass/warning/danger counts
- Clickable namespace buttons (opens drawer)
- Sorted by score (lowest first)
- **Data:** Uses `usePolarisDataContext()`, aggregates by namespace
**`src/components/NamespaceDetailView.tsx`**
- **Route:** Drawer on `/polaris/namespaces#<namespace>`
- **Purpose:** Namespace-level drill-down
- **Features:**
- Namespace score
- Resource table (kind, name, score, counts)
- URL hash navigation
- Keyboard shortcuts (Escape to close)
- **Data:** Filters `usePolarisDataContext()` by namespace
### UI Components
**`src/components/AppBarScoreBadge.tsx`**
- **Location:** Headlamp app bar (top-right)
- **Purpose:** Quick cluster score visibility
- **Features:**
- Color-coded badge (green ≥80%, orange ≥50%, red <50%)
- Clickable (navigates to `/polaris`)
- Shield emoji icon
- **Data:** Uses `usePolarisDataContext()`
**`src/components/PolarisSettings.tsx`**
- **Location:** Settings → Plugins → Polaris
- **Purpose:** Plugin configuration
- **Features:**
- Refresh interval selector (1 min to 30 min)
- Dashboard URL input (custom Polaris instances)
- Connection test button
- **Data:** localStorage for persistence
**`src/components/InlineAuditSection.tsx`**
- **Location:** Resource detail pages (Deployment, StatefulSet, etc.)
- **Purpose:** Show Polaris audit inline
- **Features:**
- Pass/warning/danger counts
- Check details with messages
- Severity badges
- **Data:** Uses `usePolarisDataContext()`, filters by resource
**`src/components/ExemptionManager.tsx`**
- **Location:** (Planned feature, UI exists but not fully integrated)
- **Purpose:** Manage Polaris exemptions via annotations
- **Features:**
- View current exemptions
- Add exemptions for failing checks
- Remove exemptions
## State Management
### Why React Context?
**Decision:** Use React Context instead of Redux/Zustand
**Rationale:**
1. **Simple state:** Single AuditData object shared across views
2. **Read-only:** No complex mutations or transactions
3. **Headlamp constraints:** Plugin cannot add dependencies (Redux not bundled)
4. **Performance:** Data changes infrequently (refresh interval 1-30 min)
### Context Structure
```typescript
interface PolarisDataContextValue {
data: AuditData | null; // Audit results or null if loading/error
loading: boolean; // True during initial fetch
error: string | null; // Error message if fetch failed
refresh: () => void; // Manual refresh function
}
```
### Data Fetching Strategy
1. **Initial fetch:** On first mount of any component using the context
2. **Auto-refresh:** Based on user setting (default 5 minutes)
3. **Manual refresh:** Via refresh button in UI
4. **Caching:** Data persists in context until refresh (no per-route refetch)
### localStorage Usage
Settings persisted in localStorage:
- **`polaris-plugin-refresh-interval`**: Number (seconds), default 300
- **`polaris-plugin-dashboard-url`**: String, default service proxy path
No sensitive data stored in localStorage.
## Integration Points
### Headlamp Plugin API
**Version:** ≥ v0.13.0
**Registration Functions Used:**
```typescript
// Sidebar navigation
registerSidebarEntry({ parent, name, label, url, icon });
// Routes
registerRoute({ path, sidebar, name, exact, component });
// App bar actions
registerAppBarAction(component);
// Plugin settings
registerPluginSettings(name, component, displaySaveButton);
// Resource detail sections
registerDetailsViewSection(component);
```
**Key Changes in v0.13.0:**
- `registerDetailsViewSection` now takes 1 argument (component), not 2 (name, component)
- `registerAppBarAction` now takes 1 argument (component), not 2 (name, component)
### Headlamp CommonComponents
**Used Components:**
- `SectionBox` - Card-like container with title
- `SectionHeader` - Page header with title
- `StatusLabel` - Color-coded status badges
- `NameValueTable` - Key-value table layout
- `SimpleTable` - Data table with sorting
- `Drawer` - Right-side overlay panel
- `Loader` - Loading spinner
**Router:**
- `Router.createRouteURL()` - Generate plugin route URLs
- React Router's `useHistory()`, `useParams()`, `useLocation()`
### Kubernetes API (via ApiProxy)
**Used for:**
- Fetching Polaris results: `ApiProxy.request(dashboardUrl + 'results.json')`
- No direct K8s API calls (all data from Polaris dashboard)
**RBAC Required:**
- `get` on `services/proxy` for `polaris-dashboard` in `polaris` namespace
## Performance Considerations
### Bundle Size
- **Current:** ~27 KB minified (gzip: ~7.6 KB)
- **Target:** Keep under 50 KB to ensure fast loading
- **Strategy:** No heavy dependencies, tree-shaking enabled
### Data Fetching
- **Lazy loading:** Data not fetched until user navigates to plugin
- **Caching:** Single fetch shared across all views (React Context)
- **Refresh strategy:** User-controlled interval prevents excessive API calls
### Rendering
- **React.memo:** Not needed (data changes infrequently)
- **Virtual scrolling:** Not needed (namespace/resource lists typically <100 items)
- **Component splitting:** Lazy load views if bundle grows significantly
## Next Steps
- **[Data Flow](data-flow.md)** - Detailed data flow diagrams and sequences
- **[Design Decisions](design-decisions.md)** - Architecture decision records
- **[ADRs](adr/README.md)** - Formal Architecture Decision Records
## References
- [Headlamp Plugin Development](https://headlamp.dev/docs/latest/development/plugins/)
- [Fairwinds Polaris Documentation](https://polaris.docs.fairwinds.com/)
- [React Context API](https://react.dev/reference/react/useContext)
- [Kubernetes Service Proxy](https://kubernetes.io/docs/tasks/administer-cluster/access-cluster-services/)