Skip to content

Commit

Permalink
create StatusIgnore helper option for PatchHelper
Browse files Browse the repository at this point in the history
Signed-off-by: Troy Connor <[email protected]>
  • Loading branch information
troy0820 committed Jun 21, 2024
1 parent 54c8e46 commit d6ac4de
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 4 deletions.
12 changes: 12 additions & 0 deletions util/patch/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ type HelperOptions struct {
// OwnedConditions defines condition types owned by the controller.
// In case of conflicts for the owned conditions, the patch helper will always use the value provided by the controller.
OwnedConditions []clusterv1.ConditionType

// StatusIgnore will not patch the status if true and only patch the spec
StatusIgnore bool
}

// WithForceOverwriteConditions allows the patch helper to overwrite conditions in case of conflicts.
Expand Down Expand Up @@ -67,3 +70,12 @@ type WithOwnedConditions struct {
func (w WithOwnedConditions) ApplyToHelper(in *HelperOptions) {
in.OwnedConditions = w.Conditions
}

// WithStatusIgnore allows the patch helper to not patch the status when
// patching an object. The spec and metadata will still be patched using this option.
type WithStatusIgnore struct{}

// ApplyToHelper applies this configuration to the given HelperOptions.
func (w WithStatusIgnore) ApplyToHelper(in *HelperOptions) {
in.StatusIgnore = true
}
13 changes: 9 additions & 4 deletions util/patch/patch.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,15 +138,20 @@ func (h *Helper) Patch(ctx context.Context, obj client.Object, opts ...Option) e
// Given that we pass in metadata.resourceVersion to perform a 3-way-merge conflict resolution,
// patching conditions first avoids an extra loop if spec or status patch succeeds first
// given that causes the resourceVersion to mutate.
if err := h.patchStatusConditions(ctx, obj, options.ForceOverwriteConditions, options.OwnedConditions); err != nil {
errs = append(errs, err)
if !options.StatusIgnore {
if err := h.patchStatusConditions(ctx, obj, options.ForceOverwriteConditions, options.OwnedConditions); err != nil {
errs = append(errs, err)
}
}
// Then proceed to patch the rest of the object.
if err := h.patch(ctx, obj); err != nil {
errs = append(errs, err)
}
if err := h.patchStatus(ctx, obj); err != nil {
errs = append(errs, err)

if !options.StatusIgnore {
if err := h.patchStatus(ctx, obj); err != nil {
errs = append(errs, err)
}
}

if len(errs) > 0 {
Expand Down
58 changes: 58 additions & 0 deletions util/patch/patch_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -868,6 +868,64 @@ func TestPatchHelper(t *testing.T) {
})
})

t.Run("Should not update the status when using StatusIgnore option", func(t *testing.T) {
obj := &clusterv1.MachineSet{
ObjectMeta: metav1.ObjectMeta{
GenerateName: "test-ms",
Namespace: ns.Name,
},
Spec: clusterv1.MachineSetSpec{
ClusterName: "test1",
Template: clusterv1.MachineTemplateSpec{
Spec: clusterv1.MachineSpec{
ClusterName: "test1",
},
},
},
}

t.Run("when updating spec", func(t *testing.T) {
g := NewWithT(t)

obj := obj.DeepCopy()

t.Log("Creating the MachineSet object")
g.Expect(env.Create(ctx, obj)).To(Succeed())
defer func() {
g.Expect(env.Delete(ctx, obj)).To(Succeed())
}()
key := client.ObjectKey{Name: obj.Name, Namespace: obj.Namespace}

t.Log("Checking that the object has been created")
g.Eventually(func() error {
obj := obj.DeepCopy()
return env.Get(ctx, key, obj)
}).Should(Succeed())

t.Log("Creating a new patch helper")
patcher, err := NewHelper(obj, env)
g.Expect(err).ToNot(HaveOccurred())

t.Log("Updating the object spec")
obj.Spec.Replicas = ptr.To[int32](10)
obj.Status.Replicas = int32(10)

t.Log("Patching the object")
g.Expect(patcher.Patch(ctx, obj, WithStatusIgnore{})).To(Succeed())

t.Log("Validating the object has been updated")
g.Eventually(func() bool {
objAfter := obj.DeepCopy()
if err := env.Get(ctx, key, objAfter); err != nil {
return false
}

return cmp.Equal(obj.Spec, objAfter.Spec) &&
obj.Status.Replicas != objAfter.Status.Replicas
}, timeout).Should(BeTrue())
})
})

t.Run("Should error if the object isn't the same", func(t *testing.T) {
g := NewWithT(t)

Expand Down

0 comments on commit d6ac4de

Please sign in to comment.