Skip to content

Emit Events from the three config controllers#5514

Open
ChrisJBurns wants to merge 2 commits into
cburns/migrate-sibling-controllers-mutatepatchstatusfrom
cburns/config-controllers-eventrecorder
Open

Emit Events from the three config controllers#5514
ChrisJBurns wants to merge 2 commits into
cburns/migrate-sibling-controllers-mutatepatchstatusfrom
cburns/config-controllers-eventrecorder

Conversation

@ChrisJBurns

Copy link
Copy Markdown
Collaborator

Summary

The MCPOIDCConfig, MCPExternalAuthConfig, and MCPAuthzConfig controllers logged validation failures and deletion-blocked transitions but emitted no Kubernetes Event objects — so an operator running kubectl describe mcpauthzconfig <name> (or the siblings) couldn't see why a config was rejected or which workloads were blocking its deletion. Per the operator Status Condition Parity rule, all three siblings gain an EventRecorder in a single change so the parity is established as one logical step. Flagged as F15 in the multi-agent review of #4777.

Closes #5496

Note: stacked on #5509 (cburns/migrate-sibling-controllers-mutatepatchstatus) — these controllers only exist in their migrated form on that branch. Rebase to main once #5509 merges.

Medium level
  • New shared helper (config_controller_events.go): emitConfigEvent (nil-guarded Eventf wrapper), emitConfigRecoveryEvent (Normal ConfigValid, no-op unless recovering), conditionStatusIs (transition detection), and the shared ConfigInvalid / ConfigValid / DeletionBlocked event reasons.
  • Each reconciler gains Recorder events.EventRecorder, wired in app.go via mgr.GetEventRecorder("<resource>-controller"), plus an events.k8s.io/events RBAC marker (matching the five sibling controllers that already carry it; regenerated manifests show no diff since the permission was already granted).
  • Emission is transition-gated: the prior condition is read before MutateAndPatchStatus (which mutates conditions in place), so a Warning fires only on entering the invalid/blocked state and the recovery Normal fires only on the FalseTrue transition — steady-state reconciles produce no event spam.
  • ExternalAuth coverage: the inline-validation path, the OBO setInvalid path, and both success paths (handleConfigHashChange, updateReferencingWorkloads) are all covered.
  • Security: event messages carry only structural validation errors (err.Error() from Validate()) and logical workload Kind/Name references — never raw policy, secrets, bearer tokens, or fully-qualified internal URLs. A test asserts the ExternalAuth deletion event omits the token URL and secret ref.
Low level
File Change
cmd/thv-operator/controllers/config_controller_events.go New: shared event reasons/actions, emitConfigEvent, emitConfigRecoveryEvent, conditionStatusIs.
cmd/thv-operator/controllers/mcpoidcconfig_controller.go Recorder field + RBAC marker; emit ConfigInvalid, ConfigValid, DeletionBlocked.
cmd/thv-operator/controllers/mcpexternalauthconfig_controller.go Recorder field + RBAC marker; emit on inline + OBO failure, both recovery paths, and deletion-block.
cmd/thv-operator/controllers/mcpauthzconfig_controller.go Recorder field + RBAC marker; emit ConfigInvalid, ConfigValid, DeletionBlocked.
cmd/thv-operator/app/app.go Wire Recorder for all three controllers.
cmd/thv-operator/controllers/config_controller_events_test.go New: per-controller event tests (invalid → recovery, deletion-blocked), steady-state recovery path, nil-recorder safety, and message-sanitization assertions using events.NewFakeRecorder.

Type of change

  • Bug fix
  • New feature
  • Breaking change
  • Refactoring
  • Documentation
  • Other

Test plan

  • task test (operator controllers + app unit suites) passes
  • task build passes
  • gofmt + go vet ./cmd/thv-operator/... clean (local task lint-fix blocked by a known golangci-lint go1.24/1.26 toolchain mismatch; CI lint is unaffected)
  • New unit tests assert: Warning ConfigInvalid on validation failure, Normal ConfigValid on recovery (incl. the steady-state path), Warning DeletionBlocked when gated by a referencing workload, no event spam while staying invalid, nil-recorder safety, and that event messages don't leak the token URL / secret ref

Special notes for reviewers

  • The events.k8s.io RBAC markers were added for parity with the sibling controllers, but task operator-manifests produces no diff — the aggregated role already granted events: create;patch from the existing five controllers.
  • The integration suite (cmd/thv-operator/test-integration/...) was not run locally; it requires envtest control-plane binaries (/usr/local/kubebuilder/bin/etcd) that aren't installed in this environment.

Generated with Claude Code

The MCPOIDCConfig, MCPExternalAuthConfig, and MCPAuthzConfig controllers
logged validation failures and deletion-blocked transitions but emitted no
Kubernetes Events, so `kubectl describe` could not show why a policy-shaped
config was rejected or which workloads blocked its deletion. Per the operator
Status Condition Parity rule, all three siblings gain an EventRecorder in one
change.

Each reconciler now carries `Recorder events.EventRecorder`, wired in app.go,
and emits: a Warning ConfigInvalid on entering the invalid state, a Warning
DeletionBlocked on entering the blocked state, and a Normal ConfigValid on
recovery. Emission is transition-gated (the prior condition is read before
MutateAndPatchStatus mutates it in place) so steady-state reconciles produce
no event spam. Messages carry only structural validation errors and logical
workload names — never raw policy, secrets, tokens, or internal URLs.

Closes #5496

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added the size/L Large PR: 600-999 lines changed label Jun 12, 2026
@codecov

codecov Bot commented Jun 12, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 85.52632% with 11 lines in your changes missing coverage. Please review.
✅ Project coverage is 69.75%. Comparing base (03199e0) to head (0c1c2ea).

Files with missing lines Patch % Lines
cmd/thv-operator/app/app.go 0.00% 9 Missing ⚠️
...or/controllers/mcpexternalauthconfig_controller.go 92.30% 1 Missing and 1 partial ⚠️
Additional details and impacted files
@@                                   Coverage Diff                                    @@
##           cburns/migrate-sibling-controllers-mutatepatchstatus    #5514      +/-   ##
========================================================================================
+ Coverage                                                 69.71%   69.75%   +0.03%     
========================================================================================
  Files                                                       645      646       +1     
  Lines                                                     65616    65684      +68     
========================================================================================
+ Hits                                                      45745    45815      +70     
  Misses                                                    16526    16526              
+ Partials                                                   3345     3343       -2     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@github-actions github-actions Bot added size/L Large PR: 600-999 lines changed and removed size/L Large PR: 600-999 lines changed labels Jun 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/L Large PR: 600-999 lines changed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant