Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generic instance update func #117

Merged
merged 1 commit into from
Jan 9, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 65 additions & 0 deletions modules/common/helper/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ limitations under the License.
package helper

import (
"context"
"encoding/json"

"github.com/go-logr/logr"
Expand All @@ -28,6 +29,9 @@ import (

"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/client/apiutil"
"sigs.k8s.io/controller-runtime/pkg/log"

k8s_errors "k8s.io/apimachinery/pkg/api/errors"
)

// Helper is a utility for ensuring the proper patching of objects.
Expand Down Expand Up @@ -164,6 +168,67 @@ func (h *Helper) calculateChanges(after client.Object) (map[string]bool, error)
return res, nil
}

// PatchInstance - Patch an instance's metadata and/or status if they have changed (based
// on comparison with its old state as represented in the helper.Helper)
//
// NOTE: This function is mainly intended for use in Podified Operators with their
// deferred-instance-persistence pattern within the reconcile loop. If used in this manner,
// any error returned by this function should be set as the error returned by the encompassing
// Reconcile(...) function so that the error from PatchInstance is properly propagated.
//
// Example:
//
// func (r *SomeReconciler) Reconcile(ctx context.Context, req ctrl.Request) (result ctrl.Result, _err error) {
// ...
// defer func() {
// ...
// err := instance.PatchInstance(ctx, h, instance)
// if err != nil {
// _err = err
// return
// }
// }
// ...
// }
//
func (h *Helper) PatchInstance(ctx context.Context, instance client.Object) error {
var err error

l := log.FromContext(ctx)

if err = h.SetAfter(instance); err != nil {
l.Error(err, "Set after and calc patch/diff")
return err
}

changes := h.GetChanges()
patch := client.MergeFrom(h.GetBeforeObject())

if changes["metadata"] {
err = h.GetClient().Patch(ctx, instance, patch)
if k8s_errors.IsConflict(err) {
l.Info("Metadata update conflict")
return err
} else if err != nil && !k8s_errors.IsNotFound(err) {
l.Error(err, "Metadate update failed")
return err
}
}

if changes["status"] {
err = h.GetClient().Status().Patch(ctx, instance, patch)
if k8s_errors.IsConflict(err) {
l.Info("Status update conflict")
return err

} else if err != nil && !k8s_errors.IsNotFound(err) {
l.Error(err, "Status update failed")
return err
}
}
return nil
}

// ToUnstructured - convert to unstructured
func ToUnstructured(obj runtime.Object) (*unstructured.Unstructured, error) {
// If the incoming object is already unstructured, perform a deep copy first
Expand Down