Skip to content

Commit 6dd6db1

Browse files
authored
Events, async watch rework, bug fixes, enhancements (#199)
Signed-off-by: Daniel Guns <danbguns@gmail.com>
1 parent e1e71d8 commit 6dd6db1

29 files changed

Lines changed: 1923 additions & 656 deletions

CHANGELOG.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
88
## [Unreleased]
99

1010
### Added
11+
- Kubernetes Events support:
12+
- The describe view (`d`) now ends with a kubectl-style Events section
13+
showing the resource's recent events (Warnings highlighted; degrades to a
14+
notice when events are unavailable, e.g. RBAC).
15+
- New `:events` (alias `:ev`) live events feed for the current namespace
16+
scope — cluster-wide with `:ns all`. Streams in real time, newest first,
17+
filterable with `/`; `Enter` jumps to the involved Flux resource. The
18+
events watcher runs only while the view is open.
19+
- Resource action keys now resolve their target from any view via a single
20+
`view_target()` resolver: `y`/`d` (and `t`/`g`/`h`/operations for watched
21+
resources) act on the selected event's involved object in the events feed
22+
and on the focused node in the graph view — previously these keys only
23+
worked from the resource list, favorites, and detail views. `y`/`d` work
24+
for non-Flux objects too (Pods, Deployments, …) via the API fetch path,
25+
and Back returns to the view you came from (events feed or graph).
1126
- Graph view keyboard navigation: `j`/`k` move a highlighted focus between nodes
1227
(the view auto-scrolls to keep it visible), `Enter` opens the focused resource's
1328
detail view, and `Esc` returns to the graph.
@@ -17,7 +32,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1732
children → drop into each child) using proper box-drawing junctions, and nodes
1833
sit closer together for a tighter, clearer layout.
1934

35+
### Fixed
36+
- `:all` now returns to the main resource list from the events feed (and stops
37+
the events watch), instead of only clearing filters while stuck in the view.
38+
- The events feed's "not a watched Flux resource" message now names the
39+
involved object's namespace and points at `y`/`d`, so namespace-scope
40+
mismatches are visible instead of just confusing.
41+
2042
### Internal
43+
- New generic `AsyncTask<K, T>` owns the request/dispatch/poll lifecycle for
44+
view fetches, replacing the five copy-pasted `*_pending`/`*_fetched`/`*_rx`
45+
field triplets and their hand-rolled trigger/poll methods.
46+
- YAML/describe fetch requests are now typed `ResourceKey`s instead of
47+
`"type:namespace:name"` strings, removing the re-parse (and its can't-happen
48+
error branches) from the main loop.
49+
- The Kubernetes events watcher has an independent lifecycle from the resource
50+
watchers (started lazily, stopped without a full watcher teardown), and
51+
survives namespace switches.
2152
- Single source of truth for graph node sizing (`GraphNode::render_width`/
2253
`render_height`); connector geometry extracted into the testable, `Frame`-free
2354
`fanout_routes()`.

Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

DEVELOPER_GUIDE.md

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,10 +106,15 @@ Terminal user interface built with ratatui.
106106

