Skip to content

Commit

Permalink
Add flag for allowing status updates even when resource is being deleted
Browse files Browse the repository at this point in the history
  • Loading branch information
andrew-su committed Feb 5, 2025
1 parent 8872d52 commit 7e6aa85
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 6 deletions.
6 changes: 5 additions & 1 deletion reconcilers/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ type ResourceReconciler[Type client.Object] struct {
// conflicts. Finalizers and events are still actionable.
SkipStatusUpdate bool

// AllowStatusUpdateDuringDeletion when true, the rsource's status will be updated even
// when the resource is marked for deletion.
AllowStatusUpdateDuringDeletion bool

// Reconciler is called for each reconciler request with the resource being reconciled.
// Typically, Reconciler is a Sequence of multiple SubReconcilers.
//
Expand Down Expand Up @@ -289,7 +293,7 @@ func (r *ResourceReconciler[T]) reconcileOuter(ctx context.Context, req Request)

// check if status has changed before updating
resourceStatus, originalResourceStatus := r.status(resource), r.status(originalResource)
if !equality.Semantic.DeepEqual(resourceStatus, originalResourceStatus) && resource.GetDeletionTimestamp() == nil {
if !equality.Semantic.DeepEqual(resourceStatus, originalResourceStatus) && (resource.GetDeletionTimestamp() == nil || r.AllowStatusUpdateDuringDeletion) {
if duck.IsDuck(resource, c.Scheme()) {
// patch status
log.Info("patching status", "diff", cmp.Diff(originalResourceStatus, resourceStatus, IgnoreAllUnexported))
Expand Down
73 changes: 68 additions & 5 deletions reconcilers/resource_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1024,6 +1024,64 @@ func TestResourceReconciler(t *testing.T) {
}),
},
},
"status does not update for deleted resource": {
Request: testRequest,
GivenObjects: []client.Object{
givenResource.MetadataDie(func(d *diemetav1.ObjectMetaDie) {
d.DeletionTimestamp(&deletedAt)
d.Finalizers(testFinalizer)
}),
},
Metadata: map[string]interface{}{
"SubReconciler": func(t *testing.T, c reconcilers.Config) reconcilers.SubReconciler[*resources.TestResource] {
return &reconcilers.SyncReconciler[*resources.TestResource]{
Sync: func(ctx context.Context, resource *resources.TestResource) error {
if resource.Status.Fields == nil {
resource.Status.Fields = map[string]string{}
}
resource.Status.Fields["Reconciler"] = "ran"
return nil
},
}
},
},
},
"status updates for deleting resource when allowed": {
Request: testRequest,
StatusSubResourceTypes: []client.Object{
&resources.TestResource{},
},
GivenObjects: []client.Object{
givenResource.MetadataDie(func(d *diemetav1.ObjectMetaDie) {
d.DeletionTimestamp(&deletedAt)
d.Finalizers(testFinalizer)
}),
},
Metadata: map[string]interface{}{
"AllowStatusUpdateDuringDeletion": true,
"SubReconciler": func(t *testing.T, c reconcilers.Config) reconcilers.SubReconciler[*resources.TestResource] {
return &reconcilers.SyncReconciler[*resources.TestResource]{
SyncDuringFinalization: true,
Sync: func(ctx context.Context, resource *resources.TestResource) error {
if resource.Status.Fields == nil {
resource.Status.Fields = map[string]string{}
}
resource.Status.Fields["Reconciler"] = "ran"
return nil
},
}
},
},
ExpectEvents: []rtesting.Event{
rtesting.NewEvent(givenResource, scheme, corev1.EventTypeNormal, "StatusUpdated",
`Updated status`),
},
ExpectStatusUpdates: []client.Object{
givenResource.StatusDie(func(d *dies.TestResourceStatusDie) {
d.AddField("Reconciler", "ran")
}),
},
},
"skip status updates": {
Request: testRequest,
GivenObjects: []client.Object{
Expand Down Expand Up @@ -1433,6 +1491,10 @@ func TestResourceReconciler(t *testing.T) {
if skip, ok := rtc.Metadata["SkipStatusUpdate"].(bool); ok {
skipStatusUpdate = skip
}
allowStatusUpdateDuringDeletion := false
if allow, ok := rtc.Metadata["AllowStatusUpdateDuringDeletion"].(bool); ok {
allowStatusUpdateDuringDeletion = allow
}
var beforeReconcile func(context.Context, reconcilers.Request) (context.Context, reconcilers.Result, error)
if before, ok := rtc.Metadata["BeforeReconcile"].(func(context.Context, reconcilers.Request) (context.Context, reconcilers.Result, error)); ok {
beforeReconcile = before
Expand All @@ -1442,11 +1504,12 @@ func TestResourceReconciler(t *testing.T) {
afterReconcile = after
}
return &reconcilers.ResourceReconciler[*resources.TestResource]{
Reconciler: rtc.Metadata["SubReconciler"].(func(*testing.T, reconcilers.Config) reconcilers.SubReconciler[*resources.TestResource])(t, c),
SkipStatusUpdate: skipStatusUpdate,
BeforeReconcile: beforeReconcile,
AfterReconcile: afterReconcile,
Config: c,
Reconciler: rtc.Metadata["SubReconciler"].(func(*testing.T, reconcilers.Config) reconcilers.SubReconciler[*resources.TestResource])(t, c),
SkipStatusUpdate: skipStatusUpdate,
AllowStatusUpdateDuringDeletion: allowStatusUpdateDuringDeletion,
BeforeReconcile: beforeReconcile,
AfterReconcile: afterReconcile,
Config: c,
}
})
}
Expand Down

0 comments on commit 7e6aa85

Please sign in to comment.