Skip to content

Commit ed2bc1b

Browse files
committed
Fix: Add owner reference to existing resources when initially missing
Fixes #8718 ReconcileResource now checks and updates owner references independently of the NeedsUpdate function. Previously, if a resource existed without an owner reference and NeedsUpdate returned false (because data, labels, and annotations were unchanged), the owner reference would never be added. Changes: Added owner reference check before the NeedsUpdate block in ReconcileResource Owner references are now added to existing resources even when other fields don't require updates Added test case to verify owner reference is added when NeedsUpdate returns false The fix ensures proper resource ownership management and enables garbage collection for resources that were created before owner references were implemented.
1 parent face37a commit ed2bc1b

File tree

2 files changed

+80
-0
lines changed

2 files changed

+80
-0
lines changed

pkg/controller/common/reconciler/reconciler.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,49 @@ func ReconcileResource(params Params) error {
144144
log.Info("Deleted resource successfully")
145145
return create()
146146
}
147+
// Check if owner reference needs to be added/updated independently of NeedsUpdate
148+
if params.Owner != nil {
149+
reconciledMeta, err := meta.Accessor(params.Reconciled)
150+
if err != nil {
151+
return err
152+
}
153+
expectedMeta, err := meta.Accessor(params.Expected)
154+
if err != nil {
155+
return err
156+
}
157+
expectedOwners := expectedMeta.GetOwnerReferences()
147158

159+
// Check if we need to update the owner reference
160+
needsOwnerUpdate := false
161+
if len(expectedOwners) > 0 {
162+
reconciledOwners := reconciledMeta.GetOwnerReferences()
163+
// Check if controller reference is missing or different
164+
controllerRefIndex := -1
165+
for i, owner := range reconciledOwners {
166+
if owner.Controller != nil && *owner.Controller {
167+
controllerRefIndex = i
168+
break
169+
}
170+
}
171+
172+
if controllerRefIndex == -1 {
173+
// No controller reference exists
174+
needsOwnerUpdate = true
175+
} else if reconciledOwners[controllerRefIndex].UID != expectedOwners[0].UID {
176+
// Controller reference exists but points to a different owner
177+
needsOwnerUpdate = true
178+
}
179+
}
180+
181+
if needsOwnerUpdate {
182+
log.Info("Updating owner reference")
183+
k8s.OverrideControllerReference(reconciledMeta, expectedOwners[0])
184+
if err := params.Client.Update(params.Context, params.Reconciled); err != nil {
185+
return err
186+
}
187+
log.Info("Updated owner reference successfully", resourceVersionKey, params.Reconciled.GetResourceVersion())
188+
}
189+
}
148190
//nolint:nestif
149191
// Update if needed
150192
if params.NeedsUpdate() {

pkg/controller/common/reconciler/reconciler_test.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,44 @@ func TestReconcileResource(t *testing.T) {
258258
require.Equal(t, "newOwner", serverState.OwnerReferences[0].Name)
259259
},
260260
},
261+
{
262+
name: "Add owner reference to existing resource without owner when NeedsUpdate returns false",
263+
args: func() args {
264+
return args{
265+
Expected: obj.DeepCopy(),
266+
Reconciled: &corev1.Secret{},
267+
Owner: &appsv1.Deployment{
268+
ObjectMeta: metav1.ObjectMeta{
269+
Namespace: objectKey.Namespace,
270+
Name: "test-owner",
271+
UID: "test-uid",
272+
},
273+
},
274+
NeedsUpdate: func() bool {
275+
return false
276+
},
277+
UpdateReconciled: noopModifier,
278+
}
279+
},
280+
initialObjects: []client.Object{
281+
&corev1.Secret{
282+
ObjectMeta: metav1.ObjectMeta{
283+
Namespace: objectKey.Namespace,
284+
Name: objectKey.Name,
285+
},
286+
},
287+
},
288+
argAssertion: func(args args) {
289+
accessor, err := meta.Accessor(args.Reconciled)
290+
require.NoError(t, err)
291+
require.Len(t, accessor.GetOwnerReferences(), 1, "owner reference should be added")
292+
require.Equal(t, "test-owner", accessor.GetOwnerReferences()[0].Name)
293+
},
294+
serverStateAssertion: func(serverState corev1.Secret) {
295+
require.Len(t, serverState.OwnerReferences, 1, "owner reference should be added on server")
296+
require.Equal(t, "test-owner", serverState.OwnerReferences[0].Name)
297+
},
298+
},
261299
}
262300
for _, tt := range tests {
263301
t.Run(tt.name, func(t *testing.T) {

0 commit comments

Comments
 (0)