Skip to content

Commit

Permalink
Add PatchE method
Browse files Browse the repository at this point in the history
Signed-off-by: Tamal Saha <[email protected]>
  • Loading branch information
tamalsaha committed Dec 10, 2024
1 parent 142fd18 commit 925693d
Showing 1 changed file with 61 additions and 5 deletions.
66 changes: 61 additions & 5 deletions client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,10 @@ func NewUncachedClient(cfg *rest.Config, funcs ...func(*runtime.Scheme) error) (
}

type (
TransformFunc func(obj client.Object, createOp bool) client.Object
TransformFuncE func(obj client.Object, createOp bool) (client.Object, error)
TransformStatusFunc func(obj client.Object) client.Object
TransformFunc func(obj client.Object, createOp bool) client.Object
TransformFuncE func(obj client.Object, createOp bool) (client.Object, error)
PatchFunc func(obj client.Object) client.Object
PatchFuncE func(obj client.Object) (client.Object, error)
)

func CreateOrPatchE(ctx context.Context, c client.Client, obj client.Object, transform TransformFuncE, opts ...client.PatchOption) (kutil.VerbType, error) {
Expand Down Expand Up @@ -147,6 +148,51 @@ func CreateOrPatch(ctx context.Context, c client.Client, obj client.Object, tran
}, opts...)
}

func PatchE(ctx context.Context, c client.Client, obj client.Object, transform PatchFuncE, opts ...client.PatchOption) (kutil.VerbType, error) {
gvk, err := apiutil.GVKForObject(obj, c.Scheme())
if err != nil {
return kutil.VerbUnchanged, errors.Wrapf(err, "failed to get GVK for object %T", obj)
}

_, unstructuredObj := obj.(*unstructured.Unstructured)

var patch client.Patch
if isOfficialTypes(gvk.Group) && !unstructuredObj {
patch = client.StrategicMergeFrom(obj)
} else {
patch = client.MergeFrom(obj)
}
mod, err := transform(obj.DeepCopyObject().(client.Object))
if err != nil {
return kutil.VerbUnchanged, err
}
err = c.Patch(ctx, mod, patch, opts...)
if err != nil {
return kutil.VerbUnchanged, err
}

vt := kutil.VerbUnchanged
if mod.GetGeneration() > 0 {
if obj.GetGeneration() != mod.GetGeneration() {
vt = kutil.VerbPatched
}
} else {
// Secret, ServiceAccount etc resources do not use metadata.generation
if meta.ObjectHash(obj) != meta.ObjectHash(mod) {
vt = kutil.VerbPatched
}
}
assign(obj, mod)
return vt, nil
}

func Patch(ctx context.Context, c client.Client, obj client.Object, transform PatchFunc, opts ...client.PatchOption) (kutil.VerbType, error) {
return PatchE(ctx, c, obj, func(obj client.Object) (client.Object, error) {
transform(obj)
return obj, nil
}, opts...)
}

func assign(target, src any) {
srcValue := reflect.ValueOf(src)
if srcValue.Kind() == reflect.Pointer {
Expand All @@ -155,7 +201,7 @@ func assign(target, src any) {
reflect.ValueOf(target).Elem().Set(srcValue)
}

func PatchStatus(ctx context.Context, c client.Client, obj client.Object, transform TransformStatusFunc, opts ...client.SubResourcePatchOption) (kutil.VerbType, error) {
func PatchStatusE(ctx context.Context, c client.Client, obj client.Object, transform PatchFuncE, opts ...client.SubResourcePatchOption) (kutil.VerbType, error) {
cur := obj.DeepCopyObject().(client.Object)
key := types.NamespacedName{
Namespace: cur.GetNamespace(),
Expand All @@ -172,7 +218,10 @@ func PatchStatus(ctx context.Context, c client.Client, obj client.Object, transf
// - application/merge-patch+json,
// - application/apply-patch+yaml
patch := client.MergeFrom(cur)
mod := transform(cur.DeepCopyObject().(client.Object))
mod, err := transform(cur.DeepCopyObject().(client.Object))
if err != nil {
return kutil.VerbUnchanged, err
}
err = c.Status().Patch(ctx, mod, patch, opts...)
if err != nil {
return kutil.VerbUnchanged, err
Expand All @@ -181,6 +230,13 @@ func PatchStatus(ctx context.Context, c client.Client, obj client.Object, transf
return kutil.VerbPatched, nil
}

func PatchStatus(ctx context.Context, c client.Client, obj client.Object, transform PatchFunc, opts ...client.SubResourcePatchOption) (kutil.VerbType, error) {
return PatchStatusE(ctx, c, obj, func(obj client.Object) (client.Object, error) {
transform(obj)
return obj, nil
}, opts...)
}

func isOfficialTypes(group string) bool {
return !strings.ContainsRune(group, '.')
}
Expand Down

0 comments on commit 925693d

Please sign in to comment.