Skip to content

Remove referencingWorkloads/referenceCount from config CRD statuses#5631

Open
ChrisJBurns wants to merge 6 commits into
mainfrom
chris/drop-referencing-workloads-status
Open

Remove referencingWorkloads/referenceCount from config CRD statuses#5631
ChrisJBurns wants to merge 6 commits into
mainfrom
chris/drop-referencing-workloads-status

Conversation

@ChrisJBurns

@ChrisJBurns ChrisJBurns commented Jun 24, 2026

Copy link
Copy Markdown
Collaborator

Summary

Removes the status.referencingWorkloads and status.referenceCount fields (and the References printer column) from the six config CRDs — MCPOIDCConfig, MCPAuthzConfig, MCPExternalAuthConfig, MCPTelemetryConfig, MCPWebhookConfig, MCPToolConfig — and deletes the watch/rebuild machinery that maintained them.

After the field-indexer rollout (#5599) and stale-scan removal (#5626), that denormalized list was kept fresh only to populate a kubectl printer column. It no longer backs deletion protection: the finalizer recomputes referrers live (findReferencingWorkloads) before allowing deletion. So the stored list was pure overhead — every workload change reconciled the config purely to refresh a count — and this removes it.

Completes the cleanup tracked in #5607.

⚠️ Breaking change

status.referencingWorkloads and status.referenceCount are removed from all six config CRDs. Anyone relying on these status fields for automated workflows — scripts, GitOps assertions, dashboards, or the kubectl get "References" column — will no longer find them. There is no replacement field; if you need the set of referrers, list the workloads and filter by their config-ref. For example:

# workloads referencing an MCPOIDCConfig named "my-oidc" in namespace ns:
kubectl -n ns get mcpservers,mcpremoteproxies,virtualmcpservers -o json \
  | jq -r '.items[] | select(.spec.oidcConfigRef.name=="my-oidc" or .spec.incomingAuth.oidcConfigRef.name=="my-oidc") | "\(.kind)/\(.metadata.name)"'
``` **Deletion protection is unchanged** (a config still cannot be deleted while a workload references it; it sets the `DeletionBlocked` condition).

## Large PR Justification

Large, mostly-deletion refactor that must land atomically: removing a CRD status field requires the type change, the controller changes, regenerated CRD manifests/deepcopy/docs, and the test updates to all move together or nothing compiles. It is **net −3810 lines** (140 / 3950); the size is duplicated tracking code and tests being deleted across six controllers and four envtest suites at once, not added complexity. Splitting per-config-type would produce six interdependent PRs that each leave the `controllers` package uncompilable in isolation.

<details>
<summary><strong>What changed</strong></summary>

- **API types** (`api/v1beta1/*`, `api/v1alpha1/types.go`): dropped both fields + the `+kubebuilder:printcolumn` "References" markers; regenerated `zz_generated.deepcopy.go`. Kept the `WorkloadReference` type (still returned by the deletion-check).
- **Controllers**: removed the `Reconcile` status-population paths, the workload `Watches` + their map handlers (they existed only to refresh the list), and the `workloadReferenceCount` helper. **Kept** `findReferencingWorkloads` + the field indexes for the on-demand finalizer deletion check, and the `DeletionBlocked` condition/message.
- **Comments**: updated the now-inaccurate "ReferencingWorkloads is maintained by the config controller" notes in the MCPServer/VirtualMCPServer/MCPRemoteProxy controllers.
- **Tests**: deleted unit + envtest specs that asserted the removed fields (tracking/prune/watch-handler); retained deletion-protection specs, rewritten to assert via the `DeletionBlocked` condition + object existence.
- **Generated**: regenerated the six config CRDs (`deploy/charts/operator-crds/...`) and `docs/operator/crd-api.md`.

</details>

## Type of change

- [ ] Bug fix
- [ ] New feature
- [x] Breaking change
- [x] Refactoring
- [ ] Documentation

## Test plan

- [x] `go build ./cmd/thv-operator/...` passes
- [x] `task operator-test` (full operator unit suite) passes
- [x] Config integration suites pass at the spec level, run individually under envtest: MCPOIDCConfig 29/29, MCPToolConfig, MCPExternalAuth, MCPTelemetryConfig 5/5 (the only failures were the known envtest `kube-apiserver` AfterSuite teardown flake under parallel load — 0 spec failures; clean on isolated re-run)
- [x] `golangci-lint` clean on changed packages (only the pre-existing `mcpserver_controller.go:1645` finding remains)
- [x] CRD manifests / deepcopy / `crd-api.md` regenerated and contain no `referencingWorkloads`/`referenceCount`/`References`

## Does this introduce a user-facing change?

Yes — see the breaking-change note above: two status fields and the `References` printer column are removed from the six config CRDs.

Generated with [Claude Code](https://claude.com/claude-code)

ChrisJBurns and others added 3 commits June 24, 2026 23:41
Remove the ReferencingWorkloads and ReferenceCount status fields from the six
config CRDs (MCPOIDCConfig, MCPAuthzConfig, MCPExternalAuthConfig,
MCPTelemetryConfig, MCPWebhookConfig, MCPToolConfig) and the machinery that
maintained them. After the indexer + stale-scan-removal work, that denormalized
list was kept fresh only to power a kubectl printer column — it no longer backs
deletion protection, which the finalizer recomputes live via
findReferencingWorkloads.

- Drop both fields (and the "References" printcolumn markers) from the v1beta1
  status structs and the v1alpha1 type markers; regenerate deepcopy.
- Remove the status-population paths in Reconcile, the workload watches and their
  map handlers (which existed only to refresh the list), and the
  workloadReferenceCount helper. Keep findReferencingWorkloads + the field
  indexes for the on-demand deletion check, and the DeletionBlocked condition.
- Update unit tests and the stale comments in the workload controllers.

BREAKING CHANGE: status.referencingWorkloads and status.referenceCount are
removed from all six config CRDs. Anything reading those fields (automation,
scripts, the kubectl "References" column) will no longer find them. Deletion
protection is unchanged.

See #5607.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Drop the envtest specs that asserted Status.ReferencingWorkloads /
ReferenceCount tracking and pruning (those fields are gone). Deletion-protection
coverage is retained, rewritten to assert via the DeletionBlocked condition and
object existence rather than the removed list.

See #5607.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Regenerate the six config CRDs and crd-api.md after removing the
referencingWorkloads/referenceCount status fields and the "References" printer
column.

See #5607.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added the size/XL Extra large PR: 1000+ lines changed label Jun 24, 2026
@codecov

codecov Bot commented Jun 24, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 66.66667% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 70.32%. Comparing base (e7934ea) to head (b837630).

Files with missing lines Patch % Lines
...perator/controllers/mcpwebhookconfig_controller.go 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #5631      +/-   ##
==========================================
+ Coverage   70.27%   70.32%   +0.04%     
==========================================
  Files         648      647       -1     
  Lines       66011    65738     -273     
==========================================
- Hits        46391    46231     -160     
+ Misses      16279    16159     -120     
- Partials     3341     3348       +7     

☔ 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.

ChrisJBurns and others added 3 commits June 25, 2026 00:07
WorkloadRefsEqual was the "did the ref list change?" guard before the config
status writes removed in this PR. With those callers gone it had no production
references (only its own test), the symmetric leftover to the deleted
workloadReferenceCount helper. Remove it and its test.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The config-CRD sections still described a referencingWorkloads status field.
Reword the three references to drop it and note that referrers are recomputed
on demand at deletion time (finalizer + field-indexed lookup).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Cover the full create-ref -> deletion blocked (DeletionBlocked condition) ->
remove ref -> deleted transition for MCPExternalAuthConfig, mirroring the
ToolConfig/Telemetry suites. With the workload watches removed, unblock now
rides the controller's 30s requeue, so the spec allows up to 45s for the
config to be garbage-collected after the reference is gone.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@ChrisJBurns ChrisJBurns requested a review from amirejaz as a code owner June 24, 2026 23:07
@github-actions github-actions Bot added size/XL Extra large PR: 1000+ lines changed and removed size/XL Extra large PR: 1000+ lines changed labels Jun 24, 2026
@ChrisJBurns

Copy link
Copy Markdown
Collaborator Author

Addressed the review findings (commits on top of the original three):

  1. WorkloadRefsEqual dead code (MEDIUM) — removed the helper + its test; it was the orphaned guard whose callers this PR deleted (symmetric with the already-removed workloadReferenceCount).
  2. Stale arch docs (MEDIUM) — updated the three docs/arch/09-operator-architecture.md references to drop referencingWorkloads and note referrers are recomputed on demand at deletion (finalizer + field-indexed lookup).
  3. Missing block→unblock envtest (LOW) — added a create-ref → deletion-blocked (DeletionBlocked condition) → remove-ref → deleted transition spec to the MCPExternalAuthConfig suite (passes 35/35; allows up to 45s for the now-30s-requeue-driven unblock). Skipped MCPAuthzConfig — it has no integration suite and standing one up for this shared behavior is disproportionate; its handleDeletion blocking is unit-tested.
  4. Empty Context blocks (LOW) — verified non-issue: the earlier commit removed whole Contexts (with setup), leaving no orphaned empty containers.
  5. Lost kubectl "References" column (LOW) — accepted (keeping even a count would require restoring the removed watch apparatus); added a concrete kubectl ... | jq field-filter alternative to the PR description.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/XL Extra large PR: 1000+ lines changed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant