Skip to content

Commit b3ac5d3

Browse files
committed
Separate CrunchyBridgeClusterReconciler client concerns
We want to be mindful of our interactions with the Kubernetes API, and these interfaces will help keep functions focused. These interfaces are also narrower than client.Reader and client.Writer and may help us keep RBAC markers accurate. A new constructor populates these fields with a single client.Client. The client.WithFieldOwner constructor allows us to drop our Owner field and patch method. This allows `make check` to cover 47% more of the "crunchybridgecluster" package.
1 parent 5ed7ca8 commit b3ac5d3

File tree

10 files changed

+70
-173
lines changed

10 files changed

+70
-173
lines changed

cmd/postgres-operator/main.go

Lines changed: 11 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -248,19 +248,22 @@ func main() {
248248
must(manager.Add(registrar))
249249
token, _ := registrar.CheckToken()
250250

251+
bridgeURL := os.Getenv("PGO_BRIDGE_URL")
252+
bridgeClient := func() *bridge.Client {
253+
client := bridge.NewClient(bridgeURL, versionString)
254+
client.Transport = otelTransportWrapper()(http.DefaultTransport)
255+
return client
256+
}
257+
251258
// add all PostgreSQL Operator controllers to the runtime manager
252259
addControllersToManager(manager, log, registrar)
253260
must(standalone_pgadmin.ManagedReconciler(manager))
261+
must(crunchybridgecluster.ManagedReconciler(manager, func() bridge.ClientInterface {
262+
return bridgeClient()
263+
}))
254264

255265
if features.Enabled(feature.BridgeIdentifiers) {
256-
url := os.Getenv("PGO_BRIDGE_URL")
257-
constructor := func() *bridge.Client {
258-
client := bridge.NewClient(url, versionString)
259-
client.Transport = otelTransportWrapper()(http.DefaultTransport)
260-
return client
261-
}
262-
263-
must(bridge.ManagedInstallationReconciler(manager, constructor))
266+
must(bridge.ManagedInstallationReconciler(manager, bridgeClient))
264267
}
265268

266269
// Enable upgrade checking
@@ -329,21 +332,4 @@ func addControllersToManager(mgr runtime.Manager, log logging.Logger, reg regist
329332
log.Error(err, "unable to create PGUpgrade controller")
330333
os.Exit(1)
331334
}
332-
333-
constructor := func() bridge.ClientInterface {
334-
client := bridge.NewClient(os.Getenv("PGO_BRIDGE_URL"), versionString)
335-
client.Transport = otelTransportWrapper()(http.DefaultTransport)
336-
return client
337-
}
338-
339-
crunchyBridgeClusterReconciler := &crunchybridgecluster.CrunchyBridgeClusterReconciler{
340-
Client: mgr.GetClient(),
341-
Owner: naming.ControllerCrunchyBridgeCluster,
342-
NewClient: constructor,
343-
}
344-
345-
if err := crunchyBridgeClusterReconciler.SetupWithManager(mgr); err != nil {
346-
log.Error(err, "unable to create CrunchyBridgeCluster controller")
347-
os.Exit(1)
348-
}
349335
}

internal/bridge/crunchybridgecluster/apply.go

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,23 +11,9 @@ import (
1111
"sigs.k8s.io/controller-runtime/pkg/client"
1212
)
1313

