Repository navigation
Say when get_changes can't see a custom kind because Radar isn't collecting it - #2369
Conversation
âĶecting it get_changes kind=X for a custom kind now carries the coverage list_resources reports for that kind, read from the same code without listing rows, and narrowHint leads with what Radar doesn't collect and when collection started inside the window. An empty answer for a kind Radar wasn't watching no longer reads the same as no changes.
âĶccurate - Kinds resolve through the history query's own normalization, so a short name such as cm is never an unknown kind; a known built-in never is. - A custom kind sharing its name with a built-in kind or native Helm history is checked by itself, named by group, without a coverage field. - The per-namespace caveat follows how Radar watches the kind, not whether every namespace's watch has synced. - No collection-start sentence within a minute of Radar's own start, which historyCoverage already reports. - Hints keep only next steps get_changes can take. - The denied-namespace early return checks for a changed connection.
The startup slack applies only when the window also starts before Radar did, where historyCoverage states the boundary. A known built-in kind counts as a shared name even when discovery omits it, and hints for a shared name's custom kind name its group on failure too.
âĶ boundary Whether a nearby store-wide boundary already covers the gap is decided from the response's own historyCoverage, which is absent for a namespace created after Radar started and withheld from callers who can't read every namespace.
PR Summary by QodoReport custom-kind collection coverage in get_changes
AI Description
Diagram
High-Level Assessment
Files changed (6)
|
Code Review by Qodo
1. New custom services can appear covered
|
It has no start time to compare, so no reported boundary can stand in for it.
get_changes reads history only in a namespace-limited caller's namespaces, so a cluster-scoped kind's changes never come back to them. Its coverage is dropped there and the limitation stated instead.
Summary
get_changes kind=Xfor a custom kind Radar wasn't collecting returned{"changes":[]}with no qualification. That reads exactly like "nothing changed". It happens for large CRDs Radar defers at startup (more than 100 objects), for kinds Radar's identity can't list, and for kinds it collects only in some namespaces. #2360 madeget_changessteer agents tokind=for custom kinds, so this path is now common.Now the answer says what Radar collects for that kind, using the same coverage
list_resourcesreports, and when collection started if that was inside the window. On a live EKS test cluster, Radar defersCiliumEndpointat startup:What changed
Reuses the coverage foundation; no new vocabulary. The new
coveragefield onget_changesis the existingresourceapi.Coverage(readreasoncodes,narrowedBy, gaps), computed bylist_resources' own dynamic read path:listDynamicResourcesis split intoreadDynamicList, which reads and returns what the read covered, plus rendering.list_resourcesoutput is unchanged.get_changescalls the read without rows. It reads the cached objects in place (ListReadOnly), so no objects are copied or minified.Same access rules as the change rows. Change rows require
liston the kind itself, so coverage applies that exact check (narrowByExactAccess). A caller with namespace access but no access to the kind readsuser_forbidden, never "complete".Coverage vs history.
coveragedescribes what Radar collects now. It says nothing about how much history Radar holds:historyCoveragestays store-wide.narrowHintleads with any part Radar doesn't collect, then the collection start when it falls inside the window. That sentence is dropped only when the same response'shistoryCoveragealready states a boundary within a minute of it; a namespace created after Radar started, or a caller shown no boundary time, keeps it.narrowHint, so an answer that is complete but narrowed still says other namespaces are unknown.Names that aren't one custom kind:
coverage.meaningfulchanges.CanonicalKind), socmordeployis never "unknown".Service, CalicoNetworkPolicy, FluxHelmRelease) is checked by itself and named by group innarrowHint, without acoveragefield. The rows can come from both sources.namespace=get one sentence.coveragefor a cluster-scoped custom kind, but a sentence instead:get_changesreads their history only in those namespaces, so that kind's changes never come back to them, and complete coverage would vouch for that empty answer.name=query withoutkind=that finds nothing says to passkind=.get_changescan take (it has nogroupargument).Connection switches. If Radar's connection changes during the request, the answer is
connection_changed, on the early-return path too.Testing
internal/mcp/changes_collection_test.go:user_forbidden;Servicebeside core;NetworkPolicywith the built-in missing from discovery;cmshort name;namespace;name=withoutkind=;list_resources' own arguments.go test ./internal/mcp/ ./internal/meaningfulchanges/ ./internal/server/,make lint,cd pkg && go build ./...pass. Existinglist_resourcestests pass unchanged.CiliumEndpointandCiliumIdentity,VirtualServicewatched since startup (no extra sentence),Deployment(nocoverage), thecmshort name, nativeHelmRelease, and an unknown kind. Results matched the cases above.Notes
list_resourcesshares lists the kind once. A planning-only path would mean changing that shared wait, which this PR leaves alone.historyCoveragealready states in the same response is not repeated.get_changes, even for a kind they may list. Fixing that changes what restricted users can see, so it is left for a separate decision.