107107
- **`app/`** - Application state and logic (refactored from single file):
108108
- `core.rs` - Main App struct and core logic
109-
- `state.rs` - State structures (ViewState, SelectionState, UIState, AsyncOperationState)
109+
- `state.rs` - State structures (ViewState, SelectionState, UIState, AsyncOperationState, KubeEventStore)
110110
- `events.rs` - Event handling and input processing
111111
- `rendering.rs` - Rendering orchestration
112-
- `async_ops.rs` - Async operation management
112+
- `async_task.rs` - Generic `AsyncTask<K, T>`: one type owns the
113+
request → dispatch → poll lifecycle for every view fetch (YAML, describe,
114+
trace, graph). Event handlers call `request()`, the main loop calls
115+
`dispatch()` and spawns the work, then polls `try_recv()` each tick.
116+
- `async_ops.rs` - Mutating-operation flow (registry validation, status
117+
message bookkeeping) and the graph result hook
113118
- **`operations.rs`** - Flux operations (suspend, resume, delete, reconcile, reconcile with source)
114119
- **`theme.rs`** - Theme configuration and loading
115120
- **`trace.rs`** - Trace operation orchestration
@@ -127,6 +132,7 @@ Terminal user interface built with ratatui.
127132
- `trace.rs` - Trace view showing resource ownership chains
128133
- `graph.rs` - Graph visualization view
129134
- `history.rs` - Reconciliation history view
135+
- `events.rs` - Live Kubernetes events feed (`:events`)
130136
- `confirmation.rs` - Confirmation dialogs
131137
- `help.rs` - Help screen
132138
- `splash.rs` - Splash screen
@@ -139,6 +145,10 @@ Terminal user interface built with ratatui.
139145
- Non-blocking async operations using `tokio::spawn`
140146
- Modular app structure with separated concerns (state, events, rendering, async)
141147
- Separate scroll offsets for different views
148+
- The Kubernetes events watcher (`ResourceWatcher::watch_kube_events`) has an
149+
independent lifecycle from the resource watchers: started lazily when the
150+
events view opens, stopped (and its `KubeEventStore` feed cleared) when the
151+
view is left, and restarted automatically across namespace/context switches
142152
- Per-view behavior (scroll target, back navigation, classification) lives on
143153
`impl View` (`src/tui/app/state.rs`) rather than scattered `match` arms
144154
- Dynamic footer wrapping for smaller screens

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ A [K9s](https://github.com/derailed/k9s)-inspired terminal UI for monitoring Flu
3131
- **Unified and type-specific views** - View all resources together or filter by type
3232
- **Resource operations** - Suspend, resume, reconcile, and delete Flux resources
3333
- **YAML viewing** - Inspect full resource manifests
34+
- **Kubernetes Events** - Per-resource events in the describe view, plus a live `:events` feed for the current namespace or cluster
3435
- **Graph visualization** - Visualize resource relationships and dependencies (Kustomization, HelmRelease, etc.)
3536
- **Reconciliation history** - View reconciliation history for resources that track it
3637
- **Favorites** - Mark frequently accessed resources for quick access
@@ -143,6 +144,7 @@ By default, `flux9s` watches the `flux-system` namespace. Use `:ns all` to view
143144
- `:ns <namespace>` - Switch namespace
144145
- `:ns all` - View all namespaces
145146
- `:favorites` or `:fav` - View favorite resources
147+
- `:events` or `:ev` - Live Kubernetes events feed (current namespace scope)
146148
- `:skin {skin-name}` - set skin directly
147149
- `:skin` - open interactive theme selection menu with live preview (17 built-in themes + custom)
148150
- `:q` or `:q!` - Quit
@@ -152,6 +154,7 @@ By default, `flux9s` watches the `flux-system` namespace. Use `:ns all` to view
152154

153155
- **Graph View (`g`)** - Visualize resource relationships and dependencies. Shows upstream sources and downstream managed resources. Move the highlighted focus between nodes with `j`/`k` (the view scrolls to keep it visible), press `Enter` to open the focused resource's detail view, and `Esc` to return to the graph. Supported for Kustomization, HelmRelease, ArtifactGenerator, FluxInstance, and ResourceSet.
154156
- **History View (`h`)** - View reconciliation history for FluxInstance, ResourceSet, Kustomization, and HelmRelease resources.
157+
- **Events View (`:events`)** - Live Kubernetes events feed for the current namespace (or cluster-wide with `:ns all`), newest first with Warnings highlighted. `Enter` jumps to the involved resource; the describe view (`d`) also shows a per-resource Events section.
155158
- **Favorites (`f`)** - Mark resources as favorites for quick access. Use `:favorites` command to view all favorites.
156159

157160
### Terminal Commands

docs/content/user-guide/_index.md

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,8 @@ Type these commands in command mode (press `:`):
9595
| `:unhealthy` | Show only unhealthy resources |
9696
| `:favorites` | View favorite resources |
9797
| `:fav` | Alias for `:favorites` |
98+
| `:events` | Live Kubernetes events feed |
99+
| `:ev` | Alias for `:events` |
98100
| `:skin <name>` | Change theme/skin (direct) |
99101
| `:skin` | Open interactive theme selection menu |
100102
| `:readonly` | Toggle readonly mode |
@@ -219,7 +221,8 @@ The graph view displays:
219221

220222
- `j` / `k` (or `` / ``) - Move the highlighted focus between nodes; the view scrolls to keep the focused node visible.
221223
- `Enter` - Open the focused node's resource in the detail view. Aggregate nodes (workload/resource groups) and external upstream URLs aren't directly openable.
222-
- `Esc` / `Backspace` - Return to the graph (when you opened a detail view from it), then back to the resource list.
224+
- `y` / `d` - View the focused node's YAML or describe output directly, including managed workloads (Deployments, Services, etc.).
225+
- `Esc` / `Backspace` - Return to the graph (when you opened a view from it), then back to the resource list.
223226

224227
Focus starts on the resource you opened the graph from, so you can immediately walk its sources and dependencies.
225228

@@ -250,6 +253,31 @@ Mark frequently accessed resources as favorites for quick access.
250253
- Favorites are saved to your configuration file
251254
- Favorites appear first in resource lists
252255

256+
### Events View (`:events`)
257+
258+
A live feed of Kubernetes Events in the current namespace scope — the
259+
"what is Flux doing right now" view. Flux controllers emit an Event for every
260+
reconciliation success and failure, so this surfaces error detail that the
261+
resource list's MESSAGE column truncates.
262+
263+
- The feed follows your namespace scope: the current namespace by default, or
264+
the whole cluster after `:ns all` (a NAMESPACE column appears)
265+
- Events are streamed in real time, newest first, with Warnings highlighted
266+
- `/` filters by type, reason, object, namespace, source, or message text
267+
- `Enter` on an event jumps to the involved resource's detail view when it is
268+
a Flux resource flux9s watches; `Esc` returns to the events feed
269+
- Resource keys act on the selected event's involved object directly: `y`
270+
(YAML) and `d` (describe) work even for non-Flux objects like Pods and
271+
Deployments, while `t`/`g`/`h` and operations (`s`/`r`/`R`) work when the
272+
object is a watched Flux resource. `Esc` from any of these returns to the
273+
events feed
274+
- `Esc` from the feed returns to the resource list and stops the events watch —
275+
events are only streamed while the view is open, so there is no overhead the
276+
rest of the time
277+
278+
Events also appear in the describe view (`d`): each resource's describe output
279+
ends with a kubectl-style Events section listing that resource's recent events.
280+
253281
## Operations
254282

255283
Perform actions on selected resources:

src/constants.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ pub const RESOURCE_KEY_FORMAT: &str = "resource_type:namespace:name";
99
/// Maximum number of reconciliation history events to store per resource
1010
pub const MAX_RECONCILIATION_HISTORY: usize = 50;
1111

12+
/// Cap on the live Kubernetes events feed. Events are the churniest resource
13+
/// in a cluster; the store evicts oldest-seen entries past this bound so a
14+
/// busy cluster can't grow memory without limit.
15+
pub const MAX_KUBE_EVENTS: usize = 1000;
16+
1217
/// Status message timeout in seconds
1318
pub const STATUS_MESSAGE_TIMEOUT_SECS: u64 = 4;
1419

0 commit comments

Comments
 (0)