14-
// patch sends patch to object's endpoint in the Kubernetes API and updates
15-
// object with any returned content. The fieldManager is set to r.Owner, but
16-
// can be overridden in options.
17-
// - https://docs.k8s.io/reference/using-api/server-side-apply/#managers
18-
//
19-
// NOTE: This function is duplicated from a version in the postgrescluster package
20-
func (r *CrunchyBridgeClusterReconciler) patch(
21-
ctx context.Context, object client.Object,
22-
patch client.Patch, options ...client.PatchOption,
23-
) error {
24-
options = append([]client.PatchOption{r.Owner}, options...)
25-
return r.Patch(ctx, object, patch, options...)
26-
}
27-
2814
// apply sends an apply patch to object's endpoint in the Kubernetes API and
29-
// updates object with any returned content. The fieldManager is set to
30-
// r.Owner and the force parameter is true.
15+
// updates object with any returned content. The fieldManager is set by
16+
// r.Writer and the force parameter is true.
3117
// - https://docs.k8s.io/reference/using-api/server-side-apply/#managers
3218
// - https://docs.k8s.io/reference/using-api/server-side-apply/#conflicts
3319
//
@@ -40,7 +26,7 @@ func (r *CrunchyBridgeClusterReconciler) apply(ctx context.Context, object clien
4026

4127
// Send the apply-patch with force=true.
4228
if err == nil {
43-
err = r.patch(ctx, object, apply, client.ForceOwnership)
29+
err = r.Writer.Patch(ctx, object, apply, client.ForceOwnership)
4430
}
4531

4632
return err

internal/bridge/crunchybridgecluster/crunchybridgecluster_controller.go

Lines changed: 34 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -33,27 +33,38 @@ import (
3333

3434
// CrunchyBridgeClusterReconciler reconciles a CrunchyBridgeCluster object
3535
type CrunchyBridgeClusterReconciler struct {
36-
client.Client
37-
38-
Owner client.FieldOwner
39-
40-
// For this iteration, we will only be setting conditions rather than
41-
// setting conditions and emitting events. That may change in the future,
42-
// so we're leaving this EventRecorder here for now.
43-
// record.EventRecorder
44-
45-
// NewClient is called each time a new Client is needed.
36+
// NewClient is called each time a new bridge.Client is needed.
4637
NewClient func() bridge.ClientInterface
38+
39+
Reader interface {
40+
Get(context.Context, client.ObjectKey, client.Object, ...client.GetOption) error
41+
List(context.Context, client.ObjectList, ...client.ListOption) error
42+
}
43+
Writer interface {
44+
Delete(context.Context, client.Object, ...client.DeleteOption) error
45+
Patch(context.Context, client.Object, client.Patch, ...client.PatchOption) error
46+
Update(context.Context, client.Object, ...client.UpdateOption) error
47+
}
48+
StatusWriter interface {
49+
Patch(context.Context, client.Object, client.Patch, ...client.SubResourcePatchOption) error
50+
}
4751
}
4852

4953
//+kubebuilder:rbac:groups="postgres-operator.crunchydata.com",resources="crunchybridgeclusters",verbs={list,watch}
5054
//+kubebuilder:rbac:groups="",resources="secrets",verbs={list,watch}
5155

52-
// SetupWithManager sets up the controller with the Manager.
53-
func (r *CrunchyBridgeClusterReconciler) SetupWithManager(
54-
mgr ctrl.Manager,
55-
) error {
56-
return ctrl.NewControllerManagedBy(mgr).
56+
// ManagedReconciler creates a [CrunchyBridgeClusterReconciler] and adds it to m.
57+
func ManagedReconciler(m ctrl.Manager, newClient func() bridge.ClientInterface) error {
58+
kubernetes := client.WithFieldOwner(m.GetClient(), naming.ControllerCrunchyBridgeCluster)
59+
60+
reconciler := &CrunchyBridgeClusterReconciler{
61+
NewClient: newClient,
62+
Reader: kubernetes,
63+
StatusWriter: kubernetes.Status(),
64+
Writer: kubernetes,
65+
}
66+
67+
return ctrl.NewControllerManagedBy(m).
5768
For(&v1beta1.CrunchyBridgeCluster{}).
5869
Owns(&corev1.Secret{}).
5970
// Wake periodically to check Bridge API for all CrunchyBridgeClusters.
@@ -63,7 +74,7 @@ func (r *CrunchyBridgeClusterReconciler) SetupWithManager(
6374
runtime.NewTickerImmediate(5*time.Minute, event.GenericEvent{},
6475
handler.EnqueueRequestsFromMapFunc(func(ctx context.Context, _ client.Object) []ctrl.Request {
6576
var list v1beta1.CrunchyBridgeClusterList
66-
_ = r.List(ctx, &list)
77+
_ = reconciler.Reader.List(ctx, &list)
6778
return runtime.Requests(initialize.Pointers(list.Items...)...)
6879
}),
6980
),
@@ -72,10 +83,10 @@ func (r *CrunchyBridgeClusterReconciler) SetupWithManager(
7283
Watches(
7384
&corev1.Secret{},
7485
handler.EnqueueRequestsFromMapFunc(func(ctx context.Context, secret client.Object) []ctrl.Request {
75-
return runtime.Requests(r.findCrunchyBridgeClustersForSecret(ctx, client.ObjectKeyFromObject(secret))...)
86+
return runtime.Requests(reconciler.findCrunchyBridgeClustersForSecret(ctx, client.ObjectKeyFromObject(secret))...)
7687
}),
7788
).
78-
Complete(r)
89+
Complete(reconciler)
7990
}
8091

8192
// The owner reference created by controllerutil.SetControllerReference blocks
@@ -91,7 +102,7 @@ func (r *CrunchyBridgeClusterReconciler) SetupWithManager(
91102
func (r *CrunchyBridgeClusterReconciler) setControllerReference(
92103
owner *v1beta1.CrunchyBridgeCluster, controlled client.Object,
93104
) error {
94-
return controllerutil.SetControllerReference(owner, controlled, r.Scheme())
105+
return controllerutil.SetControllerReference(owner, controlled, runtime.Scheme)
95106
}
96107

97108
//+kubebuilder:rbac:groups="postgres-operator.crunchydata.com",resources="crunchybridgeclusters",verbs={get,patch,update}
@@ -113,14 +124,14 @@ func (r *CrunchyBridgeClusterReconciler) Reconcile(ctx context.Context, req ctrl
113124
// copy before returning from its cache.
114125
// - https://github.com/kubernetes-sigs/controller-runtime/issues/1235
115126
crunchybridgecluster := &v1beta1.CrunchyBridgeCluster{}
116-
err := r.Get(ctx, req.NamespacedName, crunchybridgecluster)
127+
err := r.Reader.Get(ctx, req.NamespacedName, crunchybridgecluster)
117128

118129
if err == nil {
119130
// Write any changes to the crunchybridgecluster status on the way out.
120131
before := crunchybridgecluster.DeepCopy()
121132
defer func() {
122133
if !equality.Semantic.DeepEqual(before.Status, crunchybridgecluster.Status) {
123-
status := r.Status().Patch(ctx, crunchybridgecluster, client.MergeFrom(before), r.Owner)
134+
status := r.StatusWriter.Patch(ctx, crunchybridgecluster, client.MergeFrom(before))
124135

125136
if err == nil && status != nil {
126137
err = status
@@ -684,7 +695,7 @@ func (r *CrunchyBridgeClusterReconciler) GetSecretKeys(
684695
}}
685696

686697
err := errors.WithStack(
687-
r.Get(ctx, client.ObjectKeyFromObject(existing), existing))
698+
r.Reader.Get(ctx, client.ObjectKeyFromObject(existing), existing))
688699

689700
if err == nil {
690701
if existing.Data["key"] != nil && existing.Data["team"] != nil {
@@ -707,7 +718,7 @@ func (r *CrunchyBridgeClusterReconciler) deleteControlled(
707718
version := object.GetResourceVersion()
708719
exactly := client.Preconditions{UID: &uid, ResourceVersion: &version}
709720

710-
return r.Delete(ctx, object, exactly)
721+
return r.Writer.Delete(ctx, object, exactly)
711722
}
712723

713724
return nil

0 commit comments

Comments
 (0)