From 1c8943551560f577e185b2d82fce8bca57c1138c Mon Sep 17 00:00:00 2001 From: Jianbo Sun Date: Fri, 26 Mar 2021 22:20:55 +0800 Subject: [PATCH] fix app upgrade without rollout and rollout plan will create multiple version resources (#1315) * fix app upgrade without rollout and rollout plan will create multiple version resources * add and enhance tests * fix test --- .../common/rollout/rollout_webhook_test.go | 4 +- .../application_controller_test.go | 3 + .../v1alpha2/application/apply.go | 22 ++- .../v1alpha2/application/apply_test.go | 4 +- .../v1alpha2/application/revision_test.go | 2 + .../applicationconfiguration.go | 3 +- .../applicationconfiguration/render.go | 12 +- .../applicationconfiguration/workloads.go | 13 +- .../workloads_test.go | 26 ++- .../applicationrollout_helper.go | 3 +- pkg/oam/labels.go | 4 + test/e2e-test/appcontext_test.go | 5 +- test/e2e-test/application_test.go | 162 ++++++++++++++++++ test/e2e-test/rollout_plan_test.go | 2 +- test/e2e-test/testdata/app/app1.yaml | 13 ++ test/e2e-test/testdata/app/app2.yaml | 17 ++ test/e2e-test/testdata/app/app3.yaml | 17 ++ test/e2e-test/testdata/app/app4.yaml | 17 ++ 18 files changed, 308 insertions(+), 21 deletions(-) create mode 100644 test/e2e-test/application_test.go create mode 100644 test/e2e-test/testdata/app/app1.yaml create mode 100644 test/e2e-test/testdata/app/app2.yaml create mode 100644 test/e2e-test/testdata/app/app3.yaml create mode 100644 test/e2e-test/testdata/app/app4.yaml diff --git a/pkg/controller/common/rollout/rollout_webhook_test.go b/pkg/controller/common/rollout/rollout_webhook_test.go index bb4489884..5ef81f58a 100644 --- a/pkg/controller/common/rollout/rollout_webhook_test.go +++ b/pkg/controller/common/rollout/rollout_webhook_test.go @@ -119,8 +119,8 @@ func TestMakeHTTPRequest(t *testing.T) { } gotReply, gotCode, gotErr := makeHTTPRequest(ctx, "http://"+tt.url, tt.method, tt.payload) if gotCode != tt.want.statusCode { - t.Errorf("\n%s\nr.Reconcile(...): want code `%d`, got code:`%d`\n", testName, tt.want.statusCode, - gotCode) + t.Errorf("\n%s\nr.Reconcile(...): want code `%d`, got code:`%d` got err: %v \n", testName, tt.want.statusCode, + gotCode, gotErr) } if gotCode == -1 { // we don't know exactly what error we should get when the network call failed diff --git a/pkg/controller/core.oam.dev/v1alpha2/application/application_controller_test.go b/pkg/controller/core.oam.dev/v1alpha2/application/application_controller_test.go index 1cdc9ee95..3946e7693 100644 --- a/pkg/controller/core.oam.dev/v1alpha2/application/application_controller_test.go +++ b/pkg/controller/core.oam.dev/v1alpha2/application/application_controller_test.go @@ -548,6 +548,7 @@ var _ = Describe("Test Application Controller", func() { Name: curApp.Status.LatestRevision.Name, }, appRevision)).Should(BeNil()) Expect(appContext.Spec.ApplicationRevisionName).Should(Equal(appRevision.Name)) + Expect(appContext.GetAnnotations()[oam.AnnotationInplaceUpgrade]).Should(Equal("true")) gotTrait := unstructured.Unstructured{} ac, err := util.RawExtension2AppConfig(appRevision.Spec.ApplicationConfiguration) @@ -618,6 +619,7 @@ var _ = Describe("Test Application Controller", func() { Name: curApp.Status.LatestRevision.Name, }, appRevision)).Should(BeNil()) Expect(appContext.Spec.ApplicationRevisionName).Should(Equal(appRevision.Name)) + Expect(appContext.GetAnnotations()[oam.AnnotationInplaceUpgrade]).Should(Equal("true")) gotTrait := unstructured.Unstructured{} ac, err := util.RawExtension2AppConfig(appRevision.Spec.ApplicationConfiguration) @@ -693,6 +695,7 @@ var _ = Describe("Test Application Controller", func() { Name: curApp.Status.LatestRevision.Name, }, appRevision)).Should(BeNil()) Expect(appContext.Spec.ApplicationRevisionName).Should(Equal(appRevision.Name)) + Expect(appContext.GetAnnotations()[oam.AnnotationInplaceUpgrade]).Should(Equal("true")) Expect(json.Unmarshal(ac.Spec.Components[0].Traits[0].Trait.Raw, &gotTrait)).Should(BeNil()) Expect(gotTrait).Should(BeEquivalentTo(expectScalerTrait("myweb5", app.Name))) diff --git a/pkg/controller/core.oam.dev/v1alpha2/application/apply.go b/pkg/controller/core.oam.dev/v1alpha2/application/apply.go index e6a40ca3b..ab57ea83e 100644 --- a/pkg/controller/core.oam.dev/v1alpha2/application/apply.go +++ b/pkg/controller/core.oam.dev/v1alpha2/application/apply.go @@ -19,6 +19,7 @@ package application import ( "context" "fmt" + "strconv" "time" runtimev1alpha1 "github.com/crossplane/crossplane-runtime/apis/core/v1alpha1" @@ -68,6 +69,12 @@ type appHandler struct { app *v1beta1.Application appfile *appfile.Appfile logger logr.Logger + inplace bool +} + +// setInplace will mark if the application should upgrade the workload within the same instance(name never changed) +func (h *appHandler) setInplace(isInplace bool) { + h.inplace = isInplace } func (h *appHandler) handleErr(err error) (ctrl.Result, error) { @@ -135,10 +142,14 @@ func (h *appHandler) apply(ctx context.Context, ac *v1alpha2.ApplicationConfigur } } - // we only need to create appContext here if there is no rollout controller to take care of new versions + // the rollout will create AppContext which will launch the real K8s resources. + // Otherwise, we should create/update the appContext here when there if no rollout controller to take care of new versions + // In this case, the workload should update with the annotation `app.oam.dev/inplace-upgrade=true` if _, exist := h.app.GetAnnotations()[oam.AnnotationAppRollout]; !exist && h.app.Spec.RolloutPlan == nil { + h.setInplace(true) return h.createOrUpdateAppContext(ctx, owners) } + h.setInplace(false) return nil } @@ -307,7 +318,14 @@ func (h *appHandler) createOrUpdateAppContext(ctx context.Context, owners []meta } appLabel[oam.LabelAppRevisionHash] = h.app.Status.LatestRevision.RevisionHash appContext.SetLabels(appLabel) - appContext.SetAnnotations(h.app.GetAnnotations()) + + appAnnotation := h.app.GetAnnotations() + if appAnnotation == nil { + appAnnotation = make(map[string]string) + } + appAnnotation[oam.AnnotationInplaceUpgrade] = strconv.FormatBool(h.inplace) + appContext.SetAnnotations(appAnnotation) + key := ctypes.NamespacedName{Name: appContext.Name, Namespace: appContext.Namespace} if err := h.r.Get(ctx, key, &curAppContext); err != nil { diff --git a/pkg/controller/core.oam.dev/v1alpha2/application/apply_test.go b/pkg/controller/core.oam.dev/v1alpha2/application/apply_test.go index cd7b6299e..f1b04e859 100644 --- a/pkg/controller/core.oam.dev/v1alpha2/application/apply_test.go +++ b/pkg/controller/core.oam.dev/v1alpha2/application/apply_test.go @@ -18,9 +18,9 @@ package application import ( "context" - "math/rand" "strconv" "strings" + "time" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -43,7 +43,7 @@ var _ = Describe("Test Application apply", func() { BeforeEach(func() { ctx := context.TODO() - namespaceName = "apply-test-" + strconv.Itoa(rand.Intn(1000)) + namespaceName = "apply-test-" + strconv.Itoa(time.Now().Second()) + "-" + strconv.Itoa(time.Now().Nanosecond()) ns = corev1.Namespace{ ObjectMeta: metav1.ObjectMeta{ Name: namespaceName, diff --git a/pkg/controller/core.oam.dev/v1alpha2/application/revision_test.go b/pkg/controller/core.oam.dev/v1alpha2/application/revision_test.go index a1800f488..c5fc8d4a3 100644 --- a/pkg/controller/core.oam.dev/v1alpha2/application/revision_test.go +++ b/pkg/controller/core.oam.dev/v1alpha2/application/revision_test.go @@ -266,6 +266,8 @@ var _ = Describe("test generate revision ", func() { Expect(curAC.GetLabels()[oam.LabelAppRevisionHash]).Should(Equal(appHash1)) Expect(curAC.Spec.ApplicationRevisionName).Should(Equal(curApp.Status.LatestRevision.Name)) Expect(curAC.GetAnnotations()[annoKey1]).ShouldNot(BeEmpty()) + Expect(curAC.GetAnnotations()[oam.AnnotationInplaceUpgrade]).Should(Equal("true")) + Expect(metav1.GetControllerOf(curAC)).ShouldNot(BeNil()) Expect(metav1.GetControllerOf(curAC).Kind).Should(Equal(v1alpha2.ApplicationKind)) By("Apply the application again without any spec change") diff --git a/pkg/controller/core.oam.dev/v1alpha2/applicationconfiguration/applicationconfiguration.go b/pkg/controller/core.oam.dev/v1alpha2/applicationconfiguration/applicationconfiguration.go index 9fcdaa535..1987c42b9 100644 --- a/pkg/controller/core.oam.dev/v1alpha2/applicationconfiguration/applicationconfiguration.go +++ b/pkg/controller/core.oam.dev/v1alpha2/applicationconfiguration/applicationconfiguration.go @@ -23,8 +23,6 @@ import ( "strings" "time" - types2 "github.com/oam-dev/kubevela/apis/types" - "github.com/crossplane/crossplane-runtime/apis/core/v1alpha1" "github.com/crossplane/crossplane-runtime/pkg/event" "github.com/crossplane/crossplane-runtime/pkg/fieldpath" @@ -43,6 +41,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/reconcile" "github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha2" + types2 "github.com/oam-dev/kubevela/apis/types" core "github.com/oam-dev/kubevela/pkg/controller/core.oam.dev" "github.com/oam-dev/kubevela/pkg/oam" "github.com/oam-dev/kubevela/pkg/oam/discoverymapper" diff --git a/pkg/controller/core.oam.dev/v1alpha2/applicationconfiguration/render.go b/pkg/controller/core.oam.dev/v1alpha2/applicationconfiguration/render.go index 6d9ce7c4d..6e569dfe4 100644 --- a/pkg/controller/core.oam.dev/v1alpha2/applicationconfiguration/render.go +++ b/pkg/controller/core.oam.dev/v1alpha2/applicationconfiguration/render.go @@ -194,11 +194,14 @@ func (r *components) renderComponent(ctx context.Context, acc v1alpha2.Applicati oam.AnnotationAppGeneration: strconv.Itoa(int(ac.Generation)), } util.AddAnnotations(w, compInfoAnnotations) - + var inplaceUpgrade string + if acAnnotations := ac.GetAnnotations(); acAnnotations != nil { + inplaceUpgrade = acAnnotations[oam.AnnotationInplaceUpgrade] + } // pass through labels and annotation from app-config to workload util.PassLabelAndAnnotation(ac, w) // don't pass the following annotation as those are for appConfig only - util.RemoveAnnotations(w, []string{oam.AnnotationAppRollout, oam.AnnotationRollingComponent}) + util.RemoveAnnotations(w, []string{oam.AnnotationAppRollout, oam.AnnotationRollingComponent, oam.AnnotationInplaceUpgrade}) ref := metav1.NewControllerRef(ac, v1alpha2.ApplicationConfigurationGroupVersionKind) w.SetNamespace(ac.GetNamespace()) @@ -216,7 +219,7 @@ func (r *components) renderComponent(ctx context.Context, acc v1alpha2.Applicati // pass through labels and annotation from app-config to trait util.PassLabelAndAnnotation(ac, t) - util.RemoveAnnotations(t, []string{oam.AnnotationAppRollout, oam.AnnotationRollingComponent}) + util.RemoveAnnotations(t, []string{oam.AnnotationAppRollout, oam.AnnotationRollingComponent, oam.AnnotationInplaceUpgrade}) traits = append(traits, &Trait{Object: *t, Definition: *traitDef}) traitDefs = append(traitDefs, *traitDef) } @@ -250,7 +253,8 @@ func (r *components) renderComponent(ctx context.Context, acc v1alpha2.Applicati if err != nil { return nil, err } - SetAppWorkloadInstanceName(acc.ComponentName, w, revision) + // Pass inpalce upgrade into it + SetAppWorkloadInstanceName(acc.ComponentName, w, revision, inplaceUpgrade) if isComponentRolling && needRolloutTemplate { // we have a special logic to emit the workload as a template so that the rollout // controller can take over. diff --git a/pkg/controller/core.oam.dev/v1alpha2/applicationconfiguration/workloads.go b/pkg/controller/core.oam.dev/v1alpha2/applicationconfiguration/workloads.go index e7f09c5d6..ad4491f83 100644 --- a/pkg/controller/core.oam.dev/v1alpha2/applicationconfiguration/workloads.go +++ b/pkg/controller/core.oam.dev/v1alpha2/applicationconfiguration/workloads.go @@ -19,6 +19,7 @@ package applicationconfiguration import ( "fmt" "reflect" + "strconv" "github.com/crossplane/crossplane-runtime/pkg/fieldpath" "github.com/openkruise/kruise-api/apps/v1alpha1" @@ -27,6 +28,7 @@ import ( "k8s.io/klog/v2" "github.com/oam-dev/kubevela/pkg/controller/utils" + "github.com/oam-dev/kubevela/pkg/oam" ) const ( @@ -38,9 +40,14 @@ const ( // SetAppWorkloadInstanceName sets the name of the workload instance depends on the component revision // and the workload kind -func SetAppWorkloadInstanceName(componentName string, w *unstructured.Unstructured, revision int) { - // TODO: we can get the workloadDefinition name from w.GetLabels()["oam.WorkloadTypeLabel"] - // and use a special field like "use-inplace-upgrade" in the definition to allow configurable behavior +func SetAppWorkloadInstanceName(componentName string, w *unstructured.Unstructured, revision int, inplaceUpgrade string) { + + if inplaceUpgrade == strconv.FormatBool(true) { + klog.InfoS("we reuse the component name for resources that support in-place upgrade", + "GVK", w.GroupVersionKind(), "instance name", componentName, oam.AnnotationInplaceUpgrade, true) + w.SetName(componentName) + return + } // we hard code the behavior depends on the workload group/kind for now. The only in-place upgradable resources // we support is cloneset/statefulset for now. We can easily add more later. diff --git a/pkg/controller/core.oam.dev/v1alpha2/applicationconfiguration/workloads_test.go b/pkg/controller/core.oam.dev/v1alpha2/applicationconfiguration/workloads_test.go index 313016405..1b4ff232d 100644 --- a/pkg/controller/core.oam.dev/v1alpha2/applicationconfiguration/workloads_test.go +++ b/pkg/controller/core.oam.dev/v1alpha2/applicationconfiguration/workloads_test.go @@ -17,6 +17,7 @@ limitations under the License. package applicationconfiguration import ( + "strconv" "strings" "testing" @@ -35,6 +36,7 @@ func TestSetAppWorkloadInstanceName(t *testing.T) { w *unstructured.Unstructured revision int expName string + inplace string reason string }{ "two resources case": { @@ -80,10 +82,32 @@ func TestSetAppWorkloadInstanceName(t *testing.T) { expName: "mysql-v2", reason: "we compare not only the kind but also the group name", }, + "use inplaceUpgrade = true": { + compName: "mysql", + revision: 2, + w: &unstructured.Unstructured{Object: map[string]interface{}{ + "apiVersion": "oam.dev/v1alpha1", + "kind": "CloneSet", + }}, + expName: "mysql", + inplace: strconv.FormatBool(true), + reason: "we compare not only the kind but also the group name", + }, + "use inplaceUpgrade = other value won't work": { + compName: "mysql", + revision: 2, + w: &unstructured.Unstructured{Object: map[string]interface{}{ + "apiVersion": "oam.dev/v1alpha1", + "kind": "CloneSet", + }}, + expName: "mysql-v2", + inplace: "t", + reason: "we compare not only the kind but also the group name", + }, } for name, ti := range tests { t.Run(name, func(t *testing.T) { - SetAppWorkloadInstanceName(ti.compName, ti.w, ti.revision) + SetAppWorkloadInstanceName(ti.compName, ti.w, ti.revision, ti.inplace) assert.Equal(t, ti.expName, ti.w.GetName(), ti.reason) }) } diff --git a/pkg/controller/core.oam.dev/v1alpha2/applicationrollout/applicationrollout_helper.go b/pkg/controller/core.oam.dev/v1alpha2/applicationrollout/applicationrollout_helper.go index b80e5702c..1a29c9aaa 100644 --- a/pkg/controller/core.oam.dev/v1alpha2/applicationrollout/applicationrollout_helper.go +++ b/pkg/controller/core.oam.dev/v1alpha2/applicationrollout/applicationrollout_helper.go @@ -215,7 +215,8 @@ func (r *Reconciler) fetchWorkload(ctx context.Context, componentName string, return nil, errors.Wrap(err, fmt.Sprintf("failed to get component given revision %s", targetAcc.RevisionName)) } // reuse the same appConfig controller logic that determines the workload name given an ACC - applicationconfiguration.SetAppWorkloadInstanceName(componentName, w, revision) + // inplaceUpgrade not used in rollout now + applicationconfiguration.SetAppWorkloadInstanceName(componentName, w, revision, "") // get the real workload object from api-server given GVK and name workload, err := oamutil.GetObjectGivenGVKAndName(ctx, r, w.GroupVersionKind(), targetApp.GetNamespace(), w.GetName()) if err != nil { diff --git a/pkg/oam/labels.go b/pkg/oam/labels.go index 3715bad40..bf3f6d739 100644 --- a/pkg/oam/labels.go +++ b/pkg/oam/labels.go @@ -59,6 +59,10 @@ const ( // the application controller should treat it differently AnnotationAppRollout = "app.oam.dev/rollout-template" + // AnnotationInplaceUpgrade indicates the workload should upgrade with the the same name + // the name of the workload instance should not changing along with the revision + AnnotationInplaceUpgrade = "app.oam.dev/inplace-upgrade" + // AnnotationRollingComponent indicates that the component is rolling out // this is to enable any concerned controllers to handle the first component apply logic differently // the value of the annotation is a list of component name of all the new component diff --git a/test/e2e-test/appcontext_test.go b/test/e2e-test/appcontext_test.go index 2a2f04f06..dd68ae028 100644 --- a/test/e2e-test/appcontext_test.go +++ b/test/e2e-test/appcontext_test.go @@ -21,8 +21,6 @@ import ( "fmt" "time" - "github.com/oam-dev/kubevela/pkg/controller/core.oam.dev/v1alpha2/application" - . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -33,6 +31,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha2" + "github.com/oam-dev/kubevela/pkg/controller/core.oam.dev/v1alpha2/application" "github.com/oam-dev/kubevela/pkg/oam/util" ) @@ -201,7 +200,7 @@ var _ = Describe("Test applicationContext reconcile", func() { time.Sleep(15 * time.Second) }) - It("Test appContext reconcil logic ", func() { + It("Test appContext reconcile logic ", func() { By("Test AppRevision1 only have 1 workload on trait") Expect(k8sClient.Create(ctx, appContext)).Should(Succeed()) Eventually(func() error { diff --git a/test/e2e-test/application_test.go b/test/e2e-test/application_test.go new file mode 100644 index 000000000..23bb9ec73 --- /dev/null +++ b/test/e2e-test/application_test.go @@ -0,0 +1,162 @@ +/* +Copyright 2021 The KubeVela Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package controllers_test + +import ( + "context" + "fmt" + "math/rand" + "strconv" + "time" + + v1 "k8s.io/api/apps/v1" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sigs.k8s.io/controller-runtime/pkg/client" + + oamcomm "github.com/oam-dev/kubevela/apis/core.oam.dev/common" + "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" + "github.com/oam-dev/kubevela/pkg/oam/util" + "github.com/oam-dev/kubevela/pkg/utils/common" +) + +var _ = Describe("Application Normal tests", func() { + ctx := context.Background() + var namespaceName string + var ns corev1.Namespace + var app v1beta1.Application + + createNamespace := func() { + ns = corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: namespaceName, + }, + } + // delete the namespaceName with all its resources + Eventually( + func() error { + return k8sClient.Delete(ctx, &ns, client.PropagationPolicy(metav1.DeletePropagationForeground)) + }, + time.Second*120, time.Millisecond*500).Should(SatisfyAny(BeNil(), &util.NotFoundMatcher{})) + By("make sure all the resources are removed") + objectKey := client.ObjectKey{ + Name: namespaceName, + } + res := &corev1.Namespace{} + Eventually( + func() error { + return k8sClient.Get(ctx, objectKey, res) + }, + time.Second*120, time.Millisecond*500).Should(&util.NotFoundMatcher{}) + Eventually( + func() error { + return k8sClient.Create(ctx, &ns) + }, + time.Second*3, time.Millisecond*300).Should(SatisfyAny(BeNil(), &util.AlreadyExistMatcher{})) + } + + applyApp := func(source string) { + By("Apply an application") + var newApp v1beta1.Application + Expect(common.ReadYamlToObject("testdata/app/"+source, &newApp)).Should(BeNil()) + newApp.Namespace = namespaceName + Expect(k8sClient.Create(ctx, &newApp)).Should(Succeed()) + + By("Get Application latest status") + Eventually( + func() *oamcomm.Revision { + k8sClient.Get(ctx, client.ObjectKey{Namespace: namespaceName, Name: newApp.Name}, &app) + if app.Status.LatestRevision != nil { + return app.Status.LatestRevision + } + return nil + }, + time.Second*30, time.Millisecond*500).ShouldNot(BeNil()) + } + + updateApp := func(target string) { + By("Update the application to target spec during rolling") + var targetApp v1beta1.Application + Expect(common.ReadYamlToObject("testdata/app/"+target, &targetApp)).Should(BeNil()) + + Eventually( + func() error { + k8sClient.Get(ctx, client.ObjectKey{Namespace: namespaceName, Name: app.Name}, &app) + app.Spec = targetApp.Spec + return k8sClient.Update(ctx, &app) + }, time.Second*5, time.Millisecond*500).Should(Succeed()) + } + + verifyWorkloadRunningExpected := func(workloadName string, replicas int32, image string) { + var workload v1.Deployment + By("Verify AppConfig is inactive") + Eventually( + func() error { + if err := k8sClient.Get(ctx, client.ObjectKey{Namespace: namespaceName, Name: workloadName}, &workload); err != nil { + return err + } + if workload.Status.ReadyReplicas != replicas { + return fmt.Errorf("expect replicas %v != real %v", replicas, workload.Status.ReadyReplicas) + } + if workload.Spec.Template.Spec.Containers[0].Image != image { + return fmt.Errorf("expect replicas %v != real %v", image, workload.Spec.Template.Spec.Containers[0].Image) + } + return nil + }, + time.Second*30, time.Millisecond*500).Should(BeNil()) + } + + BeforeEach(func() { + By("Start to run a test, clean up previous resources") + namespaceName = "app-normal-e2e-test" + "-" + strconv.FormatInt(rand.Int63(), 16) + createNamespace() + }) + + AfterEach(func() { + By("Clean up resources after a test") + k8sClient.Delete(ctx, &app) + By(fmt.Sprintf("Delete the entire namespaceName %s", ns.Name)) + // delete the namespaceName with all its resources + Expect(k8sClient.Delete(ctx, &ns, client.PropagationPolicy(metav1.DeletePropagationBackground))).Should(BeNil()) + }) + + It("Test app created normally", func() { + applyApp("app1.yaml") + By("Apply the application rollout go directly to the target") + verifyWorkloadRunningExpected("myweb", 1, "stefanprodan/podinfo:4.0.3") + + By("Update app with trait") + updateApp("app2.yaml") + By("Apply the application rollout go directly to the target") + verifyWorkloadRunningExpected("myweb", 2, "stefanprodan/podinfo:4.0.3") + + By("Update app with trait updated") + updateApp("app3.yaml") + By("Apply the application rollout go directly to the target") + verifyWorkloadRunningExpected("myweb", 3, "stefanprodan/podinfo:4.0.3") + + By("Update app with trait and workload image updated") + updateApp("app4.yaml") + By("Apply the application rollout go directly to the target") + verifyWorkloadRunningExpected("myweb", 1, "stefanprodan/podinfo:5.0.2") + }) + +}) diff --git a/test/e2e-test/rollout_plan_test.go b/test/e2e-test/rollout_plan_test.go index 00f564a12..7b2d929c0 100644 --- a/test/e2e-test/rollout_plan_test.go +++ b/test/e2e-test/rollout_plan_test.go @@ -42,7 +42,7 @@ import ( "github.com/oam-dev/kubevela/pkg/utils/common" ) -var _ = FDescribe("Cloneset based rollout tests", func() { +var _ = Describe("Cloneset based rollout tests", func() { ctx := context.Background() var namespaceName, appRolloutName string var ns corev1.Namespace diff --git a/test/e2e-test/testdata/app/app1.yaml b/test/e2e-test/testdata/app/app1.yaml new file mode 100644 index 000000000..194ba53c0 --- /dev/null +++ b/test/e2e-test/testdata/app/app1.yaml @@ -0,0 +1,13 @@ +apiVersion: core.oam.dev/v1beta1 +kind: Application +metadata: + name: app-e2e +spec: + components: + - name: myweb + type: worker + properties: + image: "stefanprodan/podinfo:4.0.3" + cmd: + - ./podinfo + - stress-cpu=1 \ No newline at end of file diff --git a/test/e2e-test/testdata/app/app2.yaml b/test/e2e-test/testdata/app/app2.yaml new file mode 100644 index 000000000..008560d35 --- /dev/null +++ b/test/e2e-test/testdata/app/app2.yaml @@ -0,0 +1,17 @@ +apiVersion: core.oam.dev/v1beta1 +kind: Application +metadata: + name: app-e2e +spec: + components: + - name: myweb + type: worker + properties: + image: "stefanprodan/podinfo:4.0.3" + cmd: + - ./podinfo + - stress-cpu=1 + traits: + - type: scaler + properties: + replicas: 2 \ No newline at end of file diff --git a/test/e2e-test/testdata/app/app3.yaml b/test/e2e-test/testdata/app/app3.yaml new file mode 100644 index 000000000..263f94a5a --- /dev/null +++ b/test/e2e-test/testdata/app/app3.yaml @@ -0,0 +1,17 @@ +apiVersion: core.oam.dev/v1beta1 +kind: Application +metadata: + name: app-e2e +spec: + components: + - name: myweb + type: worker + properties: + image: "stefanprodan/podinfo:4.0.3" + cmd: + - ./podinfo + - stress-cpu=1 + traits: + - type: scaler + properties: + replicas: 3 \ No newline at end of file diff --git a/test/e2e-test/testdata/app/app4.yaml b/test/e2e-test/testdata/app/app4.yaml new file mode 100644 index 000000000..12765c5ef --- /dev/null +++ b/test/e2e-test/testdata/app/app4.yaml @@ -0,0 +1,17 @@ +apiVersion: core.oam.dev/v1beta1 +kind: Application +metadata: + name: app-e2e +spec: + components: + - name: myweb + type: worker + properties: + image: "stefanprodan/podinfo:5.0.2" + cmd: + - ./podinfo + - stress-cpu=1 + traits: + - type: scaler + properties: + replicas: 1 \ No newline at end of file