diff --git a/pkg/utils/apply/apply.go b/pkg/utils/apply/apply.go index e671ab2e9..1e1f0ebbd 100644 --- a/pkg/utils/apply/apply.go +++ b/pkg/utils/apply/apply.go @@ -50,7 +50,8 @@ type Applicator interface { } type applyAction struct { - skipUpdate bool + skipUpdate bool + updateAnnotation bool } // ApplyOption is called before applying state to the object. @@ -80,13 +81,13 @@ func (fn creatorFn) createOrGetExisting(ctx context.Context, act *applyAction, c } type patcher interface { - patch(c, m client.Object) (client.Patch, error) + patch(c, m client.Object, a *applyAction) (client.Patch, error) } -type patcherFn func(c, m client.Object) (client.Patch, error) +type patcherFn func(c, m client.Object, a *applyAction) (client.Patch, error) -func (fn patcherFn) patch(c, m client.Object) (client.Patch, error) { - return fn(c, m) +func (fn patcherFn) patch(c, m client.Object, a *applyAction) (client.Patch, error) { + return fn(c, m, a) } // APIApplicator implements Applicator @@ -112,7 +113,7 @@ func (a *APIApplicator) Apply(ctx context.Context, desired client.Object, ao ... if err != nil { return err } - applyAct := new(applyAction) + applyAct := &applyAction{updateAnnotation: true} existing, err := a.createOrGetExisting(ctx, applyAct, a.c, desired, ao...) if err != nil { return err @@ -132,7 +133,7 @@ func (a *APIApplicator) Apply(ctx context.Context, desired client.Object, ao ... } loggingApply("patching object", desired) - patch, err := a.patcher.patch(existing, desired) + patch, err := a.patcher.patch(existing, desired, applyAct) if err != nil { return errors.Wrap(err, "cannot calculate patch by computing a three way diff") } @@ -169,8 +170,10 @@ func createOrGetExisting(ctx context.Context, act *applyAction, c client.Client, if err := executeApplyOptions(act, nil, desired, ao); err != nil { return nil, err } - if err := addLastAppliedConfigAnnotation(desired); err != nil { - return nil, err + if act.updateAnnotation { + if err := addLastAppliedConfigAnnotation(desired); err != nil { + return nil, err + } } loggingApply("creating object", desired) return nil, errors.Wrap(c.Create(ctx, desired), "cannot create object") @@ -275,3 +278,11 @@ func MakeCustomApplyOption(f func(existing, desired client.Object) error) ApplyO return f(existing, desired) } } + +// DisableUpdateAnnotation disable write last config to annotation +func DisableUpdateAnnotation() ApplyOption { + return func(a *applyAction, existing, _ client.Object) error { + a.updateAnnotation = false + return nil + } +} diff --git a/pkg/utils/apply/apply_resource_test.go b/pkg/utils/apply/apply_resource_test.go index 00a06a26c..55120b4ea 100644 --- a/pkg/utils/apply/apply_resource_test.go +++ b/pkg/utils/apply/apply_resource_test.go @@ -28,6 +28,7 @@ import ( "k8s.io/apimachinery/pkg/types" "k8s.io/utils/pointer" + "github.com/oam-dev/kubevela/pkg/oam" oamutil "github.com/oam-dev/kubevela/pkg/oam/util" ) @@ -84,6 +85,22 @@ var _ = Describe("Test apply", func() { By("Unsetted fields shoulde be removed or set to default value") Expect(*resultDeploy.Spec.Replicas).Should(Equal(int32(1))) Expect(len(resultDeploy.Spec.Template.Spec.Volumes)).Should(Equal(0)) + + deployUpdate := basicTestDeployment() + deployUpdate.Name = deploy.Name + "-no-update" + Expect(k8sApplicator.Apply(ctx, deployUpdate, DisableUpdateAnnotation())).Should(Succeed()) + Expect(len(deployUpdate.Annotations[oam.AnnotationLastAppliedConfig])).Should(Equal(0)) + + deployUpdate = basicTestDeployment() + deployUpdate.Spec.Replicas = &int32_3 + deployUpdate.Spec.Template.Spec.Volumes = []corev1.Volume{{Name: "test"}} + Expect(k8sApplicator.Apply(ctx, deployUpdate)).Should(Succeed()) + resultDeploy = basicTestDeployment() + resultDeploy.Name = deploy.Name + "-no-update" + Expect(rawClient.Get(ctx, deployKey, resultDeploy)).Should(Succeed()) + Expect(*resultDeploy.Spec.Replicas).Should(Equal(int32_3)) + Expect(len(resultDeploy.Spec.Template.Spec.Volumes)).Should(Equal(1)) + Expect(rawClient.Delete(ctx, deployUpdate)).Should(SatisfyAny(Succeed(), &oamutil.NotFoundMatcher{})) }) It("Test multiple appliers", func() { diff --git a/pkg/utils/apply/apply_test.go b/pkg/utils/apply/apply_test.go index f680dd698..32d920340 100644 --- a/pkg/utils/apply/apply_test.go +++ b/pkg/utils/apply/apply_test.go @@ -140,7 +140,7 @@ func TestAPIApplicator(t *testing.T) { creator: creatorFn(func(_ context.Context, _ *applyAction, _ client.Client, _ client.Object, _ ...ApplyOption) (client.Object, error) { return tc.args.existing, tc.args.creatorErr }), - patcher: patcherFn(func(c, m client.Object) (client.Patch, error) { + patcher: patcherFn(func(c, m client.Object, a *applyAction) (client.Patch, error) { return nil, tc.args.patcherErr }), c: tc.c, diff --git a/pkg/utils/apply/patch.go b/pkg/utils/apply/patch.go index 437b20300..5aa1af45c 100644 --- a/pkg/utils/apply/patch.go +++ b/pkg/utils/apply/patch.go @@ -42,7 +42,7 @@ func init() { // threeWayMergePatch creates a patch by computing a three way diff based on // its current state, modified state, and last-applied-state recorded in the // annotation. -func threeWayMergePatch(currentObj, modifiedObj client.Object) (client.Patch, error) { +func threeWayMergePatch(currentObj, modifiedObj client.Object, a *applyAction) (client.Patch, error) { current, err := json.Marshal(currentObj) if err != nil { return nil, err @@ -51,7 +51,7 @@ func threeWayMergePatch(currentObj, modifiedObj client.Object) (client.Patch, er if err != nil { return nil, err } - modified, err := getModifiedConfiguration(modifiedObj, true) + modified, err := getModifiedConfiguration(modifiedObj, a.updateAnnotation) if err != nil { return nil, err } diff --git a/references/cli/install.go b/references/cli/install.go index 4acbe18ee..14b72de2c 100644 --- a/references/cli/install.go +++ b/references/cli/install.go @@ -313,9 +313,9 @@ func waitKubeVelaControllerRunning(kubeClient client.Client, namespace, manifest func upgradeCRDs(ctx context.Context, kubeClient client.Client, chart *chart.Chart) error { crds := helm.GetCRDFromChart(chart) - apply := apply.NewAPIApplicator(kubeClient) + applyHelper := apply.NewAPIApplicator(kubeClient) for _, crd := range crds { - if err := apply.Apply(ctx, crd); err != nil { + if err := applyHelper.Apply(ctx, crd, apply.DisableUpdateAnnotation()); err != nil { return err } }