Skip to content

feat(registry): stop advertising watch and mutations on computed resources#331

Open
matthyx wants to merge 2 commits into
mainfrom
feat/honest-discovery-computed-resources
Open

feat(registry): stop advertising watch and mutations on computed resources#331
matthyx wants to merge 2 commits into
mainfrom
feat/honest-discovery-computed-resources

Conversation

@matthyx

@matthyx matthyx commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

Stacked on #330 — contains only the top two commits; GitHub will retarget this PR to main automatically when #330 merges.

Summary

Hybrid watch strategy follow-up to #330: keep the watch verb where watch genuinely works (the dispatcher-backed resources that node-agent, synchronizer, and operator rely on) and stop advertising it where it can never work — the three computed ("virtual CRD") resources that are generated on the fly and never stored:

  • configurationscansummaries
  • vulnerabilitysummaries
  • generatednetworkpolicies

After #330 these resources serve an idle watch (open, event-free) — harmless but dishonest: discovery advertises watch, the server accepts, and no event ever arrives. The same applies to the mutating verbs: the storage layer rejects all mutations on computed resources, yet discovery advertised them.

How

The endpoints installer decides verbs per resource by type assertion on the registered rest.Storage object (installer.go: storage.(rest.Watcher) etc.). The new registry.ReadOnlyREST wraps *genericregistry.Store as a field instead of embedding it (embedding re-promotes Watch and friends), explicitly delegating only:

rest.Storage · rest.Scoper · rest.Getter · rest.Lister (incl. ConvertToTable, so kubectl get tables keep working) · rest.SingularNameProvider

Discovery for the three resources therefore lists exactly get,list — the same pattern as metrics.k8s.io. Effects:

  • Rancher steve gates informer setup on IsListWatchable (requires both list+watch verbs) → it now skips these resources entirely instead of holding silent watches.
  • Clients that try ?watch=true anyway get a clean pre-stream 405 MethodNotSupported (handlers/get.go), with standard reflector backoff.
  • No kubescape component is affected: node-agent, synchronizer, and operator only watch dispatcher-backed resources (verified), which are untouched — pinned by a keep-side regression test asserting registry.REST still satisfies rest.Watcher.

Also fixes a copy-pasted package name: vulnerabilitysummary/ declared package workloadconfigurationscansummary (hidden by the import alias).

Testing

  • TestReadOnlyRESTInterfaceSurface pins the installer-visible interface surface (not Watcher/Creater/Updater/GracefulDeleter/CollectionDeleter; is Getter/Lister/Scoper/SingularNameProvider)
  • TestRESTKeepsWatchVerb — keep-side regression guard
  • Compile-time var _ guards for the required interfaces
  • Full suite green (make test), go vet clean
  • Manual check after deploy: kubectl api-resources -o wide shows get,list for the three resources; steve no longer logs watch attempts for them

Release note

Computed resources (ConfigurationScanSummary, VulnerabilitySummary, GeneratedNetworkPolicy) now advertise only get and list verbs; watch and mutation attempts receive 405 MethodNotSupported instead of silently doing nothing.

Refs #318, #320 · Stacked on #330

🤖 Generated with Claude Code

matthyx and others added 2 commits June 5, 2026 11:40
…urces

ConfigurationScanSummary, VulnerabilitySummary, and GeneratedNetworkPolicy
are generated on the fly and never stored: watching them can never deliver
events, and mutations are always rejected by the storage layer. Yet
discovery advertised the full verb set, so clients that trust discovery
(e.g. Rancher steve, which sets up informers for every list+watch-able
GVK) opened watches that silently never produced anything.

Introduce ReadOnlyREST, a wrapper that delegates to genericregistry.Store
without embedding it, deliberately implementing only rest.Getter,
rest.Lister, rest.Scoper, rest.Storage and rest.SingularNameProvider.
The endpoints installer decides verbs by type assertion, so these three
resources now advertise exactly get and list — the same pattern as
metrics.k8s.io. Clients that try to watch anyway receive a clean
pre-stream 405 MethodNotSupported instead of an idle stream.

Watch is unchanged for the dispatcher-backed resources (the kubescape
components rely on it), pinned by a keep-side regression test.

Refs #318, #320

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Matthias Bertschy <matthias.bertschy@gmail.com>
Both files declared "package workloadconfigurationscansummary"; compilation
succeeded only because the import alias (vsumstorage) hid the mismatch.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Matthias Bertschy <matthias.bertschy@gmail.com>
@coderabbitai

coderabbitai Bot commented Jun 5, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8e648472-c687-461c-a0db-99aa2bb31f15

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/honest-discovery-computed-resources

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions

github-actions Bot commented Jun 5, 2026

Copy link
Copy Markdown

Summary:

  • License scan: failure
  • Credentials scan: failure
  • Vulnerabilities scan: failure
  • Unit test: success
  • Go linting: failure

@matthyx matthyx moved this to WIP in KS PRs tracking Jun 5, 2026
Base automatically changed from fix/318-effective-feature-gates-idle-watch to main June 18, 2026 08:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: WIP

Development

Successfully merging this pull request may close these issues.

1 participant