Skip to content

Commit 2e8e487

Browse files
ChrisJBurnsclaude
andauthored
Extract shared WorkloadReference helpers into controllerutil (#4520)
* Extract shared WorkloadReference helpers into controllerutil The ReferencingWorkloads pattern was duplicated across four config controllers with inconsistent sorting behavior: MCPTelemetryConfig and MCPExternalAuthConfig sorted refs, but MCPToolConfig and MCPOIDCConfig did not. This caused unnecessary API server writes when the same set of workloads was discovered in a different list order across reconcile runs. Extract SortWorkloadRefs, WorkloadRefsEqual, and FindWorkloadRefsFromMCPServers into the shared controllerutil package so all controllers use deterministic, consistent ordering. Each controller's findReferencingWorkloads now delegates to the shared helper, removing ~50 lines of duplicated list-filter-build logic. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Add WorkloadKind constants to replace string literals Define WorkloadKindMCPServer, WorkloadKindVirtualMCPServer, and WorkloadKindMCPRemoteProxy constants in the API types and use them across all controllers. This fixes a goconst lint violation where "MCPServer" appeared as a raw string literal 4+ times. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent ce3ade5 commit 2e8e487

9 files changed

Lines changed: 258 additions & 100 deletions

cmd/thv-operator/api/v1alpha1/mcpoidcconfig_types.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,13 @@ type InlineOIDCSharedConfig struct {
144144
InsecureAllowHTTP bool `json:"insecureAllowHTTP"`
145145
}
146146

147+
// Well-known WorkloadReference Kind values.
148+
const (
149+
WorkloadKindMCPServer = "MCPServer"
150+
WorkloadKindVirtualMCPServer = "VirtualMCPServer"
151+
WorkloadKindMCPRemoteProxy = "MCPRemoteProxy"
152+
)
153+
147154
// WorkloadReference identifies a workload that references a shared configuration resource.
148155
// Namespace is implicit — cross-namespace references are not supported.
149156
type WorkloadReference struct {

cmd/thv-operator/controllers/mcpexternalauthconfig_controller.go

Lines changed: 11 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ package controllers
66
import (
77
"context"
88
"fmt"
9-
"slices"
109
"time"
1110

1211
"k8s.io/apimachinery/pkg/api/errors"
@@ -158,23 +157,9 @@ func (r *MCPExternalAuthConfigReconciler) handleConfigHashChange(
158157
// Update the status with the list of referencing workloads
159158
refs := make([]mcpv1alpha1.WorkloadReference, 0, len(referencingServers))
160159
for _, server := range referencingServers {
161-
refs = append(refs, mcpv1alpha1.WorkloadReference{Kind: "MCPServer", Name: server.Name})
160+
refs = append(refs, mcpv1alpha1.WorkloadReference{Kind: mcpv1alpha1.WorkloadKindMCPServer, Name: server.Name})
162161
}
163-
slices.SortFunc(refs, func(a, b mcpv1alpha1.WorkloadReference) int {
164-
if a.Kind != b.Kind {
165-
if a.Kind < b.Kind {
166-
return -1
167-
}
168-
return 1
169-
}
170-
if a.Name < b.Name {
171-
return -1
172-
}
173-
if a.Name > b.Name {
174-
return 1
175-
}
176-
return 0
177-
})
162+
ctrlutil.SortWorkloadRefs(refs)
178163
externalAuthConfig.Status.ReferencingWorkloads = refs
179164

180165
// Update the MCPExternalAuthConfig status
@@ -271,18 +256,13 @@ func (r *MCPExternalAuthConfigReconciler) findReferencingWorkloads(
271256
ctx context.Context,
272257
externalAuthConfig *mcpv1alpha1.MCPExternalAuthConfig,
273258
) ([]mcpv1alpha1.WorkloadReference, error) {
274-
mcpServerList := &mcpv1alpha1.MCPServerList{}
275-
if err := r.List(ctx, mcpServerList, client.InNamespace(externalAuthConfig.Namespace)); err != nil {
276-
return nil, fmt.Errorf("failed to list MCPServers: %w", err)
277-
}
278-
279-
var refs []mcpv1alpha1.WorkloadReference
280-
for _, server := range mcpServerList.Items {
281-
if server.Spec.ExternalAuthConfigRef != nil && server.Spec.ExternalAuthConfigRef.Name == externalAuthConfig.Name {
282-
refs = append(refs, mcpv1alpha1.WorkloadReference{Kind: "MCPServer", Name: server.Name})
283-
}
284-
}
285-
return refs, nil
259+
return ctrlutil.FindWorkloadRefsFromMCPServers(ctx, r.Client, externalAuthConfig.Namespace, externalAuthConfig.Name,
260+
func(server *mcpv1alpha1.MCPServer) *string {
261+
if server.Spec.ExternalAuthConfigRef != nil {
262+
return &server.Spec.ExternalAuthConfigRef.Name
263+
}
264+
return nil
265+
})
286266
}
287267

288268
// SetupWithManager sets up the controller with the Manager.
@@ -326,7 +306,7 @@ func (r *MCPExternalAuthConfigReconciler) SetupWithManager(mgr ctrl.Manager) err
326306
continue
327307
}
328308
for _, ref := range cfg.Status.ReferencingWorkloads {
329-
if ref.Kind == "MCPServer" && ref.Name == server.Name {
309+
if ref.Kind == mcpv1alpha1.WorkloadKindMCPServer && ref.Name == server.Name {
330310
requests = append(requests, reconcile.Request{NamespacedName: nn})
331311
break
332312
}
@@ -356,7 +336,7 @@ func (r *MCPExternalAuthConfigReconciler) updateReferencingWorkloads(
356336
return ctrl.Result{}, fmt.Errorf("failed to find referencing workloads: %w", err)
357337
}
358338

359-
if !slices.Equal(externalAuthConfig.Status.ReferencingWorkloads, refs) {
339+
if !ctrlutil.WorkloadRefsEqual(externalAuthConfig.Status.ReferencingWorkloads, refs) {
360340
externalAuthConfig.Status.ReferencingWorkloads = refs
361341
if err := r.Status().Update(ctx, externalAuthConfig); err != nil {
362342
logger := log.FromContext(ctx)

cmd/thv-operator/controllers/mcpoidcconfig_controller.go

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ package controllers
66
import (
77
"context"
88
"fmt"
9-
"slices"
109
"time"
1110

1211
"k8s.io/apimachinery/pkg/api/errors"
@@ -129,7 +128,7 @@ func (r *MCPOIDCConfigReconciler) Reconcile(ctx context.Context, req ctrl.Reques
129128
referencingWorkloads, err := r.findReferencingWorkloads(ctx, oidcConfig)
130129
if err != nil {
131130
logger.Error(err, "Failed to find referencing workloads")
132-
} else if !slices.Equal(oidcConfig.Status.ReferencingWorkloads, referencingWorkloads) {
131+
} else if !ctrlutil.WorkloadRefsEqual(oidcConfig.Status.ReferencingWorkloads, referencingWorkloads) {
133132
oidcConfig.Status.ReferencingWorkloads = referencingWorkloads
134133
conditionChanged = true
135134
}
@@ -206,19 +205,19 @@ func (r *MCPOIDCConfigReconciler) findReferencingWorkloads(
206205
ctx context.Context,
207206
oidcConfig *mcpv1alpha1.MCPOIDCConfig,
208207
) ([]mcpv1alpha1.WorkloadReference, error) {
209-
mcpServerList := &mcpv1alpha1.MCPServerList{}
210-
if err := r.List(ctx, mcpServerList, client.InNamespace(oidcConfig.Namespace)); err != nil {
211-
return nil, fmt.Errorf("failed to list MCPServers: %w", err)
212-
}
213-
214-
var refs []mcpv1alpha1.WorkloadReference
215-
for _, server := range mcpServerList.Items {
216-
if server.Spec.OIDCConfigRef != nil && server.Spec.OIDCConfigRef.Name == oidcConfig.Name {
217-
refs = append(refs, mcpv1alpha1.WorkloadReference{Kind: "MCPServer", Name: server.Name})
218-
}
208+
// Find referencing MCPServers
209+
refs, err := ctrlutil.FindWorkloadRefsFromMCPServers(ctx, r.Client, oidcConfig.Namespace, oidcConfig.Name,
210+
func(server *mcpv1alpha1.MCPServer) *string {
211+
if server.Spec.OIDCConfigRef != nil {
212+
return &server.Spec.OIDCConfigRef.Name
213+
}
214+
return nil
215+
})
216+
if err != nil {
217+
return nil, err
219218
}
220219

221-
// Check VirtualMCPServers
220+
// Also check VirtualMCPServers
222221
vmcpList := &mcpv1alpha1.VirtualMCPServerList{}
223222
if err := r.List(ctx, vmcpList, client.InNamespace(oidcConfig.Namespace)); err != nil {
224223
return nil, fmt.Errorf("failed to list VirtualMCPServers: %w", err)
@@ -227,10 +226,11 @@ func (r *MCPOIDCConfigReconciler) findReferencingWorkloads(
227226
if vmcp.Spec.IncomingAuth != nil &&
228227
vmcp.Spec.IncomingAuth.OIDCConfigRef != nil &&
229228
vmcp.Spec.IncomingAuth.OIDCConfigRef.Name == oidcConfig.Name {
230-
refs = append(refs, mcpv1alpha1.WorkloadReference{Kind: "VirtualMCPServer", Name: vmcp.Name})
229+
refs = append(refs, mcpv1alpha1.WorkloadReference{Kind: mcpv1alpha1.WorkloadKindVirtualMCPServer, Name: vmcp.Name})
231230
}
232231
}
233232

233+
ctrlutil.SortWorkloadRefs(refs)
234234
return refs, nil
235235
}
236236

@@ -275,7 +275,7 @@ func (r *MCPOIDCConfigReconciler) SetupWithManager(mgr ctrl.Manager) error {
275275
continue
276276
}
277277
for _, ref := range cfg.Status.ReferencingWorkloads {
278-
if ref.Kind == "MCPServer" && ref.Name == server.Name {
278+
if ref.Kind == mcpv1alpha1.WorkloadKindMCPServer && ref.Name == server.Name {
279279
requests = append(requests, reconcile.Request{NamespacedName: nn})
280280
break
281281
}
@@ -333,7 +333,7 @@ func (r *MCPOIDCConfigReconciler) mapVirtualMCPServerToOIDCConfig(
333333
continue
334334
}
335335
for _, ref := range cfg.Status.ReferencingWorkloads {
336-
if ref.Kind == "VirtualMCPServer" && ref.Name == vmcp.Name {
336+
if ref.Kind == mcpv1alpha1.WorkloadKindVirtualMCPServer && ref.Name == vmcp.Name {
337337
requests = append(requests, reconcile.Request{NamespacedName: nn})
338338
break
339339
}

cmd/thv-operator/controllers/mcpserver_controller.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2132,7 +2132,7 @@ func (r *MCPServerReconciler) updateOIDCConfigReferencingWorkloads(
21322132
serverName string,
21332133
) error {
21342134
ref := mcpv1alpha1.WorkloadReference{
2135-
Kind: "MCPServer",
2135+
Kind: mcpv1alpha1.WorkloadKindMCPServer,
21362136
Name: serverName,
21372137
}
21382138

cmd/thv-operator/controllers/mcptelemetryconfig_controller.go

Lines changed: 9 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ package controllers
66
import (
77
"context"
88
"fmt"
9-
"slices"
109
"time"
1110

1211
"k8s.io/apimachinery/pkg/api/errors"
@@ -116,7 +115,7 @@ func (r *MCPTelemetryConfigReconciler) Reconcile(ctx context.Context, req ctrl.R
116115

117116
// Check what changed
118117
hashChanged := telemetryConfig.Status.ConfigHash != configHash
119-
refsChanged := !workloadRefsEqual(telemetryConfig.Status.ReferencingWorkloads, referencingWorkloads)
118+
refsChanged := !ctrlutil.WorkloadRefsEqual(telemetryConfig.Status.ReferencingWorkloads, referencingWorkloads)
120119
needsUpdate := hashChanged || refsChanged || conditionChanged
121120

122121
if hashChanged {
@@ -180,7 +179,7 @@ func (r *MCPTelemetryConfigReconciler) SetupWithManager(mgr ctrl.Manager) error
180179
continue
181180
}
182181
for _, ref := range cfg.Status.ReferencingWorkloads {
183-
if ref.Kind == "MCPServer" && ref.Name == server.Name {
182+
if ref.Kind == mcpv1alpha1.WorkloadKindMCPServer && ref.Name == server.Name {
184183
requests = append(requests, reconcile.Request{NamespacedName: nn})
185184
break
186185
}
@@ -257,36 +256,11 @@ func (r *MCPTelemetryConfigReconciler) findReferencingWorkloads(
257256
ctx context.Context,
258257
telemetryConfig *mcpv1alpha1.MCPTelemetryConfig,
259258
) ([]mcpv1alpha1.WorkloadReference, error) {
260-
mcpServerList := &mcpv1alpha1.MCPServerList{}
261-
if err := r.List(ctx, mcpServerList, client.InNamespace(telemetryConfig.Namespace)); err != nil {
262-
return nil, fmt.Errorf("failed to list MCPServers: %w", err)
263-
}
264-
265-
var refs []mcpv1alpha1.WorkloadReference
266-
for _, server := range mcpServerList.Items {
267-
if server.Spec.TelemetryConfigRef != nil &&
268-
server.Spec.TelemetryConfigRef.Name == telemetryConfig.Name {
269-
refs = append(refs, mcpv1alpha1.WorkloadReference{
270-
Kind: "MCPServer",
271-
Name: server.Name,
272-
})
273-
}
274-
}
275-
slices.SortFunc(refs, func(a, b mcpv1alpha1.WorkloadReference) int {
276-
if a.Name < b.Name {
277-
return -1
278-
}
279-
if a.Name > b.Name {
280-
return 1
281-
}
282-
return 0
283-
})
284-
return refs, nil
285-
}
286-
287-
// workloadRefsEqual compares two WorkloadReference slices for equality.
288-
func workloadRefsEqual(a, b []mcpv1alpha1.WorkloadReference) bool {
289-
return slices.EqualFunc(a, b, func(x, y mcpv1alpha1.WorkloadReference) bool {
290-
return x.Kind == y.Kind && x.Name == y.Name
291-
})
259+
return ctrlutil.FindWorkloadRefsFromMCPServers(ctx, r.Client, telemetryConfig.Namespace, telemetryConfig.Name,
260+
func(server *mcpv1alpha1.MCPServer) *string {
261+
if server.Spec.TelemetryConfigRef != nil {
262+
return &server.Spec.TelemetryConfigRef.Name
263+
}
264+
return nil
265+
})
292266
}

cmd/thv-operator/controllers/toolconfig_controller.go

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ package controllers
66
import (
77
"context"
88
"fmt"
9-
"slices"
109
"time"
1110

1211
"k8s.io/apimachinery/pkg/api/errors"
@@ -102,7 +101,7 @@ func (r *ToolConfigReconciler) Reconcile(ctx context.Context, req ctrl.Request)
102101
referencingWorkloads, err := r.findReferencingWorkloads(ctx, toolConfig)
103102
if err != nil {
104103
logger.Error(err, "Failed to find referencing workloads")
105-
} else if !slices.Equal(toolConfig.Status.ReferencingWorkloads, referencingWorkloads) {
104+
} else if !ctrlutil.WorkloadRefsEqual(toolConfig.Status.ReferencingWorkloads, referencingWorkloads) {
106105
toolConfig.Status.ReferencingWorkloads = referencingWorkloads
107106
conditionChanged = true
108107
}
@@ -144,8 +143,9 @@ func (r *ToolConfigReconciler) handleConfigHashChange(
144143
// Update the status with the list of referencing workloads
145144
refs := make([]mcpv1alpha1.WorkloadReference, 0, len(referencingServers))
146145
for _, server := range referencingServers {
147-
refs = append(refs, mcpv1alpha1.WorkloadReference{Kind: "MCPServer", Name: server.Name})
146+
refs = append(refs, mcpv1alpha1.WorkloadReference{Kind: mcpv1alpha1.WorkloadKindMCPServer, Name: server.Name})
148147
}
148+
ctrlutil.SortWorkloadRefs(refs)
149149
toolConfig.Status.ReferencingWorkloads = refs
150150

151151
// Update the MCPToolConfig status
@@ -228,18 +228,13 @@ func (r *ToolConfigReconciler) findReferencingWorkloads(
228228
ctx context.Context,
229229
toolConfig *mcpv1alpha1.MCPToolConfig,
230230
) ([]mcpv1alpha1.WorkloadReference, error) {
231-
mcpServerList := &mcpv1alpha1.MCPServerList{}
232-
if err := r.List(ctx, mcpServerList, client.InNamespace(toolConfig.Namespace)); err != nil {
233-
return nil, fmt.Errorf("failed to list MCPServers: %w", err)
234-
}
235-
236-
var refs []mcpv1alpha1.WorkloadReference
237-
for _, server := range mcpServerList.Items {
238-
if server.Spec.ToolConfigRef != nil && server.Spec.ToolConfigRef.Name == toolConfig.Name {
239-
refs = append(refs, mcpv1alpha1.WorkloadReference{Kind: "MCPServer", Name: server.Name})
240-
}
241-
}
242-
return refs, nil
231+
return ctrlutil.FindWorkloadRefsFromMCPServers(ctx, r.Client, toolConfig.Namespace, toolConfig.Name,
232+
func(server *mcpv1alpha1.MCPServer) *string {
233+
if server.Spec.ToolConfigRef != nil {
234+
return &server.Spec.ToolConfigRef.Name
235+
}
236+
return nil
237+
})
243238
}
244239

245240
// findReferencingMCPServers finds all MCPServers that reference the given MCPToolConfig.
@@ -298,7 +293,7 @@ func (r *ToolConfigReconciler) SetupWithManager(mgr ctrl.Manager) error {
298293
continue
299294
}
300295
for _, ref := range cfg.Status.ReferencingWorkloads {
301-
if ref.Kind == "MCPServer" && ref.Name == server.Name {
296+
if ref.Kind == mcpv1alpha1.WorkloadKindMCPServer && ref.Name == server.Name {
302297
requests = append(requests, reconcile.Request{NamespacedName: nn})
303298
break
304299
}

cmd/thv-operator/controllers/virtualmcpserver_controller.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2824,7 +2824,7 @@ func (r *VirtualMCPServerReconciler) updateOIDCConfigReferencingWorkloads(
28242824
oidcConfig *mcpv1alpha1.MCPOIDCConfig,
28252825
vmcpName string,
28262826
) error {
2827-
ref := mcpv1alpha1.WorkloadReference{Kind: "VirtualMCPServer", Name: vmcpName}
2827+
ref := mcpv1alpha1.WorkloadReference{Kind: mcpv1alpha1.WorkloadKindVirtualMCPServer, Name: vmcpName}
28282828
// Check if already listed
28292829
for _, entry := range oidcConfig.Status.ReferencingWorkloads {
28302830
if entry.Kind == ref.Kind && entry.Name == ref.Name {

cmd/thv-operator/pkg/controllerutil/config.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import (
77
"context"
88
"fmt"
99
"hash/fnv"
10+
"slices"
11+
"strings"
1012

1113
"k8s.io/apimachinery/pkg/types"
1214
"k8s.io/apimachinery/pkg/util/dump"
@@ -72,6 +74,52 @@ func FindReferencingMCPServers(
7274
return referencingServers, nil
7375
}
7476

77+
// CompareWorkloadRefs compares two WorkloadReference values by Kind then Name.
78+
// Suitable for use with slices.SortFunc.
79+
func CompareWorkloadRefs(a, b mcpv1alpha1.WorkloadReference) int {
80+
if a.Kind != b.Kind {
81+
return strings.Compare(a.Kind, b.Kind)
82+
}
83+
return strings.Compare(a.Name, b.Name)
84+
}
85+
86+
// SortWorkloadRefs sorts a WorkloadReference slice by Kind then Name for deterministic ordering.
87+
// This prevents unnecessary API server writes when the same set of workloads is discovered
88+
// in a different list order across reconcile runs.
89+
func SortWorkloadRefs(refs []mcpv1alpha1.WorkloadReference) {
90+
slices.SortFunc(refs, CompareWorkloadRefs)
91+
}
92+
93+
// WorkloadRefsEqual reports whether two WorkloadReference slices contain the same entries.
94+
// Both slices must already be sorted (use SortWorkloadRefs) for correct results.
95+
func WorkloadRefsEqual(a, b []mcpv1alpha1.WorkloadReference) bool {
96+
return slices.EqualFunc(a, b, func(x, y mcpv1alpha1.WorkloadReference) bool {
97+
return x.Kind == y.Kind && x.Name == y.Name
98+
})
99+
}
100+
101+
// FindWorkloadRefsFromMCPServers returns a sorted list of WorkloadReference for MCPServers
102+
// in the given namespace that reference a config identified by configName.
103+
// The refExtractor determines which spec field contains the config reference name.
104+
func FindWorkloadRefsFromMCPServers(
105+
ctx context.Context,
106+
c client.Client,
107+
namespace string,
108+
configName string,
109+
refExtractor func(*mcpv1alpha1.MCPServer) *string,
110+
) ([]mcpv1alpha1.WorkloadReference, error) {
111+
servers, err := FindReferencingMCPServers(ctx, c, namespace, configName, refExtractor)
112+
if err != nil {
113+
return nil, err
114+
}
115+
refs := make([]mcpv1alpha1.WorkloadReference, 0, len(servers))
116+
for _, server := range servers {
117+
refs = append(refs, mcpv1alpha1.WorkloadReference{Kind: mcpv1alpha1.WorkloadKindMCPServer, Name: server.Name})
118+
}
119+
SortWorkloadRefs(refs)
120+
return refs, nil
121+
}
122+
75123
// GetToolConfigForMCPRemoteProxy fetches MCPToolConfig referenced by MCPRemoteProxy
76124
func GetToolConfigForMCPRemoteProxy(
77125
ctx context.Context,

0 commit comments

Comments
 (0)