Skip to content

Commit 6a23c9d

Browse files
committed
Optimize updateAndSetOwner to Reduce Multiple Updates and Prevent Conflicts
Signed-off-by: Oded Viner <[email protected]>
1 parent e881939 commit 6a23c9d

File tree

3 files changed

+281
-119
lines changed

3 files changed

+281
-119
lines changed

go.mod

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ require (
2121
github.com/ramendr/ramen/api v0.0.0-20240924121439-b7cba82de417
2222
github.com/ramendr/recipe v0.0.0-20240918115450-667b9d79599f
2323
github.com/stolostron/multicloud-operators-placementrule v1.2.4-1-20220311-8eedb3f.0.20230828200208-cd3c119a7fa0
24+
github.com/stretchr/testify v1.9.0
2425
github.com/vmware-tanzu/velero v1.9.1
2526
go.uber.org/zap v1.27.0
2627
golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67
@@ -76,6 +77,7 @@ require (
7677
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
7778
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
7879
github.com/pkg/errors v0.9.1 // indirect
80+
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
7981
github.com/prometheus/client_model v0.6.1 // indirect
8082
github.com/prometheus/common v0.59.1 // indirect
8183
github.com/prometheus/procfs v0.15.1 // indirect
@@ -100,6 +102,7 @@ require (
100102
golang.org/x/tools v0.28.0 // indirect
101103
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
102104
google.golang.org/protobuf v1.35.2 // indirect
105+
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
103106
gopkg.in/inf.v0 v0.9.1 // indirect
104107
gopkg.in/ini.v1 v1.67.0 // indirect
105108
gopkg.in/yaml.v2 v2.4.0 // indirect
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
package controllers
2+
3+
import (
4+
"context"
5+
"testing"
6+
7+
"github.com/stretchr/testify/assert"
8+
corev1 "k8s.io/api/core/v1"
9+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
10+
"k8s.io/apimachinery/pkg/runtime"
11+
"k8s.io/apimachinery/pkg/types"
12+
ctrl "sigs.k8s.io/controller-runtime"
13+
"sigs.k8s.io/controller-runtime/pkg/client/fake"
14+
15+
rmn "github.com/ramendr/ramen/api/v1alpha1"
16+
)
17+
18+
const (
19+
DRPCNameAnnotationTest = "drplacementcontrol.ramendr.openshift.io/drpc-name"
20+
DRPCNamespaceAnnotationTest = "drplacementcontrol.ramendr.openshift.io/drpc-namespace"
21+
DRPCFinalizerTest = "drpc.ramendr.openshift.io/finalizer"
22+
OCMBackupLabelKeyTest = "cluster.open-cluster-management.io/backup"
23+
OCMBackupLabelValueTest = "ramen"
24+
)
25+
26+
func TestUpdateAndSetOwnerAnnotationsFinalizerOwnerReference(t *testing.T) {
27+
// 1. Create a test scheme and register corev1 and custom resource types.
28+
scheme := runtime.NewScheme()
29+
err := corev1.AddToScheme(scheme)
30+
assert.NoError(t, err, "Failed to add corev1 to scheme")
31+
err = rmn.AddToScheme(scheme)
32+
assert.NoError(t, err, "Failed to add rmn to scheme")
33+
34+
// 2. Create test objects: DRPC and Placement (using a Pod for Placement).
35+
drpc := &rmn.DRPlacementControl{
36+
ObjectMeta: metav1.ObjectMeta{
37+
Name: "test-drpc",
38+
Namespace: "test-namespace",
39+
},
40+
}
41+
placementObj := &corev1.Pod{
42+
ObjectMeta: metav1.ObjectMeta{
43+
Name: "test-placement",
44+
Namespace: "test-namespace",
45+
},
46+
}
47+
48+
// 3. Create a fake client with the test objects.
49+
fakeClient := fake.NewClientBuilder().
50+
WithScheme(scheme).
51+
WithObjects(drpc, placementObj).
52+
Build()
53+
54+
// 4. Create DRPlacementControlReconciler reconciler instance.
55+
reconciler := &DRPlacementControlReconciler{
56+
Client: fakeClient,
57+
APIReader: fakeClient,
58+
Log: ctrl.Log.WithName("test"),
59+
Scheme: scheme,
60+
}
61+
62+
// 5. Call updateAndSetOwner(), which should:
63+
// - Add annotations to placement (DRPCNameAnnotation, DRPCNamespaceAnnotation)
64+
// - Add finalizers to both DRPC and placement
65+
// - Set the owner reference on DRPC pointing to placement
66+
// - Add the OCM backup label to DRPC.
67+
updated, err := reconciler.updateAndSetOwner(context.TODO(), drpc, placementObj, reconciler.Log)
68+
assert.NoError(t, err, "updateAndSetOwner should not return an error")
69+
assert.True(t, updated, "updateAndSetOwner should indicate that an update occurred")
70+
71+
// 6. Retrieve the updated DRPC.
72+
updatedDRPC := &rmn.DRPlacementControl{}
73+
err = fakeClient.Get(context.TODO(), types.NamespacedName{
74+
Namespace: drpc.GetNamespace(),
75+
Name: drpc.GetName(),
76+
}, updatedDRPC)
77+
assert.NoError(t, err, "Failed to get updated DRPC")
78+
79+
// 7. Retrieve the updated Placement.
80+
updatedPlacement := &corev1.Pod{}
81+
err = fakeClient.Get(context.TODO(), types.NamespacedName{
82+
Namespace: placementObj.GetNamespace(),
83+
Name: placementObj.GetName(),
84+
}, updatedPlacement)
85+
assert.NoError(t, err, "Failed to get updated placement")
86+
87+
// --- Verify Annotations on Placement ---
88+
annotations := updatedPlacement.GetAnnotations()
89+
assert.NotNil(t, annotations, "Placement should have annotations")
90+
assert.Equal(t, drpc.GetName(), annotations[DRPCNameAnnotationTest],
91+
"Placement should have the DRPC name annotation")
92+
assert.Equal(t, drpc.GetNamespace(), annotations[DRPCNamespaceAnnotationTest],
93+
"Placement should have the DRPC namespace annotation")
94+
95+
// --- Verify Finalizers on DRPC and Placement ---
96+
assert.Contains(t, updatedDRPC.GetFinalizers(), DRPCFinalizerTest, "DRPC should contain the finalizer")
97+
assert.Contains(t, updatedPlacement.GetFinalizers(), DRPCFinalizerTest, "Placement should contain the finalizer")
98+
99+
// --- Verify OwnerReference on DRPC ---
100+
ownerRefs := updatedDRPC.GetOwnerReferences()
101+
assert.NotEmpty(t, ownerRefs, "DRPC should have owner references")
102+
foundOwner := false
103+
for _, ownerRef := range ownerRefs {
104+
// Check that the owner reference matches the placement object's name and Kind ("Pod").
105+
if ownerRef.Name == placementObj.GetName() && ownerRef.Kind == "Pod" {
106+
foundOwner = true
107+
108+
break
109+
}
110+
}
111+
assert.True(t, foundOwner, "DRPC should have an owner reference with the placement object's name")
112+
113+
// --- Verify Label on DRPC ---
114+
labels := updatedDRPC.GetLabels()
115+
assert.NotNil(t, labels, "DRPC should have labels")
116+
assert.Equal(t, OCMBackupLabelValueTest, labels[OCMBackupLabelKeyTest],
117+
"DRPC should have the OCM backup label set correctly")
118+
}

0 commit comments

Comments
 (0)