Skip to content

v1.1.2 — stability pass: time-merged multi-pod logs

Choose a tag to compare

@LywwKkA-aD LywwKkA-aD released this 25 Aug 22:06
· 2 commits to master since this release

Stability release: the multi-pod logs fix everyone felt, plus a full
review pass over the TUI loop, port-forwards and the k8s client layer.
No new keybindings, no behaviour you need to relearn — just fewer
glitches.

Why

Tailing several pods at once (l on a service) used to dump the whole
--tail history of pod A, then the whole history of pod B — the
per-pod reader goroutines raced to the shared channel. History is now
buffered per pod, merged by Kubernetes log timestamps, then live lines
stream through as they arrive.

The rest of the release is a systematic bug hunt: leaks that pinned
local ports across context switches, exec shells landing in the wrong
cluster, duplicate refresh loops, and a dashboard that fetched
megabytes of objects every 5 seconds just to count them.

What

Logs

  • internal/tui/views/logs/merge.go — two-phase merge: historical tail
    is requested with Timestamps=true, parsed, stable-sorted across
    pods, then live lines pass through. Single-pod streaming keeps the
    old zero-overhead path.

Port-forward

  • Service forwards now tunnel to the service's targetPort (previously
    the tunnel went green but hit the service port, not the container port).
  • Switching contexts tears down live forwards — local ports are freed
    instead of leaking SPDY sessions until exit.
  • The forwards list and the startup restore prompt are scoped to the
    active context.
  • SPDY upgrade gets a 15s ResponseHeaderTimeout: a stuck API server
    fails fast instead of leaking a goroutine; established tunnels are
    untouched.
  • Nil-client guard before the first API call.

Exec / contexts

  • kubectl exec now passes --context for the context selected inside
    k4s — previously it silently used the kubeconfig file's
    current-context, so a shell could open in the wrong cluster.
  • The marker no longer eats the first letter of the active context
    name (ANSI-styled cell vs. table width truncation).

TUI loop

  • Generation guard in every auto-refreshing view: returning to a view
    no longer stacks duplicate tick/fetch chains.
  • Busy guard: a new fetch (tick or r) is skipped while the previous
    one is still in flight — on a slow API the 5s tick used to overlap
    the 5s timeout.
  • Async list responses are fenced by namespace: stale replies after a
    namespace switch are dropped.
  • Esc from describe/logs returns to the previous list view instead of
    doing nothing.
  • Footer errors auto-clear after 5s; the cursor now actually blinks in
    command/prompt modes.
  • top ignores metrics from the wrong mode after toggling n.

Dashboard

  • Stats are 4 parallel Limit: 1 count queries using
    RemainingItemCount instead of four full object lists — drastically
    less traffic on big clusters.
  • Per-resource error isolation: an RBAC denial on one resource no
    longer blanks the whole dashboard; failed counters are listed as
    unavailable: ….

k8s client

  • Deployment log/exec resolution supports matchExpressions selectors.
  • describe truncation is UTF-8 safe; events are listed with a
    server-side involvedObject.name field selector.

Deps

  • Go 1.26.7, k8s.io/* v0.36.4, charmbracelet/x/ansi v0.11.8.

Coverage

New tests: log-merge unit tests + a cluster-tagged smoke test
(-tags cluster), stats partial/total failure via fake-client
reactors, busy-guard and namespace-fencing tests for list views,
matchExpressions resolution, UTF-8 truncate, SPDY transport cloning,
cmdError TTL. Every fix above was also exercised live against a real
cluster (tmux-driven TUI smoke with the race detector enabled:
multi-pod logs, exec, forward start/stop with port checks, context
switching, key-spam stress — zero races, zero panics).

Quality

  • go vet
  • golangci-lint ✓ (0 issues)
  • go test -race
  • govulncheck

Install

go install github.com/LywwKkA-aD/k4s/cmd/k4s@v1.1.2

Website: https://k4scli.io