<#1111 Rollout follow-ups: node page stage line an...
# osctrl
g
#1111 Rollout follow-ups: node page stage line and cached rollout progress Pull request opened by javuto Rollout follow-ups: node page stage line and cached rollout progress Follow-up to #1109 (gradual rollout for the environment osquery target). Problem • The node Osquery page could only say a gated host was "not in the rollout yet". It could not say which stage the host joins or when that stage opens, because the node response carried no rollout information. • Every GET, PUT, DELETE, Resume and Abort on the environment osquery endpoint reloaded and hashed all non-Windows hosts of the environment to build the rollout counts. That is wasteful on large environments, and the admin page refetches on focus. Change Stage line on the node page • The node osquery response gains an optional
rollout
object with
state
(running or paused),
stage
(1-based stage the host joins),
stages
(percent per stage) and
eligible_at
(when that stage opens, null when paused or already open). • It is present only when all of these hold: • the effective target comes from the environment, not a pin • the latest rollout row belongs to the current target • the rollout is running or paused • the host is not Windows • The stage uses the same bucket as
Resolve
(environment id, target version, stored upper-case uuid), so the node page and the route cannot disagree. A test ties the two together. •
eligible_at
is the stored stage's open time plus the number of stage-waits ahead of it. Using the effective stage here would count elapsed stages twice. • New
Rollout.NodeStage(bucket)
returns the first stage that contains a bucket. • Wording: • gated: "Not in the rollout yet: this host is in the 50% stage, which opens in about 1 h 20 min." • past or under a minute: "opens shortly" • the stage has already opened: "The rollout has reached this host's stage (50%); it will upgrade at its next sync." • paused: the existing sentence plus the host's stage • no rollout information: the previous generic sentences • The relative-time helper moved into
osqueryReasons.ts
and the rollout panel reuses it. Cached rollout progress • The environment
rollout
view caches its progress result per environment in the API process for 5 seconds. The cache is bounded to 256 environments, safe for concurrent use, and has an injectable clock. • The key is rollout row id, effective state and effective stage, so a stage opening or a state change misses automatically. • Errors are never cached, and aborted rollouts (which skip the scan) are not cached. The cache sits below the permission checks, and the cached host list is copied on the way in and out. • Set target, Clear target, Resume and Abort invalidate the environment's entry, so their responses are fresh. • With several API replicas, another replica can show counts up to 5 seconds old after a change. Security and operational impact • No new endpoints, permissions or schema. The node
rollout
field is derived server-side. The UI interpolates only a numeric stage and a parsed date. • Fewer database scans on the admin page. A cache hit costs one lookup. • The OpenAPI file is regenerated for the new field. Validation •
go test ./cmd/api/... ./pkg/... -count=1
,
go vet ./...
,
gofmt -l cmd pkg
• `golangci-lint run ./cmd/api/... ./pkg/...`: 0 issues • `make openapi-check`: clean • Frontend:
npm test
(644 tests) and
npm run check
• New tests cover: •
NodeStage
, including invalid thresholds •
eligible_at
before and after earlier stages open • pin, no rollout, paused, completed, Windows and mismatched request id • the parity test with
Resolve
• cache hit, miss after the TTL, invalidation by Set, Clear and Abort, key changes, the bound, and the copied host list • each wording branch • Not done: a manual check against a live rollout. Please look at the node page of a gated host on a staging rollout. Notes • The node response shows
rollout
for any host in a running or paused rollout, including hosts already at the target. The UI only shows the text when the host's last report is
rollout_pending
or
rollout_paused
. • A node osquery request now fails with 500 if the rollout lookup fails, although the block is optional. It could be changed to log and omit the block. jmpsec/osctrl