mirror of
https://github.com/kubevela/kubevela.git
synced 2026-05-19 07:46:51 +00:00
remove appContext from app/appRollout controller (#1774)
* refine assemble and dispatch Signed-off-by: roy wang <seiwy2010@gmail.com> * remove app context in app controller modify clean up app revision remove old resource tracker related logic fix unit tests Signed-off-by: roy wang <seiwy2010@gmail.com> * fix e2e-test - get rid of appCtx in test cases - fix test cases according other logic changes in app controller remove whole appcontext_test.go file disable rollout related e2e test provisionally disable resource tracker related e2e test provisionally Signed-off-by: roy wang <seiwy2010@gmail.com> * add finalizer logic for app controller Signed-off-by: roywang <seiwy2010@gmail.com> * add new apply option MustBeControllableByAny make dispatch idempotent Signed-off-by: roywang <seiwy2010@gmail.com> * refactor rollout * fix rollout finalize succeed Signed-off-by: roywang <seiwy2010@gmail.com> * add update trait and gc test fix lint * fix flaky e2e test Signed-off-by: roywang <seiwy2010@gmail.com> * fix comment * fix comments and add sourceRevision dispatch delete useless Signed-off-by: Yue Wang <seiwy2010@gmail.com> * fix app finalizer backward compatible Signed-off-by: roywang <seiwy2010@gmail.com> * fix backward compatability for deprecation of appContext add unit test for apply option add e2e test Signed-off-by: Yue Wang <seiwy2010@gmail.com> * fix app controller unit test Signed-off-by: Yue Wang <seiwy2010@gmail.com> * refine app controller apply logic Signed-off-by: Yue Wang <seiwy2010@gmail.com> * fix e2e test of resource tracker fix e2e test of rollout plan fix flaky e2e tests Signed-off-by: Yue Wang <seiwy2010@gmail.com> * refine comments and remove useless codes Signed-off-by: Yue Wang <seiwy2010@gmail.com> * disable appCtx controller add Component handler into app controller Signed-off-by: Yue Wang <seiwy2010@gmail.com> Co-authored-by: wangyike <wangyike.wyk@alibaba-inc.com>
This commit is contained in:
@@ -33,9 +33,7 @@ import (
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
apicommon "github.com/oam-dev/kubevela/apis/core.oam.dev/common"
|
||||
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha2"
|
||||
"github.com/oam-dev/kubevela/apis/standard.oam.dev/v1alpha1"
|
||||
"github.com/oam-dev/kubevela/apis/types"
|
||||
"github.com/oam-dev/kubevela/pkg/controller/utils"
|
||||
|
||||
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
|
||||
@@ -137,8 +135,7 @@ var _ = Describe("Cloneset based app embed rollout tests", func() {
|
||||
Expect(k8sClient.Delete(ctx, &ns, client.PropagationPolicy(metav1.DeletePropagationBackground))).Should(BeNil())
|
||||
})
|
||||
|
||||
verifyRolloutSucceeded := func(targetAppContextName string, cpu string) {
|
||||
By(fmt.Sprintf("Wait for the rollout `%s` to succeed", targetAppContextName))
|
||||
verifyRolloutSucceeded := func(targetAppRevisionName string, cpu string) {
|
||||
Eventually(
|
||||
func() error {
|
||||
app = v1beta1.Application{}
|
||||
@@ -155,23 +152,6 @@ var _ = Describe("Cloneset based app embed rollout tests", func() {
|
||||
Expect(app.Status.Rollout.UpgradedReplicas).Should(BeEquivalentTo(app.Status.Rollout.RolloutTargetSize))
|
||||
clonesetName := app.Spec.Components[0].Name
|
||||
Expect(app.Status.Phase).Should(BeEquivalentTo(apicommon.ApplicationRunning))
|
||||
By("Verify AppContext rolling status")
|
||||
appContext := &v1alpha2.ApplicationContext{}
|
||||
Eventually(
|
||||
func() error {
|
||||
if err := k8sClient.Get(ctx, client.ObjectKey{Namespace: namespaceName, Name: targetAppContextName}, appContext); err != nil {
|
||||
return err
|
||||
}
|
||||
if appContext.Status.RollingStatus != types.RollingCompleted {
|
||||
return fmt.Errorf("appcontext %s rolling state mismatch actualy %s", targetAppContextName, appContext.Status.RollingStatus)
|
||||
}
|
||||
owner := metav1.GetControllerOf(appContext)
|
||||
if owner.Name != appName && owner.Kind != app.Kind && owner.APIVersion != app.APIVersion {
|
||||
return fmt.Errorf("appcontext owner mismatch")
|
||||
}
|
||||
return nil
|
||||
},
|
||||
time.Second*120, time.Microsecond*300).Should(BeNil())
|
||||
|
||||
By("Verify cloneset status")
|
||||
var clonesetOwner *metav1.OwnerReference
|
||||
@@ -181,16 +161,22 @@ var _ = Describe("Cloneset based app embed rollout tests", func() {
|
||||
return err
|
||||
}
|
||||
clonesetOwner = metav1.GetControllerOf(&kc)
|
||||
if clonesetOwner.Kind != v1alpha2.ApplicationContextKind {
|
||||
return fmt.Errorf("cloneset owner mismatch actually %s", v1alpha2.ApplicationContextKind)
|
||||
if clonesetOwner == nil {
|
||||
return fmt.Errorf("cloneset don't have any controller owner")
|
||||
}
|
||||
if clonesetOwner.Kind != v1beta1.ResourceTrackerKind {
|
||||
return fmt.Errorf("cloneset owner mismatch wants %s actually %s", v1beta1.ResourceTrackerKind, clonesetOwner.Kind)
|
||||
}
|
||||
if kc.Status.UpdatedReplicas != *kc.Spec.Replicas {
|
||||
return fmt.Errorf("upgraded pod number error")
|
||||
}
|
||||
resourceTrackerName := fmt.Sprintf("%s-%s", targetAppRevisionName, app.Namespace)
|
||||
if clonesetOwner.Name != resourceTrackerName {
|
||||
return fmt.Errorf("resourceTracker haven't take back controller owner")
|
||||
}
|
||||
return nil
|
||||
},
|
||||
time.Second*30, time.Millisecond*500).Should(BeNil())
|
||||
Expect(clonesetOwner.Name).Should(BeEquivalentTo(targetAppContextName))
|
||||
By("Verify pod status")
|
||||
Eventually(func() error {
|
||||
podList := corev1.PodList{}
|
||||
|
||||
@@ -59,11 +59,11 @@ var _ = Describe("Test application cross namespace resource", func() {
|
||||
Eventually(func() error {
|
||||
ns := new(corev1.Namespace)
|
||||
return k8sClient.Get(ctx, types.NamespacedName{Name: namespace}, ns)
|
||||
}, time.Second*60, time.Microsecond*300).Should(BeNil())
|
||||
}, time.Second*5, time.Millisecond*300).Should(BeNil())
|
||||
Eventually(func() error {
|
||||
ns := new(corev1.Namespace)
|
||||
return k8sClient.Get(ctx, types.NamespacedName{Name: crossNamespace}, ns)
|
||||
}, time.Second*60, time.Microsecond*300).Should(BeNil())
|
||||
}, time.Second*5, time.Millisecond*300).Should(BeNil())
|
||||
})
|
||||
|
||||
AfterEach(func() {
|
||||
@@ -253,7 +253,7 @@ var _ = Describe("Test application cross namespace resource", func() {
|
||||
}, 20*time.Second, 2*time.Second).Should(SatisfyAll(&util.NotFoundMatcher{}))
|
||||
})
|
||||
|
||||
It("Test application have cross-namespace workload", func() {
|
||||
It("Test application have cross-namespace workload", func() {
|
||||
// install component definition
|
||||
crossCdJson, _ := yaml.YAMLToJSON([]byte(fmt.Sprintf(crossCompDefYaml, namespace, crossNamespace)))
|
||||
ccd := new(v1beta1.ComponentDefinition)
|
||||
@@ -271,7 +271,7 @@ var _ = Describe("Test application cross namespace resource", func() {
|
||||
},
|
||||
Spec: v1beta1.ApplicationSpec{
|
||||
Components: []v1beta1.ApplicationComponent{
|
||||
v1beta1.ApplicationComponent{
|
||||
{
|
||||
Name: componentName,
|
||||
Type: "cross-worker",
|
||||
Properties: runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox"}`)},
|
||||
@@ -287,27 +287,20 @@ var _ = Describe("Test application cross namespace resource", func() {
|
||||
if err := k8sClient.Get(ctx, types.NamespacedName{Namespace: namespace, Name: appName}, app); err != nil {
|
||||
return fmt.Errorf("app not found %v", err)
|
||||
}
|
||||
if err := k8sClient.Get(ctx, generateResourceTrackerKey(app.Namespace, app.Name), resourceTracker); err != nil {
|
||||
if err := k8sClient.Get(ctx, generateResourceTrackerKey(app.Namespace, app.Name, 1), resourceTracker); err != nil {
|
||||
return err
|
||||
}
|
||||
if app.Status.Phase != common.ApplicationRunning {
|
||||
return fmt.Errorf("application status is not running")
|
||||
}
|
||||
if app.Status.ResourceTracker == nil || app.Status.ResourceTracker.UID != resourceTracker.UID {
|
||||
return fmt.Errorf("appication status error ")
|
||||
}
|
||||
return nil
|
||||
}, time.Second*300, time.Microsecond*300).Should(BeNil())
|
||||
}, time.Second*5, time.Millisecond*300).Should(BeNil())
|
||||
By("check resource is generated correctly")
|
||||
Expect(k8sClient.Get(ctx, types.NamespacedName{Namespace: namespace, Name: appName}, app)).Should(BeNil())
|
||||
var workload appsv1.Deployment
|
||||
Eventually(func() error {
|
||||
appContext := &v1alpha2.ApplicationContext{}
|
||||
if err := k8sClient.Get(ctx, types.NamespacedName{Namespace: namespace, Name: appName}, appContext); err != nil {
|
||||
return fmt.Errorf("cannot generate AppContext %v", err)
|
||||
}
|
||||
checkRt := new(v1beta1.ResourceTracker)
|
||||
if err := k8sClient.Get(ctx, generateResourceTrackerKey(app.Namespace, app.Name), checkRt); err != nil {
|
||||
if err := k8sClient.Get(ctx, generateResourceTrackerKey(app.Namespace, app.Name, 1), checkRt); err != nil {
|
||||
return err
|
||||
}
|
||||
component := &v1alpha2.Component{}
|
||||
@@ -339,14 +332,13 @@ var _ = Describe("Test application cross namespace resource", func() {
|
||||
return fmt.Errorf("resourceTracker status recode trackedResource name mismatch recorded %s, actually %s", checkRt.Status.TrackedResources[0].Name, workload.Name)
|
||||
}
|
||||
return nil
|
||||
}, time.Second*50, time.Microsecond*300).Should(BeNil())
|
||||
}, time.Second*5, time.Millisecond*300).Should(BeNil())
|
||||
|
||||
By("deleting application will remove resourceTracker and related workload will be removed")
|
||||
time.Sleep(3 * time.Second) // wait informer cache to be synced
|
||||
Expect(k8sClient.Get(ctx, types.NamespacedName{Namespace: namespace, Name: appName}, app)).Should(BeNil())
|
||||
Expect(k8sClient.Delete(ctx, app)).Should(BeNil())
|
||||
Eventually(func() error {
|
||||
err := k8sClient.Get(ctx, generateResourceTrackerKey(app.Namespace, app.Name), resourceTracker)
|
||||
err := k8sClient.Get(ctx, generateResourceTrackerKey(app.Namespace, app.Name, 1), resourceTracker)
|
||||
if err == nil {
|
||||
return fmt.Errorf("resourceTracker still exist")
|
||||
}
|
||||
@@ -361,7 +353,7 @@ var _ = Describe("Test application cross namespace resource", func() {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}, time.Second*30, time.Microsecond*300).Should(BeNil())
|
||||
}, time.Second*5, time.Millisecond*300).Should(BeNil())
|
||||
})
|
||||
|
||||
It("Test update application by add a cross namespace trait resource", func() {
|
||||
@@ -389,7 +381,7 @@ var _ = Describe("Test application cross namespace resource", func() {
|
||||
},
|
||||
Spec: v1beta1.ApplicationSpec{
|
||||
Components: []v1beta1.ApplicationComponent{
|
||||
v1beta1.ApplicationComponent{
|
||||
{
|
||||
Name: componentName,
|
||||
Type: "normal-worker",
|
||||
Properties: runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox"}`)},
|
||||
@@ -421,18 +413,14 @@ var _ = Describe("Test application cross namespace resource", func() {
|
||||
return fmt.Errorf("error workload number %v", err)
|
||||
}
|
||||
workload := depolys.Items[0]
|
||||
if len(workload.OwnerReferences) != 1 || workload.OwnerReferences[0].Kind != v1alpha2.ApplicationContextKind {
|
||||
if len(workload.OwnerReferences) != 1 || workload.OwnerReferences[0].Kind != v1beta1.ResourceTrackerKind {
|
||||
return fmt.Errorf("workload owneRefernece err")
|
||||
}
|
||||
err = k8sClient.Get(ctx, generateResourceTrackerKey(app.Namespace, app.Name), resourceTracker)
|
||||
if err == nil {
|
||||
return fmt.Errorf("resourceTracker should not be created")
|
||||
}
|
||||
if !apierrors.IsNotFound(err) {
|
||||
if err = k8sClient.Get(ctx, generateResourceTrackerKey(app.Namespace, app.Name, 1), resourceTracker); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}, time.Second*60, time.Microsecond*300).Should(BeNil())
|
||||
}, time.Second*5, time.Millisecond*500).Should(BeNil())
|
||||
|
||||
Eventually(func() error {
|
||||
err := k8sClient.Get(ctx, types.NamespacedName{Namespace: namespace, Name: appName}, app)
|
||||
@@ -440,13 +428,13 @@ var _ = Describe("Test application cross namespace resource", func() {
|
||||
return err
|
||||
}
|
||||
app.Spec.Components[0].Traits = []v1beta1.ApplicationTrait{
|
||||
v1beta1.ApplicationTrait{
|
||||
{
|
||||
Type: "cross-scaler",
|
||||
Properties: runtime.RawExtension{Raw: []byte(`{"replicas": 1}`)},
|
||||
},
|
||||
}
|
||||
return k8sClient.Update(ctx, app)
|
||||
}, time.Second*30, time.Microsecond*300).Should(BeNil())
|
||||
}, time.Second*5, time.Millisecond*300).Should(BeNil())
|
||||
|
||||
By("add a cross namespace trait, check resourceTracker and trait status")
|
||||
Eventually(func() error {
|
||||
@@ -457,7 +445,7 @@ var _ = Describe("Test application cross namespace resource", func() {
|
||||
if app.Status.Phase != common.ApplicationRunning {
|
||||
return fmt.Errorf("application status not running")
|
||||
}
|
||||
err := k8sClient.Get(ctx, generateResourceTrackerKey(app.Namespace, app.Name), resourceTracker)
|
||||
err := k8sClient.Get(ctx, generateResourceTrackerKey(app.Namespace, app.Name, 2), resourceTracker)
|
||||
if err != nil {
|
||||
return fmt.Errorf("resourceTracker not generated %v", err)
|
||||
}
|
||||
@@ -476,14 +464,11 @@ var _ = Describe("Test application cross namespace resource", func() {
|
||||
if len(trait.OwnerReferences) != 1 || trait.OwnerReferences[0].UID != resourceTracker.UID {
|
||||
return fmt.Errorf("trait owner reference missmatch")
|
||||
}
|
||||
if len(resourceTracker.Status.TrackedResources) != 1 {
|
||||
return fmt.Errorf("resourceTracker status recode trackedResource length missmatch")
|
||||
}
|
||||
if resourceTracker.Status.TrackedResources[0].Name != trait.Name {
|
||||
return fmt.Errorf("resourceTracker status recode trackedResource name mismatch recorded %s, actually %s", resourceTracker.Status.TrackedResources[0].Name, trait.Name)
|
||||
if len(resourceTracker.Status.TrackedResources) != 2 {
|
||||
return fmt.Errorf("expect track %q resources, but got %q", 2, len(resourceTracker.Status.TrackedResources))
|
||||
}
|
||||
return nil
|
||||
}, time.Second*60, time.Microsecond*300).Should(BeNil())
|
||||
}, time.Second*5, time.Millisecond*500).Should(BeNil())
|
||||
})
|
||||
|
||||
It("Test update application by delete a cross namespace trait resource", func() {
|
||||
@@ -511,12 +496,12 @@ var _ = Describe("Test application cross namespace resource", func() {
|
||||
},
|
||||
Spec: v1beta1.ApplicationSpec{
|
||||
Components: []v1beta1.ApplicationComponent{
|
||||
v1beta1.ApplicationComponent{
|
||||
{
|
||||
Name: componentName,
|
||||
Type: "normal-worker",
|
||||
Properties: runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox"}`)},
|
||||
Traits: []v1beta1.ApplicationTrait{
|
||||
v1beta1.ApplicationTrait{
|
||||
{
|
||||
Type: "cross-scaler",
|
||||
Properties: runtime.RawExtension{Raw: []byte(`{"replicas": 1}`)},
|
||||
},
|
||||
@@ -526,7 +511,6 @@ var _ = Describe("Test application cross namespace resource", func() {
|
||||
},
|
||||
}
|
||||
Expect(k8sClient.Create(ctx, app)).Should(BeNil())
|
||||
time.Sleep(3 * time.Second) // give informer cache to sync
|
||||
resourceTracker := new(v1beta1.ResourceTracker)
|
||||
By("create application will create a cross ns trait, and resourceTracker. check those status")
|
||||
Eventually(func() error {
|
||||
@@ -537,7 +521,7 @@ var _ = Describe("Test application cross namespace resource", func() {
|
||||
if app.Status.Phase != common.ApplicationRunning {
|
||||
return fmt.Errorf("application status not running")
|
||||
}
|
||||
err := k8sClient.Get(ctx, generateResourceTrackerKey(app.Namespace, app.Name), resourceTracker)
|
||||
err := k8sClient.Get(ctx, generateResourceTrackerKey(app.Namespace, app.Name, 1), resourceTracker)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error to get resourceTracker %v", err)
|
||||
}
|
||||
@@ -556,22 +540,19 @@ var _ = Describe("Test application cross namespace resource", func() {
|
||||
if len(trait.OwnerReferences) != 1 || trait.OwnerReferences[0].UID != resourceTracker.UID {
|
||||
return fmt.Errorf("trait owner reference missmatch")
|
||||
}
|
||||
if len(resourceTracker.Status.TrackedResources) != 1 {
|
||||
return fmt.Errorf("resourceTracker status recode trackedResource length missmatch")
|
||||
}
|
||||
if resourceTracker.Status.TrackedResources[0].Name != trait.Name {
|
||||
return fmt.Errorf("resourceTracker status recode trackedResource name mismatch recorded %s, actually %s", resourceTracker.Status.TrackedResources[0].Name, trait.Name)
|
||||
if len(resourceTracker.Status.TrackedResources) != 2 {
|
||||
return fmt.Errorf("expect track %q resources, but got %q", 2, len(resourceTracker.Status.TrackedResources))
|
||||
}
|
||||
return nil
|
||||
}, time.Second*60, time.Microsecond*300).Should(BeNil())
|
||||
}, time.Second*5, time.Millisecond*300).Should(BeNil())
|
||||
|
||||
By("update application trait by delete cross ns trait, will delete resourceTracker and related trait resource")
|
||||
By("update application trait by delete cross ns trait")
|
||||
Eventually(func() error {
|
||||
app = new(v1beta1.Application)
|
||||
Expect(k8sClient.Get(ctx, types.NamespacedName{Namespace: namespace, Name: appName}, app)).Should(BeNil())
|
||||
app.Spec.Components[0].Traits = []v1beta1.ApplicationTrait{}
|
||||
return k8sClient.Update(ctx, app)
|
||||
}, time.Second*30, time.Microsecond*300).Should(BeNil())
|
||||
}, time.Second*5, time.Millisecond*300).Should(BeNil())
|
||||
fmt.Println(app.ResourceVersion)
|
||||
Eventually(func() error {
|
||||
app = new(v1beta1.Application)
|
||||
@@ -581,9 +562,8 @@ var _ = Describe("Test application cross namespace resource", func() {
|
||||
if app.Status.Phase != common.ApplicationRunning {
|
||||
return fmt.Errorf("application status not running")
|
||||
}
|
||||
err := k8sClient.Get(ctx, generateResourceTrackerKey(app.Namespace, app.Name), resourceTracker)
|
||||
if err == nil {
|
||||
return fmt.Errorf("resourceTracker still exist")
|
||||
if err := k8sClient.Get(ctx, generateResourceTrackerKey(app.Namespace, app.Name, 2), resourceTracker); err != nil {
|
||||
return err
|
||||
}
|
||||
mts := new(v1alpha2.ManualScalerTraitList)
|
||||
opts := []client.ListOption{
|
||||
@@ -596,11 +576,8 @@ var _ = Describe("Test application cross namespace resource", func() {
|
||||
if err != nil || len(mts.Items) != 0 {
|
||||
return fmt.Errorf("cross ns trait still exist")
|
||||
}
|
||||
if app.Status.ResourceTracker != nil {
|
||||
return fmt.Errorf("application status resourceTracker field still exist %s", string(util.JSONMarshal(app.Status.ResourceTracker)))
|
||||
}
|
||||
return nil
|
||||
}, time.Second*60, time.Microsecond*300).Should(BeNil())
|
||||
}, time.Second*5, time.Millisecond*500).Should(BeNil())
|
||||
})
|
||||
|
||||
It("Test application have two different workload", func() {
|
||||
@@ -629,12 +606,12 @@ var _ = Describe("Test application cross namespace resource", func() {
|
||||
},
|
||||
Spec: v1beta1.ApplicationSpec{
|
||||
Components: []v1beta1.ApplicationComponent{
|
||||
v1beta1.ApplicationComponent{
|
||||
{
|
||||
Name: component1Name,
|
||||
Type: "normal-worker",
|
||||
Properties: runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox"}`)},
|
||||
},
|
||||
v1beta1.ApplicationComponent{
|
||||
{
|
||||
Name: component2Name,
|
||||
Type: "cross-worker",
|
||||
Properties: runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox"}`)},
|
||||
@@ -644,7 +621,6 @@ var _ = Describe("Test application cross namespace resource", func() {
|
||||
}
|
||||
|
||||
Expect(k8sClient.Create(ctx, app)).Should(BeNil())
|
||||
time.Sleep(3 * time.Second) // give informer cache to sync
|
||||
resourceTracker := new(v1beta1.ResourceTracker)
|
||||
|
||||
By("create application will generate two workload, and generate resourceTracker")
|
||||
@@ -656,7 +632,7 @@ var _ = Describe("Test application cross namespace resource", func() {
|
||||
if app.Status.Phase != common.ApplicationRunning {
|
||||
return fmt.Errorf("application status not running")
|
||||
}
|
||||
err := k8sClient.Get(ctx, generateResourceTrackerKey(app.Namespace, app.Name), resourceTracker)
|
||||
err := k8sClient.Get(ctx, generateResourceTrackerKey(app.Namespace, app.Name, 1), resourceTracker)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error to generate resourceTracker %v", err)
|
||||
}
|
||||
@@ -678,7 +654,7 @@ var _ = Describe("Test application cross namespace resource", func() {
|
||||
return fmt.Errorf("failed generate same namespace workload")
|
||||
}
|
||||
sameDeplpoy := same.Items[0]
|
||||
if len(sameDeplpoy.OwnerReferences) != 1 || sameDeplpoy.OwnerReferences[0].Kind != v1alpha2.ApplicationContextKind {
|
||||
if len(sameDeplpoy.OwnerReferences) != 1 || sameDeplpoy.OwnerReferences[0].Kind != v1beta1.ResourceTrackerKind {
|
||||
return fmt.Errorf("same ns deploy have error ownerReference")
|
||||
}
|
||||
err = k8sClient.List(ctx, cross, crossOpts...)
|
||||
@@ -689,24 +665,18 @@ var _ = Describe("Test application cross namespace resource", func() {
|
||||
if len(sameDeplpoy.OwnerReferences) != 1 || crossDeplpoy.OwnerReferences[0].UID != resourceTracker.UID {
|
||||
return fmt.Errorf("same ns deploy have error ownerReference")
|
||||
}
|
||||
if app.Status.ResourceTracker == nil || app.Status.ResourceTracker.UID != resourceTracker.UID {
|
||||
return fmt.Errorf("app status resourceTracker error")
|
||||
}
|
||||
if len(resourceTracker.Status.TrackedResources) != 1 {
|
||||
return fmt.Errorf("resourceTracker status recode trackedResource length missmatch")
|
||||
}
|
||||
if resourceTracker.Status.TrackedResources[0].Name != crossDeplpoy.Name {
|
||||
return fmt.Errorf("resourceTracker status recode trackedResource name mismatch recorded %s, actually %s", resourceTracker.Status.TrackedResources[0].Name, crossDeplpoy.Name)
|
||||
if len(resourceTracker.Status.TrackedResources) != 2 {
|
||||
return fmt.Errorf("expect track %q resources, but got %q", 2, len(resourceTracker.Status.TrackedResources))
|
||||
}
|
||||
return nil
|
||||
}, time.Second*60, time.Microsecond*300).Should(BeNil())
|
||||
By("update application by delete cross namespace workload, resource tracker will be deleted, then check app status")
|
||||
}, time.Second*5, time.Millisecond*500).Should(BeNil())
|
||||
By("update application by delete cross namespace workload")
|
||||
Eventually(func() error {
|
||||
app = new(v1beta1.Application)
|
||||
Expect(k8sClient.Get(ctx, types.NamespacedName{Namespace: namespace, Name: appName}, app)).Should(BeNil())
|
||||
app.Spec.Components = app.Spec.Components[:1] // delete a component
|
||||
return k8sClient.Update(ctx, app)
|
||||
}, time.Second*30, time.Microsecond*300).Should(BeNil())
|
||||
}, time.Second*5, time.Millisecond*300).Should(BeNil())
|
||||
Eventually(func() error {
|
||||
app = new(v1beta1.Application)
|
||||
if err := k8sClient.Get(ctx, types.NamespacedName{Namespace: namespace, Name: appName}, app); err != nil {
|
||||
@@ -715,9 +685,8 @@ var _ = Describe("Test application cross namespace resource", func() {
|
||||
if app.Status.Phase != common.ApplicationRunning {
|
||||
return fmt.Errorf("application status not running")
|
||||
}
|
||||
err := k8sClient.Get(ctx, generateResourceTrackerKey(app.Namespace, app.Name), resourceTracker)
|
||||
if err == nil {
|
||||
return fmt.Errorf("resourceTracker still exist")
|
||||
if err := k8sClient.Get(ctx, generateResourceTrackerKey(app.Namespace, app.Name, 2), resourceTracker); err != nil {
|
||||
return err
|
||||
}
|
||||
sameOpts := []client.ListOption{
|
||||
client.InNamespace(namespace),
|
||||
@@ -737,18 +706,15 @@ var _ = Describe("Test application cross namespace resource", func() {
|
||||
return fmt.Errorf("failed generate same namespace workload")
|
||||
}
|
||||
sameDeplpoy := same.Items[0]
|
||||
if len(sameDeplpoy.OwnerReferences) != 1 || sameDeplpoy.OwnerReferences[0].Kind != v1alpha2.ApplicationContextKind {
|
||||
if len(sameDeplpoy.OwnerReferences) != 1 || sameDeplpoy.OwnerReferences[0].Kind != v1beta1.ResourceTrackerKind {
|
||||
return fmt.Errorf("same ns deploy have error ownerReference")
|
||||
}
|
||||
err = k8sClient.List(ctx, cross, crossOpts...)
|
||||
if err != nil || len(cross.Items) != 0 {
|
||||
return fmt.Errorf("error : cross namespace workload still exist")
|
||||
}
|
||||
if app.Status.ResourceTracker != nil {
|
||||
return fmt.Errorf("error app status resourceTracker")
|
||||
}
|
||||
return nil
|
||||
}, time.Second*60, time.Microsecond*300).Should(BeNil())
|
||||
}, time.Second*5, time.Millisecond*300).Should(BeNil())
|
||||
})
|
||||
|
||||
It("Update a cross namespace workload of application", func() {
|
||||
@@ -769,7 +735,7 @@ var _ = Describe("Test application cross namespace resource", func() {
|
||||
},
|
||||
Spec: v1beta1.ApplicationSpec{
|
||||
Components: []v1beta1.ApplicationComponent{
|
||||
v1beta1.ApplicationComponent{
|
||||
{
|
||||
Name: componentName,
|
||||
Type: "cross-worker",
|
||||
Properties: runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox"}`)},
|
||||
@@ -785,25 +751,18 @@ var _ = Describe("Test application cross namespace resource", func() {
|
||||
if err := k8sClient.Get(ctx, types.NamespacedName{Namespace: namespace, Name: appName}, app); err != nil {
|
||||
return fmt.Errorf("app not found %v", err)
|
||||
}
|
||||
if err := k8sClient.Get(ctx, generateResourceTrackerKey(app.Namespace, app.Name), resourceTracker); err != nil {
|
||||
if err := k8sClient.Get(ctx, generateResourceTrackerKey(app.Namespace, app.Name, 1), resourceTracker); err != nil {
|
||||
return err
|
||||
}
|
||||
if app.Status.Phase != common.ApplicationRunning {
|
||||
return fmt.Errorf("application status is not running")
|
||||
}
|
||||
if app.Status.ResourceTracker == nil || app.Status.ResourceTracker.UID != resourceTracker.UID {
|
||||
return fmt.Errorf("appication status error ")
|
||||
}
|
||||
return nil
|
||||
}, time.Second*600, time.Microsecond*300).Should(BeNil())
|
||||
}, time.Second*5, time.Millisecond*300).Should(BeNil())
|
||||
By("check resource is generated correctly")
|
||||
Expect(k8sClient.Get(ctx, types.NamespacedName{Namespace: namespace, Name: appName}, app)).Should(BeNil())
|
||||
var workload appsv1.Deployment
|
||||
Eventually(func() error {
|
||||
appContext := &v1alpha2.ApplicationContext{}
|
||||
if err := k8sClient.Get(ctx, types.NamespacedName{Namespace: namespace, Name: appName}, appContext); err != nil {
|
||||
return fmt.Errorf("cannot generate AppContext %v", err)
|
||||
}
|
||||
component := &v1alpha2.Component{}
|
||||
if err := k8sClient.Get(ctx, types.NamespacedName{Namespace: namespace, Name: componentName}, component); err != nil {
|
||||
return fmt.Errorf("cannot generate component %v", err)
|
||||
@@ -823,7 +782,7 @@ var _ = Describe("Test application cross namespace resource", func() {
|
||||
return fmt.Errorf("error workload number %v", err)
|
||||
}
|
||||
workload = depolys.Items[0]
|
||||
if err := k8sClient.Get(ctx, generateResourceTrackerKey(app.Namespace, app.Name), resourceTracker); err != nil {
|
||||
if err := k8sClient.Get(ctx, generateResourceTrackerKey(app.Namespace, app.Name, 1), resourceTracker); err != nil {
|
||||
return err
|
||||
}
|
||||
if len(workload.OwnerReferences) != 1 || workload.OwnerReferences[0].UID != resourceTracker.UID {
|
||||
@@ -833,13 +792,10 @@ var _ = Describe("Test application cross namespace resource", func() {
|
||||
return fmt.Errorf("container image not match")
|
||||
}
|
||||
if len(resourceTracker.Status.TrackedResources) != 1 {
|
||||
return fmt.Errorf("resourceTracker status recode trackedResource length missmatch")
|
||||
}
|
||||
if resourceTracker.Status.TrackedResources[0].Name != workload.Name {
|
||||
return fmt.Errorf("resourceTracker status recode trackedResource name mismatch recorded %s, actually %s", resourceTracker.Status.TrackedResources[0].Name, workload.Name)
|
||||
return fmt.Errorf("expect track %q resources, but got %q", 1, len(resourceTracker.Status.TrackedResources))
|
||||
}
|
||||
return nil
|
||||
}, time.Second*50, time.Microsecond*300).Should(BeNil())
|
||||
}, time.Second*50, time.Millisecond*300).Should(BeNil())
|
||||
|
||||
By("update application and check resource status")
|
||||
Eventually(func() error {
|
||||
@@ -854,13 +810,9 @@ var _ = Describe("Test application cross namespace resource", func() {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}, time.Second*60, time.Microsecond*300).Should(BeNil())
|
||||
}, time.Second*5, time.Millisecond*300).Should(BeNil())
|
||||
|
||||
Eventually(func() error {
|
||||
appContext := &v1alpha2.ApplicationContext{}
|
||||
if err := k8sClient.Get(ctx, types.NamespacedName{Namespace: namespace, Name: appName}, appContext); err != nil {
|
||||
return fmt.Errorf("cannot generate AppContext %v", err)
|
||||
}
|
||||
component := &v1alpha2.Component{}
|
||||
if err := k8sClient.Get(ctx, types.NamespacedName{Namespace: namespace, Name: componentName}, component); err != nil {
|
||||
return fmt.Errorf("cannot generate component %v", err)
|
||||
@@ -868,6 +820,12 @@ var _ = Describe("Test application cross namespace resource", func() {
|
||||
if component.ObjectMeta.Labels[oam.LabelAppName] != appName {
|
||||
return fmt.Errorf("component error label ")
|
||||
}
|
||||
if err := k8sClient.Get(ctx, generateResourceTrackerKey(app.Namespace, app.Name, 2), resourceTracker); err != nil {
|
||||
return err
|
||||
}
|
||||
if len(resourceTracker.Status.TrackedResources) != 1 {
|
||||
return fmt.Errorf("expect track %q resources, but got %q", 1, len(resourceTracker.Status.TrackedResources))
|
||||
}
|
||||
depolys := new(appsv1.DeploymentList)
|
||||
opts := []client.ListOption{
|
||||
client.InNamespace(crossNamespace),
|
||||
@@ -886,24 +844,14 @@ var _ = Describe("Test application cross namespace resource", func() {
|
||||
if workload.Spec.Template.Spec.Containers[0].Image != "nginx" {
|
||||
return fmt.Errorf("container image not match")
|
||||
}
|
||||
if err := k8sClient.Get(ctx, generateResourceTrackerKey(app.Namespace, app.Name), resourceTracker); err != nil {
|
||||
return err
|
||||
}
|
||||
if len(resourceTracker.Status.TrackedResources) != 1 {
|
||||
return fmt.Errorf("resourceTracker status recode trackedResource length missmatch")
|
||||
}
|
||||
if resourceTracker.Status.TrackedResources[0].Name != workload.Name {
|
||||
return fmt.Errorf("resourceTracker status recode trackedResource name mismatch recorded %s, actually %s", resourceTracker.Status.TrackedResources[0].Name, workload.Name)
|
||||
}
|
||||
return nil
|
||||
}, time.Second*60, time.Microsecond*1000).Should(BeNil())
|
||||
}, time.Second*5, time.Millisecond*500).Should(BeNil())
|
||||
|
||||
By("deleting application will remove resourceTracker and related workload will be removed")
|
||||
time.Sleep(3 * time.Second) // wait informer cache to be synced
|
||||
Expect(k8sClient.Get(ctx, types.NamespacedName{Namespace: namespace, Name: appName}, app)).Should(BeNil())
|
||||
Expect(k8sClient.Delete(ctx, app)).Should(BeNil())
|
||||
Eventually(func() error {
|
||||
err := k8sClient.Get(ctx, generateResourceTrackerKey(app.Namespace, app.Name), resourceTracker)
|
||||
err := k8sClient.Get(ctx, generateResourceTrackerKey(app.Namespace, app.Name, 2), resourceTracker)
|
||||
if err == nil {
|
||||
return fmt.Errorf("resourceTracker still exist")
|
||||
}
|
||||
@@ -918,7 +866,7 @@ var _ = Describe("Test application cross namespace resource", func() {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}, time.Second*30, time.Microsecond*300).Should(BeNil())
|
||||
}, time.Second*5, time.Millisecond*500).Should(BeNil())
|
||||
})
|
||||
|
||||
It("Test cross-namespace resource gc logic, delete a cross-ns component", func() {
|
||||
@@ -943,12 +891,12 @@ var _ = Describe("Test application cross namespace resource", func() {
|
||||
},
|
||||
Spec: v1beta1.ApplicationSpec{
|
||||
Components: []v1beta1.ApplicationComponent{
|
||||
v1beta1.ApplicationComponent{
|
||||
{
|
||||
Name: component1Name,
|
||||
Type: "cross-worker",
|
||||
Properties: runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox"}`)},
|
||||
},
|
||||
v1beta1.ApplicationComponent{
|
||||
{
|
||||
Name: component2Name,
|
||||
Type: "cross-worker",
|
||||
Properties: runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox"}`)},
|
||||
@@ -958,7 +906,6 @@ var _ = Describe("Test application cross namespace resource", func() {
|
||||
}
|
||||
|
||||
Expect(k8sClient.Create(ctx, app)).Should(BeNil())
|
||||
time.Sleep(3 * time.Second) // give informer cache to sync
|
||||
resourceTracker := new(v1beta1.ResourceTracker)
|
||||
|
||||
By("create application will generate two workload, and generate resourceTracker")
|
||||
@@ -970,7 +917,7 @@ var _ = Describe("Test application cross namespace resource", func() {
|
||||
if app.Status.Phase != common.ApplicationRunning {
|
||||
return fmt.Errorf("application status not running")
|
||||
}
|
||||
err := k8sClient.Get(ctx, generateResourceTrackerKey(app.Namespace, app.Name), resourceTracker)
|
||||
err := k8sClient.Get(ctx, generateResourceTrackerKey(app.Namespace, app.Name, 1), resourceTracker)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error to generate resourceTracker %v", err)
|
||||
}
|
||||
@@ -994,11 +941,8 @@ var _ = Describe("Test application cross namespace resource", func() {
|
||||
if len(deploy2.OwnerReferences) != 1 || deploy2.OwnerReferences[0].UID != resourceTracker.UID {
|
||||
return fmt.Errorf("deploy2 have error ownerReference")
|
||||
}
|
||||
if app.Status.ResourceTracker == nil || app.Status.ResourceTracker.UID != resourceTracker.UID {
|
||||
return fmt.Errorf("app status resourceTracker error")
|
||||
}
|
||||
if len(resourceTracker.Status.TrackedResources) != 2 {
|
||||
return fmt.Errorf("resourceTracker status recode trackedResource length missmatch")
|
||||
return fmt.Errorf("expect track %q resources, but got %q", 2, len(resourceTracker.Status.TrackedResources))
|
||||
}
|
||||
if resourceTracker.Status.TrackedResources[0].Namespace != crossNamespace || resourceTracker.Status.TrackedResources[1].Namespace != crossNamespace {
|
||||
return fmt.Errorf("resourceTracker recorde namespace mismatch")
|
||||
@@ -1010,14 +954,14 @@ var _ = Describe("Test application cross namespace resource", func() {
|
||||
return fmt.Errorf("resourceTracker status recode trackedResource name mismatch recorded %s, actually %s", resourceTracker.Status.TrackedResources[0].Name, deploy2.Name)
|
||||
}
|
||||
return nil
|
||||
}, time.Second*60, time.Microsecond*300).Should(BeNil())
|
||||
By("update application by delete a cross namespace workload, resource tracker will still exist, then check app status")
|
||||
}, time.Second*5, time.Millisecond*300).Should(BeNil())
|
||||
By("update application by delete a cross namespace workload")
|
||||
Eventually(func() error {
|
||||
app = new(v1beta1.Application)
|
||||
Expect(k8sClient.Get(ctx, types.NamespacedName{Namespace: namespace, Name: appName}, app)).Should(BeNil())
|
||||
app.Spec.Components = app.Spec.Components[:1] // delete a component
|
||||
return k8sClient.Update(ctx, app)
|
||||
}, time.Second*30, time.Microsecond*300).Should(BeNil())
|
||||
}, time.Second*5, time.Millisecond*300).Should(BeNil())
|
||||
Eventually(func() error {
|
||||
app = new(v1beta1.Application)
|
||||
if err := k8sClient.Get(ctx, types.NamespacedName{Namespace: namespace, Name: appName}, app); err != nil {
|
||||
@@ -1026,7 +970,7 @@ var _ = Describe("Test application cross namespace resource", func() {
|
||||
if app.Status.Phase != common.ApplicationRunning {
|
||||
return fmt.Errorf("application status not running")
|
||||
}
|
||||
err := k8sClient.Get(ctx, generateResourceTrackerKey(app.Namespace, app.Name), resourceTracker)
|
||||
err := k8sClient.Get(ctx, generateResourceTrackerKey(app.Namespace, app.Name, 2), resourceTracker)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get resourceTracker %v", err)
|
||||
}
|
||||
@@ -1046,28 +990,22 @@ var _ = Describe("Test application cross namespace resource", func() {
|
||||
return fmt.Errorf("same ns deploy have error ownerReference")
|
||||
}
|
||||
checkRt := new(v1beta1.ResourceTracker)
|
||||
err = k8sClient.Get(ctx, generateResourceTrackerKey(app.Namespace, app.Name), checkRt)
|
||||
err = k8sClient.Get(ctx, generateResourceTrackerKey(app.Namespace, app.Name, 2), checkRt)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error get resourceTracker")
|
||||
}
|
||||
if app.Status.ResourceTracker == nil {
|
||||
return fmt.Errorf("app status resourceTracker error")
|
||||
}
|
||||
if app.Status.ResourceTracker.UID != checkRt.UID {
|
||||
return fmt.Errorf("error app status resourceTracker UID")
|
||||
}
|
||||
if len(checkRt.Status.TrackedResources) != 1 {
|
||||
return fmt.Errorf("error resourceTracker status trackedResource")
|
||||
return fmt.Errorf("expect track %q resources, but got %q", 1, len(checkRt.Status.TrackedResources))
|
||||
}
|
||||
return nil
|
||||
}, time.Second*80, time.Microsecond*300).Should(BeNil())
|
||||
}, time.Second*5, time.Millisecond*500).Should(BeNil())
|
||||
|
||||
By("deleting application will remove resourceTracker and related resourceTracker will be removed")
|
||||
By("deleting application will remove resourceTracker")
|
||||
app = new(v1beta1.Application)
|
||||
Expect(k8sClient.Get(ctx, types.NamespacedName{Namespace: namespace, Name: appName}, app)).Should(BeNil())
|
||||
Expect(k8sClient.Delete(ctx, app)).Should(BeNil())
|
||||
Eventually(func() error {
|
||||
err := k8sClient.Get(ctx, generateResourceTrackerKey(app.Namespace, app.Name), resourceTracker)
|
||||
err := k8sClient.Get(ctx, generateResourceTrackerKey(app.Namespace, app.Name, 2), resourceTracker)
|
||||
if err == nil {
|
||||
return fmt.Errorf("resourceTracker still exist")
|
||||
}
|
||||
@@ -1075,7 +1013,7 @@ var _ = Describe("Test application cross namespace resource", func() {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}, time.Second*60, time.Microsecond*300).Should(BeNil())
|
||||
}, time.Second*5, time.Millisecond*500).Should(BeNil())
|
||||
})
|
||||
|
||||
It("Test cross-namespace resource gc logic, delete a cross-ns trait", func() {
|
||||
@@ -1105,12 +1043,12 @@ var _ = Describe("Test application cross namespace resource", func() {
|
||||
},
|
||||
Spec: v1beta1.ApplicationSpec{
|
||||
Components: []v1beta1.ApplicationComponent{
|
||||
v1beta1.ApplicationComponent{
|
||||
{
|
||||
Name: componentName,
|
||||
Type: "cross-worker",
|
||||
Properties: runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox"}`)},
|
||||
Traits: []v1beta1.ApplicationTrait{
|
||||
v1beta1.ApplicationTrait{
|
||||
{
|
||||
Type: "cross-scaler",
|
||||
Properties: runtime.RawExtension{Raw: []byte(`{"replicas": 0}`)},
|
||||
},
|
||||
@@ -1121,7 +1059,6 @@ var _ = Describe("Test application cross namespace resource", func() {
|
||||
}
|
||||
|
||||
Expect(k8sClient.Create(ctx, app)).Should(BeNil())
|
||||
time.Sleep(3 * time.Second) // give informer cache to sync
|
||||
resourceTracker := new(v1beta1.ResourceTracker)
|
||||
By("create app and check resource and app status")
|
||||
Eventually(func() error {
|
||||
@@ -1132,7 +1069,7 @@ var _ = Describe("Test application cross namespace resource", func() {
|
||||
if app.Status.Phase != common.ApplicationRunning {
|
||||
return fmt.Errorf("application status not running")
|
||||
}
|
||||
err := k8sClient.Get(ctx, generateResourceTrackerKey(app.Namespace, app.Name), resourceTracker)
|
||||
err := k8sClient.Get(ctx, generateResourceTrackerKey(app.Namespace, app.Name, 1), resourceTracker)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error to get resourceTracker %v", err)
|
||||
}
|
||||
@@ -1148,7 +1085,7 @@ var _ = Describe("Test application cross namespace resource", func() {
|
||||
return fmt.Errorf("failed generate cross namespace trait")
|
||||
}
|
||||
if len(resourceTracker.Status.TrackedResources) != 2 {
|
||||
return fmt.Errorf("resourceTracker status recode trackedResource length missmatch")
|
||||
return fmt.Errorf("expect track %q resources, but got %q", 2, len(resourceTracker.Status.TrackedResources))
|
||||
}
|
||||
trait := mts.Items[0]
|
||||
if len(trait.OwnerReferences) != 1 || trait.OwnerReferences[0].UID != resourceTracker.UID {
|
||||
@@ -1172,7 +1109,7 @@ var _ = Describe("Test application cross namespace resource", func() {
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}, time.Second*60, time.Microsecond*300).Should(BeNil())
|
||||
}, time.Second*5, time.Millisecond*500).Should(BeNil())
|
||||
|
||||
By("update application trait by delete cross ns trait, resourceTracker will still exist")
|
||||
Eventually(func() error {
|
||||
@@ -1180,7 +1117,7 @@ var _ = Describe("Test application cross namespace resource", func() {
|
||||
Expect(k8sClient.Get(ctx, types.NamespacedName{Namespace: namespace, Name: appName}, app)).Should(BeNil())
|
||||
app.Spec.Components[0].Traits = []v1beta1.ApplicationTrait{}
|
||||
return k8sClient.Update(ctx, app)
|
||||
}, time.Second*30, time.Microsecond*300).Should(BeNil())
|
||||
}, time.Second*5, time.Millisecond*300).Should(BeNil())
|
||||
|
||||
Eventually(func() error {
|
||||
app = new(v1beta1.Application)
|
||||
@@ -1190,7 +1127,7 @@ var _ = Describe("Test application cross namespace resource", func() {
|
||||
if app.Status.Phase != common.ApplicationRunning {
|
||||
return fmt.Errorf("application status not running")
|
||||
}
|
||||
err := k8sClient.Get(ctx, generateResourceTrackerKey(app.Namespace, app.Name), resourceTracker)
|
||||
err := k8sClient.Get(ctx, generateResourceTrackerKey(app.Namespace, app.Name, 2), resourceTracker)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error to get resourceTracker %v", err)
|
||||
}
|
||||
@@ -1206,7 +1143,7 @@ var _ = Describe("Test application cross namespace resource", func() {
|
||||
return fmt.Errorf("cross namespace trait still exist")
|
||||
}
|
||||
if len(resourceTracker.Status.TrackedResources) != 1 {
|
||||
return fmt.Errorf("resourceTracker status recode trackedResource length missmatch")
|
||||
return fmt.Errorf("expect track %d resources, but got %d", 1, len(resourceTracker.Status.TrackedResources))
|
||||
}
|
||||
deploys := new(appsv1.DeploymentList)
|
||||
err = k8sClient.List(ctx, deploys, opts...)
|
||||
@@ -1221,13 +1158,13 @@ var _ = Describe("Test application cross namespace resource", func() {
|
||||
return fmt.Errorf("error to record deploy name in app status")
|
||||
}
|
||||
return nil
|
||||
}, time.Second*60, time.Microsecond*300).Should(BeNil())
|
||||
}, time.Second*5, time.Millisecond*500).Should(BeNil())
|
||||
By("deleting application will remove resourceTracker and related resourceTracker will be removed")
|
||||
app = new(v1beta1.Application)
|
||||
Expect(k8sClient.Get(ctx, types.NamespacedName{Namespace: namespace, Name: appName}, app)).Should(BeNil())
|
||||
Expect(k8sClient.Delete(ctx, app)).Should(BeNil())
|
||||
Eventually(func() error {
|
||||
err := k8sClient.Get(ctx, generateResourceTrackerKey(app.Namespace, app.Name), resourceTracker)
|
||||
err := k8sClient.Get(ctx, generateResourceTrackerKey(app.Namespace, app.Name, 2), resourceTracker)
|
||||
if err == nil {
|
||||
return fmt.Errorf("resourceTracker still exist")
|
||||
}
|
||||
@@ -1235,7 +1172,7 @@ var _ = Describe("Test application cross namespace resource", func() {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}, time.Second*60, time.Microsecond*300).Should(BeNil())
|
||||
}, time.Second*5, time.Millisecond*500).Should(BeNil())
|
||||
})
|
||||
|
||||
It("Test cross-namespace resource gc logic, update a cross-ns workload's namespace", func() {
|
||||
@@ -1262,7 +1199,7 @@ var _ = Describe("Test application cross namespace resource", func() {
|
||||
},
|
||||
Spec: v1beta1.ApplicationSpec{
|
||||
Components: []v1beta1.ApplicationComponent{
|
||||
v1beta1.ApplicationComponent{
|
||||
{
|
||||
Name: componentName,
|
||||
Type: "cross-worker",
|
||||
Properties: runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox"}`)},
|
||||
@@ -1278,23 +1215,20 @@ var _ = Describe("Test application cross namespace resource", func() {
|
||||
if err := k8sClient.Get(ctx, types.NamespacedName{Namespace: namespace, Name: appName}, app); err != nil {
|
||||
return fmt.Errorf("app not found %v", err)
|
||||
}
|
||||
if err := k8sClient.Get(ctx, generateResourceTrackerKey(app.Namespace, app.Name), resourceTracker); err != nil {
|
||||
if err := k8sClient.Get(ctx, generateResourceTrackerKey(app.Namespace, app.Name, 1), resourceTracker); err != nil {
|
||||
return err
|
||||
}
|
||||
if app.Status.Phase != common.ApplicationRunning {
|
||||
return fmt.Errorf("application status is not running")
|
||||
}
|
||||
if app.Status.ResourceTracker == nil || app.Status.ResourceTracker.UID != resourceTracker.UID {
|
||||
return fmt.Errorf("appication status error ")
|
||||
}
|
||||
return nil
|
||||
}, time.Second*60, time.Microsecond*300).Should(BeNil())
|
||||
}, time.Second*5, time.Millisecond*500).Should(BeNil())
|
||||
By("check resource is generated correctly")
|
||||
Expect(k8sClient.Get(ctx, types.NamespacedName{Namespace: namespace, Name: appName}, app)).Should(BeNil())
|
||||
var workload appsv1.Deployment
|
||||
Eventually(func() error {
|
||||
checkRt := new(v1beta1.ResourceTracker)
|
||||
if err := k8sClient.Get(ctx, generateResourceTrackerKey(app.Namespace, app.Name), checkRt); err != nil {
|
||||
if err := k8sClient.Get(ctx, generateResourceTrackerKey(app.Namespace, app.Name, 1), checkRt); err != nil {
|
||||
return err
|
||||
}
|
||||
depolys := new(appsv1.DeploymentList)
|
||||
@@ -1319,10 +1253,9 @@ var _ = Describe("Test application cross namespace resource", func() {
|
||||
return fmt.Errorf("resourceTracker status recode trackedResource name mismatch recorded %s, actually %s", checkRt.Status.TrackedResources[0].Name, workload.Name)
|
||||
}
|
||||
return nil
|
||||
}, time.Second*60, time.Microsecond*300).Should(BeNil())
|
||||
}, time.Second*5, time.Millisecond*500).Should(BeNil())
|
||||
|
||||
By("update application modify workload namespace will remove resourceTracker and related old workload will be removed")
|
||||
time.Sleep(3 * time.Second) // wait informer cache to be synced
|
||||
By("update application modify workload namespace")
|
||||
Eventually(func() error {
|
||||
app = new(v1beta1.Application)
|
||||
err := k8sClient.Get(ctx, types.NamespacedName{Namespace: namespace, Name: appName}, app)
|
||||
@@ -1335,16 +1268,12 @@ var _ = Describe("Test application cross namespace resource", func() {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}, time.Second*30, time.Microsecond).Should(BeNil())
|
||||
}, time.Second*5, time.Millisecond*500).Should(BeNil())
|
||||
Eventually(func() error {
|
||||
err := k8sClient.Get(ctx, generateResourceTrackerKey(app.Namespace, app.Name), resourceTracker)
|
||||
if err == nil {
|
||||
return fmt.Errorf("resourceTracker still exist")
|
||||
}
|
||||
if !apierrors.IsNotFound(err) {
|
||||
if err := k8sClient.Get(ctx, generateResourceTrackerKey(app.Namespace, app.Name, 2), resourceTracker); err != nil {
|
||||
return err
|
||||
}
|
||||
err = k8sClient.Get(ctx, types.NamespacedName{Namespace: crossNamespace, Name: workload.GetName()}, &workload)
|
||||
err := k8sClient.Get(ctx, types.NamespacedName{Namespace: crossNamespace, Name: workload.GetName()}, &workload)
|
||||
if err == nil {
|
||||
return fmt.Errorf("wrokload still exist")
|
||||
}
|
||||
@@ -1357,12 +1286,12 @@ var _ = Describe("Test application cross namespace resource", func() {
|
||||
return fmt.Errorf("generate same namespace workload error")
|
||||
}
|
||||
return nil
|
||||
}, time.Second*60, time.Microsecond*300).Should(BeNil())
|
||||
}, time.Second*5, time.Millisecond*500).Should(BeNil())
|
||||
})
|
||||
})
|
||||
|
||||
func generateResourceTrackerKey(namespace string, name string) types.NamespacedName {
|
||||
return types.NamespacedName{Name: fmt.Sprintf("%s-%s", namespace, name)}
|
||||
func generateResourceTrackerKey(namespace string, appName string, revision int) types.NamespacedName {
|
||||
return types.NamespacedName{Name: fmt.Sprintf("%s-v%d-%s", appName, revision, namespace)}
|
||||
}
|
||||
|
||||
const (
|
||||
|
||||
@@ -31,9 +31,9 @@ import (
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
"k8s.io/utils/pointer"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha2"
|
||||
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
|
||||
"github.com/oam-dev/kubevela/apis/standard.oam.dev/v1alpha1"
|
||||
"github.com/oam-dev/kubevela/pkg/oam"
|
||||
@@ -46,12 +46,12 @@ var (
|
||||
|
||||
var _ = Describe("Test application controller clean up appRevision", func() {
|
||||
ctx := context.TODO()
|
||||
namespace := "clean-up-revision"
|
||||
var namespace string
|
||||
|
||||
cd := &v1beta1.ComponentDefinition{}
|
||||
cdDefJson, _ := yaml.YAMLToJSON([]byte(compDefYaml))
|
||||
|
||||
BeforeEach(func() {
|
||||
namespace = randomNamespaceName("clean-up-revision-test")
|
||||
ns := v1.Namespace{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: namespace,
|
||||
@@ -59,6 +59,7 @@ var _ = Describe("Test application controller clean up appRevision", func() {
|
||||
}
|
||||
Expect(k8sClient.Create(ctx, &ns)).Should(SatisfyAny(BeNil(), &util.AlreadyExistMatcher{}))
|
||||
|
||||
cdDefJson, _ := yaml.YAMLToJSON([]byte(fmt.Sprintf(compDefYaml, namespace)))
|
||||
Expect(json.Unmarshal(cdDefJson, cd)).Should(BeNil())
|
||||
Expect(k8sClient.Create(ctx, cd.DeepCopy())).Should(SatisfyAny(BeNil(), &util.AlreadyExistMatcher{}))
|
||||
})
|
||||
@@ -71,15 +72,6 @@ var _ = Describe("Test application controller clean up appRevision", func() {
|
||||
k8sClient.DeleteAllOf(ctx, &v1beta1.TraitDefinition{}, client.InNamespace(namespace))
|
||||
|
||||
Expect(k8sClient.Delete(ctx, &v1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: namespace}}, client.PropagationPolicy(metav1.DeletePropagationForeground))).Should(Succeed())
|
||||
// guarantee namespace have been deleted
|
||||
Eventually(func() error {
|
||||
ns := new(v1.Namespace)
|
||||
err := k8sClient.Get(ctx, types.NamespacedName{Name: namespace}, ns)
|
||||
if err == nil {
|
||||
return fmt.Errorf("namespace still exist")
|
||||
}
|
||||
return nil
|
||||
}, time.Second*60, time.Microsecond*300).Should(BeNil())
|
||||
})
|
||||
|
||||
It("Test clean up appRevision", func() {
|
||||
@@ -96,7 +88,7 @@ var _ = Describe("Test application controller clean up appRevision", func() {
|
||||
return fmt.Errorf("application point to wrong revision")
|
||||
}
|
||||
return nil
|
||||
}, time.Second*30, time.Microsecond*300).Should(BeNil())
|
||||
}, time.Second*10, time.Millisecond*500).Should(BeNil())
|
||||
Eventually(func() error {
|
||||
checkApp = new(v1beta1.Application)
|
||||
Expect(k8sClient.Get(ctx, appKey, checkApp)).Should(BeNil())
|
||||
@@ -106,10 +98,8 @@ var _ = Describe("Test application controller clean up appRevision", func() {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}, time.Second*30, time.Microsecond*300).Should(BeNil())
|
||||
}, time.Second*10, time.Millisecond*500).Should(BeNil())
|
||||
}
|
||||
appContext := new(v1alpha2.ApplicationContext)
|
||||
Expect(k8sClient.Get(ctx, appKey, appContext)).Should(BeNil())
|
||||
listOpts := []client.ListOption{
|
||||
client.InNamespace(namespace),
|
||||
client.MatchingLabels{
|
||||
@@ -126,13 +116,7 @@ var _ = Describe("Test application controller clean up appRevision", func() {
|
||||
return fmt.Errorf("error appRevison number wants %d, actually %d", appRevisionLimit+1, len(appRevisionList.Items))
|
||||
}
|
||||
return nil
|
||||
}, time.Second*30, time.Microsecond*300).Should(BeNil())
|
||||
Eventually(func() error {
|
||||
if err := k8sClient.Get(ctx, appKey, appContext); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}, time.Second*30, time.Microsecond*300).Should(BeNil())
|
||||
}, time.Second*10, time.Millisecond*500).Should(BeNil())
|
||||
By("create new appRevision will remove appRevison1")
|
||||
Expect(k8sClient.Get(ctx, appKey, checkApp)).Should(BeNil())
|
||||
property := fmt.Sprintf(`{"cmd":["sleep","1000"],"image":"busybox:%d"}`, 6)
|
||||
@@ -156,7 +140,7 @@ var _ = Describe("Test application controller clean up appRevision", func() {
|
||||
return fmt.Errorf("appRevision collection mismatch")
|
||||
}
|
||||
return nil
|
||||
}, time.Second*30, time.Microsecond*300).Should(BeNil())
|
||||
}, time.Second*10, time.Millisecond*500).Should(BeNil())
|
||||
|
||||
By("update app again will gc appRevision2")
|
||||
Eventually(func() error {
|
||||
@@ -187,7 +171,7 @@ var _ = Describe("Test application controller clean up appRevision", func() {
|
||||
return fmt.Errorf("appRevision collection mismatch")
|
||||
}
|
||||
return nil
|
||||
}, time.Second*30, time.Microsecond*300).Should(BeNil())
|
||||
}, time.Second*10, time.Millisecond*500).Should(BeNil())
|
||||
})
|
||||
|
||||
It("Test clean up rollout appRevision", func() {
|
||||
@@ -215,10 +199,8 @@ var _ = Describe("Test application controller clean up appRevision", func() {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}, time.Second*30, time.Microsecond*300).Should(BeNil())
|
||||
}, time.Second*10, time.Millisecond*500).Should(BeNil())
|
||||
}
|
||||
appContext := new(v1alpha2.ApplicationContext)
|
||||
Expect(k8sClient.Get(ctx, appKey, appContext)).Should(util.NotFoundMatcher{})
|
||||
listOpts := []client.ListOption{
|
||||
client.InNamespace(namespace),
|
||||
client.MatchingLabels{
|
||||
@@ -260,7 +242,7 @@ var _ = Describe("Test application controller clean up appRevision", func() {
|
||||
return fmt.Errorf("appRevision collection mismatch")
|
||||
}
|
||||
return nil
|
||||
}, time.Second*30, time.Microsecond*300).Should(BeNil())
|
||||
}, time.Second*10, time.Millisecond*500).Should(BeNil())
|
||||
|
||||
By("update app again will gc appRevision2")
|
||||
Expect(k8sClient.Get(ctx, appKey, checkApp)).Should(BeNil())
|
||||
@@ -284,7 +266,7 @@ var _ = Describe("Test application controller clean up appRevision", func() {
|
||||
return fmt.Errorf("appRevision collection mismatch")
|
||||
}
|
||||
return nil
|
||||
}, time.Second*30, time.Microsecond*300).Should(BeNil())
|
||||
}, time.Second*10, time.Millisecond*500).Should(BeNil())
|
||||
appRollout := &v1beta1.AppRollout{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
APIVersion: v1beta1.AppRolloutKindAPIVersion,
|
||||
@@ -298,9 +280,10 @@ var _ = Describe("Test application controller clean up appRevision", func() {
|
||||
TargetAppRevisionName: appName + "-v3",
|
||||
ComponentList: []string{"comp1"},
|
||||
RolloutPlan: v1alpha1.RolloutPlan{
|
||||
TargetSize: pointer.Int32Ptr(2),
|
||||
RolloutBatches: []v1alpha1.RolloutBatch{
|
||||
{
|
||||
Replicas: intstr.FromInt(1),
|
||||
Replicas: intstr.FromInt(2),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -318,7 +301,7 @@ var _ = Describe("Test application controller clean up appRevision", func() {
|
||||
return fmt.Errorf("application point to wrong revision")
|
||||
}
|
||||
return nil
|
||||
}, time.Second*30, time.Microsecond*300).Should(BeNil())
|
||||
}, time.Second*10, time.Millisecond*500).Should(BeNil())
|
||||
Eventually(func() error {
|
||||
if err := k8sClient.Get(ctx, appKey, checkApp); err != nil {
|
||||
return err
|
||||
@@ -354,7 +337,7 @@ var _ = Describe("Test application controller clean up appRevision", func() {
|
||||
return fmt.Errorf("appRevision collection mismatch")
|
||||
}
|
||||
return nil
|
||||
}, time.Second*30, time.Microsecond*300).Should(BeNil())
|
||||
}, time.Second*60, time.Microsecond*300).Should(BeNil())
|
||||
})
|
||||
})
|
||||
|
||||
@@ -364,7 +347,7 @@ apiVersion: core.oam.dev/v1beta1
|
||||
kind: ComponentDefinition
|
||||
metadata:
|
||||
name: normal-worker
|
||||
namespace: clean-up-revision
|
||||
namespace: %s
|
||||
annotations:
|
||||
definition.oam.dev/description: "Long-running scalable backend worker without network endpoint"
|
||||
spec:
|
||||
|
||||
@@ -1,349 +0,0 @@
|
||||
/*
|
||||
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"
|
||||
"time"
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"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"
|
||||
)
|
||||
|
||||
var _ = Describe("Test applicationContext reconcile", func() {
|
||||
ctx := context.Background()
|
||||
var (
|
||||
namespace = "appcontext-test-ns"
|
||||
acName1 = "applicationconfig1"
|
||||
acName2 = "applicationconfig2"
|
||||
compName1 = "component1"
|
||||
compName2 = "component2"
|
||||
containerName = "test-container"
|
||||
containerImage = "notarealimage"
|
||||
cwName1 = "appcontext-test-cw1"
|
||||
cwName2 = "appcontext-test-cw2"
|
||||
arName1 = "ar1"
|
||||
arName2 = "ar2"
|
||||
appContextName = "appcontext1"
|
||||
traitName1 = "trait1"
|
||||
traitName2 = "trait2"
|
||||
key = types.NamespacedName{Namespace: namespace, Name: appContextName}
|
||||
)
|
||||
var ns = corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: namespace}}
|
||||
|
||||
workload1 := cw(
|
||||
cwWithName(cwName1),
|
||||
cwWithContainers([]v1alpha2.Container{
|
||||
{
|
||||
Name: containerName,
|
||||
Image: containerImage,
|
||||
Command: []string{"sleep", "30s"},
|
||||
Ports: []v1alpha2.ContainerPort{
|
||||
v1alpha2.ContainerPort{
|
||||
Name: "http",
|
||||
Port: 80,
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
)
|
||||
|
||||
rawWorkload1 := runtime.RawExtension{Object: workload1}
|
||||
co1 := comp(
|
||||
compWithName(compName1),
|
||||
compWithNamespace(namespace),
|
||||
compWithWorkload(rawWorkload1),
|
||||
)
|
||||
|
||||
ac1 := ac(
|
||||
acWithName(acName1),
|
||||
acWithNamspace(namespace),
|
||||
acWithComps([]v1alpha2.ApplicationConfigurationComponent{
|
||||
{
|
||||
ComponentName: compName1,
|
||||
Traits: []v1alpha2.ComponentTrait{},
|
||||
},
|
||||
}),
|
||||
)
|
||||
workload2 := cw(
|
||||
cwWithName(cwName2),
|
||||
cwWithContainers([]v1alpha2.Container{
|
||||
{
|
||||
Name: containerName,
|
||||
Image: containerImage,
|
||||
Command: []string{"sleep", "30s"},
|
||||
Ports: []v1alpha2.ContainerPort{
|
||||
v1alpha2.ContainerPort{
|
||||
Name: "http",
|
||||
Port: 80,
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
)
|
||||
rawWorkload2 := runtime.RawExtension{Object: workload2}
|
||||
co2 := comp(
|
||||
compWithName(compName2),
|
||||
compWithNamespace(namespace),
|
||||
compWithWorkload(rawWorkload2),
|
||||
)
|
||||
dummyApp := &v1alpha2.Application{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "dummy",
|
||||
Namespace: namespace,
|
||||
},
|
||||
Spec: v1alpha2.ApplicationSpec{
|
||||
Components: []v1alpha2.ApplicationComponent{},
|
||||
},
|
||||
}
|
||||
ar1 := &v1alpha2.ApplicationRevision{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: arName1,
|
||||
Namespace: namespace,
|
||||
},
|
||||
Spec: v1alpha2.ApplicationRevisionSpec{
|
||||
Components: application.ConvertComponents2RawRevisions([]*v1alpha2.Component{co1}),
|
||||
|
||||
ApplicationConfiguration: util.Object2RawExtension(ac1),
|
||||
Application: *dummyApp,
|
||||
}}
|
||||
trait2 := &v1alpha2.ManualScalerTrait{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: v1alpha2.ManualScalerTraitKind,
|
||||
APIVersion: v1alpha2.SchemeGroupVersion.String(),
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: traitName2,
|
||||
Namespace: namespace,
|
||||
},
|
||||
Spec: v1alpha2.ManualScalerTraitSpec{
|
||||
ReplicaCount: 3,
|
||||
},
|
||||
}
|
||||
rawTrait2 := runtime.RawExtension{Object: trait2}
|
||||
ac2 := ac(
|
||||
acWithName(acName2),
|
||||
acWithNamspace(namespace),
|
||||
acWithComps([]v1alpha2.ApplicationConfigurationComponent{
|
||||
{
|
||||
ComponentName: compName2,
|
||||
Traits: []v1alpha2.ComponentTrait{
|
||||
v1alpha2.ComponentTrait{
|
||||
Trait: rawTrait2,
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
)
|
||||
ar2 := &v1alpha2.ApplicationRevision{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: arName2,
|
||||
Namespace: namespace,
|
||||
},
|
||||
Spec: v1alpha2.ApplicationRevisionSpec{
|
||||
ApplicationConfiguration: util.Object2RawExtension(ac2),
|
||||
Components: application.ConvertComponents2RawRevisions([]*v1alpha2.Component{co2}),
|
||||
Application: *dummyApp,
|
||||
}}
|
||||
appContext := &v1alpha2.ApplicationContext{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: appContextName,
|
||||
Namespace: namespace,
|
||||
},
|
||||
Spec: v1alpha2.ApplicationContextSpec{
|
||||
ApplicationRevisionName: arName1,
|
||||
},
|
||||
}
|
||||
|
||||
BeforeEach(func() {
|
||||
Expect(k8sClient.Create(ctx, &ns)).Should(SatisfyAny(BeNil()))
|
||||
Eventually(
|
||||
func() error {
|
||||
return k8sClient.Get(ctx, types.NamespacedName{Name: namespace}, &ns)
|
||||
},
|
||||
time.Second*3, time.Millisecond*300).Should(BeNil())
|
||||
|
||||
Expect(k8sClient.Create(ctx, co1)).Should(Succeed())
|
||||
Expect(k8sClient.Create(ctx, co2)).Should(Succeed())
|
||||
Expect(k8sClient.Create(ctx, ar1)).Should(Succeed())
|
||||
Expect(k8sClient.Create(ctx, ar2)).Should(Succeed())
|
||||
})
|
||||
|
||||
AfterEach(func() {
|
||||
By("Clean up resources after a test")
|
||||
Expect(k8sClient.Delete(ctx, &ns, client.PropagationPolicy(metav1.DeletePropagationForeground))).Should(Succeed())
|
||||
time.Sleep(15 * time.Second)
|
||||
})
|
||||
|
||||
It("Test appContext reconcile logic ", func() {
|
||||
By("Test AppRevision1 only have 1 workload on trait")
|
||||
Expect(k8sClient.Create(ctx, appContext)).Should(Succeed())
|
||||
updateTime := time.Now()
|
||||
Eventually(func() error {
|
||||
appCtx := new(v1alpha2.ApplicationContext)
|
||||
err := k8sClient.Get(ctx, key, appCtx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
now := time.Now()
|
||||
if now.Sub(updateTime) > 4*time.Second {
|
||||
requestReconcileNow(ctx, appCtx)
|
||||
updateTime = now
|
||||
}
|
||||
if len(appCtx.Status.Workloads) != 1 {
|
||||
return fmt.Errorf("appContext status error:the number of workloads not right")
|
||||
}
|
||||
if appCtx.Status.Workloads[0].ComponentName != compName1 {
|
||||
return fmt.Errorf("appContext status error:the name of component not right, expect %s", compName1)
|
||||
}
|
||||
cw := new(v1alpha2.ContainerizedWorkload)
|
||||
return k8sClient.Get(ctx, types.NamespacedName{Namespace: namespace, Name: cwName1}, cw)
|
||||
}, time.Second*60, time.Millisecond*300).Should(BeNil())
|
||||
|
||||
By("Test revision have both workload and trait , switch AppContext to revision2")
|
||||
Eventually(func() error {
|
||||
updateContext := new(v1alpha2.ApplicationContext)
|
||||
err := k8sClient.Get(ctx, key, updateContext)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
updateContext.Spec.ApplicationRevisionName = arName2
|
||||
err = k8sClient.Update(ctx, updateContext)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}, time.Second*60, time.Microsecond*300).Should(BeNil())
|
||||
updateTime = time.Now()
|
||||
Eventually(func() error {
|
||||
appCtx := new(v1alpha2.ApplicationContext)
|
||||
err := k8sClient.Get(ctx, types.NamespacedName{Namespace: namespace, Name: appContextName}, appCtx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
now := time.Now()
|
||||
if now.Sub(updateTime) > 4*time.Second {
|
||||
requestReconcileNow(ctx, appCtx)
|
||||
updateTime = now
|
||||
}
|
||||
if len(appCtx.Status.Workloads) != 1 {
|
||||
return fmt.Errorf("appContext status error:the number of workloads not right")
|
||||
}
|
||||
if appCtx.Status.Workloads[0].ComponentName != compName2 {
|
||||
return fmt.Errorf("appContext status error:the name of component not right, expect %s", compName2)
|
||||
}
|
||||
cw := new(v1alpha2.ContainerizedWorkload)
|
||||
err = k8sClient.Get(ctx, types.NamespacedName{Namespace: namespace, Name: cwName2}, cw)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot get workload 2 %v", err)
|
||||
}
|
||||
if len(appCtx.Status.Workloads[0].Traits) != 1 {
|
||||
return fmt.Errorf("appContext status error:the number of traits status not right")
|
||||
}
|
||||
mt := new(v1alpha2.ManualScalerTrait)
|
||||
err = k8sClient.Get(ctx, types.NamespacedName{Namespace: namespace, Name: traitName2}, mt)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot get component trait %v", err)
|
||||
}
|
||||
return nil
|
||||
}, time.Second*60, time.Millisecond*300).Should(BeNil())
|
||||
|
||||
By("Test add trait in AppRevision1, and switch context to AppRevision1")
|
||||
|
||||
trait1 := &v1alpha2.ManualScalerTrait{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: v1alpha2.ManualScalerTraitKind,
|
||||
APIVersion: v1alpha2.SchemeGroupVersion.String(),
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: traitName1,
|
||||
Namespace: namespace,
|
||||
},
|
||||
Spec: v1alpha2.ManualScalerTraitSpec{
|
||||
ReplicaCount: 2,
|
||||
},
|
||||
}
|
||||
rawTrait1 := runtime.RawExtension{Object: trait1}
|
||||
ac1.Spec.Components[0].Traits = []v1alpha2.ComponentTrait{
|
||||
v1alpha2.ComponentTrait{
|
||||
Trait: rawTrait1,
|
||||
},
|
||||
}
|
||||
Expect(k8sClient.Get(ctx, types.NamespacedName{Namespace: namespace, Name: arName1}, ar1)).Should(BeNil())
|
||||
ar1.Spec.ApplicationConfiguration = util.Object2RawExtension(ac1)
|
||||
Expect(k8sClient.Update(ctx, ar1)).Should(Succeed())
|
||||
Eventually(func() error {
|
||||
updateContext := new(v1alpha2.ApplicationContext)
|
||||
err := k8sClient.Get(ctx, key, updateContext)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
updateContext.Spec.ApplicationRevisionName = arName1
|
||||
err = k8sClient.Update(ctx, updateContext)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}, time.Second*60, time.Microsecond*300).Should(BeNil())
|
||||
Eventually(func() error {
|
||||
mt := new(v1alpha2.ManualScalerTrait)
|
||||
err := k8sClient.Get(ctx, types.NamespacedName{Namespace: namespace, Name: traitName1}, mt)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if mt.Spec.ReplicaCount != 2 {
|
||||
return fmt.Errorf("repica number missmatch , actual: %d", mt.Spec.ReplicaCount)
|
||||
}
|
||||
return nil
|
||||
}, time.Second*60, time.Millisecond*300).Should(BeNil())
|
||||
ac1.Spec.Components[0].Traits = []v1alpha2.ComponentTrait{}
|
||||
|
||||
By("Test delete trait in AppRevision2, and switch context to AppRevision2")
|
||||
Expect(k8sClient.Get(ctx, types.NamespacedName{Namespace: namespace, Name: arName2}, ar2)).Should(BeNil())
|
||||
ac2.Spec.Components[0].Traits = []v1alpha2.ComponentTrait{}
|
||||
ar1.Spec.ApplicationConfiguration = util.Object2RawExtension(ac2)
|
||||
Expect(k8sClient.Update(ctx, ar2)).Should(BeNil())
|
||||
Eventually(func() error {
|
||||
updateContext := new(v1alpha2.ApplicationContext)
|
||||
err := k8sClient.Get(ctx, key, updateContext)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
updateContext.Spec.ApplicationRevisionName = arName2
|
||||
err = k8sClient.Update(ctx, updateContext)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}, time.Second*60, time.Microsecond*300).Should(BeNil())
|
||||
Eventually(func() error {
|
||||
mt := new(v1alpha2.ManualScalerTrait)
|
||||
return k8sClient.Get(ctx, types.NamespacedName{Namespace: namespace, Name: traitName2}, mt)
|
||||
}, time.Second*60, time.Millisecond*300).Should(util.NotFoundMatcher{})
|
||||
})
|
||||
})
|
||||
368
test/e2e-test/appctx_compatibility_test.go
Normal file
368
test/e2e-test/appctx_compatibility_test.go
Normal file
@@ -0,0 +1,368 @@
|
||||
/*
|
||||
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"
|
||||
"time"
|
||||
|
||||
"github.com/crossplane/crossplane-runtime/apis/core/v1alpha1"
|
||||
"github.com/crossplane/crossplane-runtime/pkg/meta"
|
||||
"github.com/ghodss/yaml"
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/kind/pkg/errors"
|
||||
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/utils/pointer"
|
||||
|
||||
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha2"
|
||||
"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/apply"
|
||||
)
|
||||
|
||||
// For legacy clusters that use appContext to create/update resources, we should guarantee backward compatibility while we
|
||||
// deprecate appContext and replace it with assemble/dispatch modules.
|
||||
// This test is to simulate a scenario where a cluster has an application whose resources are already created and owned
|
||||
// by appContext and resource tracker(for cx-ns), and once we create a new application whose resources are same as
|
||||
// existing ones, existing resources's ctrl-owner should be changed from appContext to resource tracker.
|
||||
var _ = Describe("Test compatibility for deprecation of appContext", func() {
|
||||
ctx := context.Background()
|
||||
var namespaceName string
|
||||
var ns corev1.Namespace
|
||||
|
||||
BeforeEach(func() {
|
||||
namespaceName = randomNamespaceName("deprecation-appctx-test")
|
||||
ns = corev1.Namespace{}
|
||||
ns.SetName(namespaceName)
|
||||
Expect(k8sClient.Create(ctx, &ns)).Should(Succeed())
|
||||
_, err := createFromYAML(ctx, pvTraitDefinition, namespaceName, nil)
|
||||
Expect(err).Should(BeNil())
|
||||
})
|
||||
|
||||
AfterEach(func() {
|
||||
Expect(k8sClient.Delete(ctx, &ns)).Should(Succeed())
|
||||
Expect(k8sClient.DeleteAllOf(ctx, &v1beta1.ResourceTracker{})).Should(Succeed())
|
||||
Expect(k8sClient.DeleteAllOf(ctx, &corev1.PersistentVolume{})).Should(Succeed())
|
||||
})
|
||||
|
||||
It("Test application can update its resources' owners", func() {
|
||||
var err error
|
||||
var appCtxKey, rtKey *client.ObjectKey
|
||||
|
||||
By("Mock existing owners in a legacy cluster")
|
||||
appCtxKey, err = createFromYAML(ctx, legacyAppCtx, namespaceName, nil)
|
||||
Expect(err).Should(BeNil())
|
||||
rtKey, err = createFromYAML(ctx, legacyResourceTracker, namespaceName, nil)
|
||||
Expect(err).Should(BeNil())
|
||||
By("Mock owner references: appCtx owns Deployment and Service")
|
||||
appCtx := &v1alpha2.ApplicationContext{}
|
||||
Expect(k8sClient.Get(ctx, *appCtxKey, appCtx)).Should(Succeed())
|
||||
appCtxOwnRef := meta.AsController(&v1alpha1.TypedReference{
|
||||
APIVersion: "core.oam.dev/v1alpha2",
|
||||
Kind: "ApplicationContext",
|
||||
Name: appCtx.GetName(),
|
||||
UID: appCtx.GetUID(),
|
||||
})
|
||||
|
||||
By("Mock owner references: rscTracker owns PersistentVolume")
|
||||
rt := &v1beta1.ResourceTracker{}
|
||||
Expect(k8sClient.Get(ctx, *rtKey, rt)).Should(Succeed())
|
||||
rtOwnerRef := meta.AsController(&v1alpha1.TypedReference{
|
||||
APIVersion: "core.oam.dev/v1beta1",
|
||||
Kind: "ResourceTracker",
|
||||
Name: rt.GetName(),
|
||||
UID: rt.GetUID(),
|
||||
})
|
||||
|
||||
var deployKey, svcKey, pvKey *client.ObjectKey
|
||||
By("Mock existing resources in a legacy cluster")
|
||||
deployKey, err = createFromYAML(ctx, legacyDeploy, namespaceName, &appCtxOwnRef)
|
||||
Expect(err).Should(BeNil())
|
||||
svcKey, err = createFromYAML(ctx, legacyService, namespaceName, &appCtxOwnRef)
|
||||
Expect(err).Should(BeNil())
|
||||
pvKey, err = createFromYAML(ctx, legacyPersistentVolume, namespaceName, &rtOwnerRef)
|
||||
Expect(err).Should(BeNil())
|
||||
By("Create an application")
|
||||
_, err = createFromYAML(ctx, newApplication, namespaceName, nil)
|
||||
Expect(err).Should(BeNil())
|
||||
|
||||
By("Wait for new resource tracker is created")
|
||||
Eventually(func() error {
|
||||
rt = &v1beta1.ResourceTracker{}
|
||||
if err := k8sClient.Get(ctx, client.ObjectKey{Name: "myapp-v1-" + namespaceName}, rt); err != nil {
|
||||
return errors.Wrap(err, "cannot get new resource tracker")
|
||||
}
|
||||
return nil
|
||||
}, 10*time.Second, 500*time.Millisecond).Should(Succeed())
|
||||
wantNewOwner := metav1.OwnerReference{
|
||||
APIVersion: "core.oam.dev/v1beta1",
|
||||
Kind: "ResourceTracker",
|
||||
Name: rt.GetName(),
|
||||
UID: rt.GetUID(),
|
||||
Controller: pointer.BoolPtr(true),
|
||||
BlockOwnerDeletion: pointer.BoolPtr(true),
|
||||
}
|
||||
|
||||
By("Verify existing resources' new owners")
|
||||
deploy := &appsv1.Deployment{}
|
||||
Expect(k8sClient.Get(ctx, *deployKey, deploy)).Should(Succeed())
|
||||
newDeployOwner := metav1.GetControllerOf(deploy)
|
||||
Expect(newDeployOwner).ShouldNot(BeNil())
|
||||
Expect(*newDeployOwner).Should(BeEquivalentTo(wantNewOwner))
|
||||
|
||||
svc := &corev1.Service{}
|
||||
Expect(k8sClient.Get(ctx, *svcKey, svc)).Should(Succeed())
|
||||
newSvcOwner := metav1.GetControllerOf(svc)
|
||||
Expect(newSvcOwner).ShouldNot(BeNil())
|
||||
Expect(*newSvcOwner).Should(Equal(wantNewOwner))
|
||||
|
||||
pv := &corev1.PersistentVolume{}
|
||||
Expect(k8sClient.Get(ctx, *pvKey, pv)).Should(Succeed())
|
||||
newPVOwner := metav1.GetControllerOf(svc)
|
||||
Expect(newPVOwner).ShouldNot(BeNil())
|
||||
Expect(*newPVOwner).Should(Equal(wantNewOwner))
|
||||
|
||||
By("Delete the application")
|
||||
app := &v1beta1.Application{}
|
||||
app.SetName("myapp")
|
||||
app.SetNamespace(namespaceName)
|
||||
Expect(k8sClient.Delete(ctx, app)).Should(Succeed())
|
||||
|
||||
By("Verify all resources can be deleted")
|
||||
Eventually(func() error {
|
||||
return k8sClient.Get(ctx, client.ObjectKey{Name: "myapp-v1-" + namespaceName}, rt)
|
||||
}, 10*time.Second, 500*time.Millisecond).Should(util.NotFoundMatcher{})
|
||||
Eventually(func() error {
|
||||
return k8sClient.Get(ctx, *deployKey, deploy)
|
||||
}, 30*time.Second, 500*time.Millisecond).Should(util.NotFoundMatcher{})
|
||||
Eventually(func() error {
|
||||
return k8sClient.Get(ctx, *svcKey, svc)
|
||||
}, 30*time.Second, 500*time.Millisecond).Should(util.NotFoundMatcher{})
|
||||
Eventually(func() error {
|
||||
return k8sClient.Get(ctx, *pvKey, pv)
|
||||
}, 30*time.Second, 500*time.Millisecond).Should(util.NotFoundMatcher{})
|
||||
})
|
||||
|
||||
It("Test delete an application with a legacy finalizer", func() {
|
||||
var err error
|
||||
var rtKey *client.ObjectKey
|
||||
// simulate a resource tracker created by a legacy application
|
||||
rtKey, err = createFromYAML(ctx, legacyResourceTracker, namespaceName, nil)
|
||||
Expect(err).Should(BeNil())
|
||||
|
||||
By("Create the application")
|
||||
app := &v1beta1.Application{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "myapp",
|
||||
Namespace: namespaceName,
|
||||
},
|
||||
Spec: v1beta1.ApplicationSpec{
|
||||
Components: []v1beta1.ApplicationComponent{{
|
||||
Name: "mycomp",
|
||||
Type: "worker",
|
||||
Properties: runtime.RawExtension{Raw: []byte(`{"cmd":["sleep","1000"],"image":"busybox"}`)},
|
||||
}},
|
||||
},
|
||||
}
|
||||
app.SetFinalizers([]string{
|
||||
// this finalizer only apperars in a legacy application
|
||||
// this case is to test whether a legacy application with this finalizer can be deleted
|
||||
"resourceTracker.finalizer.core.oam.dev",
|
||||
})
|
||||
Expect(k8sClient.Create(ctx, app.DeepCopy())).Should(Succeed())
|
||||
|
||||
By("Delete the application")
|
||||
Expect(k8sClient.Delete(ctx, app)).Should(Succeed())
|
||||
|
||||
By("Verify legacy resource tracker is deleted")
|
||||
Eventually(func() error {
|
||||
return k8sClient.Get(ctx, client.ObjectKey{Name: rtKey.Name}, &v1beta1.ResourceTracker{})
|
||||
}, 10*time.Second, 500*time.Millisecond).Should(util.NotFoundMatcher{})
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
var createFromYAML = func(ctx context.Context, objYAML string, ns string, owner *metav1.OwnerReference) (*client.ObjectKey, error) {
|
||||
u := &unstructured.Unstructured{}
|
||||
if err := yaml.Unmarshal([]byte(fmt.Sprintf(objYAML, ns)), u); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if owner != nil {
|
||||
u.SetOwnerReferences([]metav1.OwnerReference{*owner})
|
||||
}
|
||||
objKey := client.ObjectKey{
|
||||
Name: u.GetName(),
|
||||
Namespace: ns,
|
||||
}
|
||||
// use apply.Applicator to simulate real scenario
|
||||
applicator := apply.NewAPIApplicator(k8sClient)
|
||||
if err := applicator.Apply(ctx, u); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &objKey, nil
|
||||
}
|
||||
|
||||
var (
|
||||
legacyDeploy = `apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
labels:
|
||||
app.oam.dev/app-revision-hash: 3dc894b5cb767c4b
|
||||
app.oam.dev/appRevision: myapp-v1
|
||||
app.oam.dev/component: myworker
|
||||
app.oam.dev/name: myapp
|
||||
app.oam.dev/resourceType: WORKLOAD
|
||||
app.oam.dev/revision: myworker-v1
|
||||
workload.oam.dev/type: worker
|
||||
name: myworker
|
||||
namespace: %s
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
app.oam.dev/component: myworker
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app.oam.dev/component: myworker
|
||||
spec:
|
||||
containers:
|
||||
- image: nginx:latest
|
||||
name: myworker`
|
||||
|
||||
legacyService = `apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
labels:
|
||||
app.oam.dev/app-revision-hash: 3dc894b5cb767c4b
|
||||
app.oam.dev/appRevision: myapp-v1
|
||||
app.oam.dev/component: myworker
|
||||
app.oam.dev/name: myapp
|
||||
app.oam.dev/resourceType: TRAIT
|
||||
app.oam.dev/revision: myworker-v1
|
||||
trait.oam.dev/resource: service
|
||||
trait.oam.dev/type: ingress
|
||||
name: myworker
|
||||
namespace: %s
|
||||
spec:
|
||||
ports:
|
||||
- port: 8080
|
||||
protocol: TCP
|
||||
targetPort: 8080
|
||||
selector:
|
||||
app.oam.dev/component: myworker
|
||||
type: ClusterIP`
|
||||
|
||||
legacyPersistentVolume = `apiVersion: v1
|
||||
kind: PersistentVolume
|
||||
metadata:
|
||||
labels:
|
||||
app.oam.dev/appRevision: myapp-v1
|
||||
app.oam.dev/component: myworker
|
||||
app.oam.dev/name: myapp
|
||||
app.oam.dev/resourceType: TRAIT
|
||||
app.oam.dev/revision: myworker-v1
|
||||
trait.oam.dev/resource: pv
|
||||
trait.oam.dev/type: testpv
|
||||
name: csi-gcs-pv-myworker
|
||||
namespace: %s
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
capacity:
|
||||
storage: 5Gi
|
||||
nfs:
|
||||
server: 1.1.1.1
|
||||
path: "/"
|
||||
persistentVolumeReclaimPolicy: Retain
|
||||
storageClassName: csi-gcs-test-sc`
|
||||
|
||||
legacyAppCtx = `apiVersion: core.oam.dev/v1alpha2
|
||||
kind: ApplicationContext
|
||||
metadata:
|
||||
labels:
|
||||
app.oam.dev/app-revision-hash: 3dc894b5cb767c4b
|
||||
name: myapp
|
||||
namespace: %s
|
||||
spec:
|
||||
applicationRevisionName: myapp-v1`
|
||||
|
||||
legacyResourceTracker = `apiVersion: core.oam.dev/v1beta1
|
||||
kind: ResourceTracker
|
||||
metadata:
|
||||
name: %s-myapp`
|
||||
|
||||
newApplication = `apiVersion: core.oam.dev/v1beta1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: myapp
|
||||
namespace: %s
|
||||
spec:
|
||||
components:
|
||||
- name: myworker
|
||||
type: worker
|
||||
properties:
|
||||
image: "nginx:latest"
|
||||
traits:
|
||||
- type: ingress
|
||||
properties:
|
||||
domain: localhost
|
||||
http:
|
||||
"/": 8080
|
||||
- type: testpv
|
||||
properties:
|
||||
secretName: testSecret`
|
||||
|
||||
pvTraitDefinition = `apiVersion: core.oam.dev/v1beta1
|
||||
kind: TraitDefinition
|
||||
metadata:
|
||||
name: testpv
|
||||
namespace: %s
|
||||
annotations:
|
||||
definition.oam.dev/description: Mock a cluster-scope resource
|
||||
spec:
|
||||
schematic:
|
||||
cue:
|
||||
template: |
|
||||
parameter: {
|
||||
secretName: string
|
||||
}
|
||||
outputs: {
|
||||
pv: {
|
||||
apiVersion: "v1"
|
||||
kind: "PersistentVolume"
|
||||
metadata: name: "csi-gcs-pv-\(context.name)"
|
||||
spec: {
|
||||
accessModes: ["ReadWriteOnce"]
|
||||
capacity: storage: "5Gi"
|
||||
persistentVolumeReclaimPolicy: "Retain"
|
||||
storageClassName: "csi-gcs-test-sc"
|
||||
nfs: {
|
||||
server: "1.1.1.1"
|
||||
path: "/"
|
||||
}
|
||||
}
|
||||
}
|
||||
}`
|
||||
)
|
||||
@@ -24,6 +24,7 @@ import (
|
||||
"github.com/ghodss/yaml"
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
"github.com/pkg/errors"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
batchv1 "k8s.io/api/batch/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
@@ -33,7 +34,6 @@ import (
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
"github.com/oam-dev/kubevela/apis/core.oam.dev/common"
|
||||
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha2"
|
||||
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
|
||||
"github.com/oam-dev/kubevela/pkg/oam/util"
|
||||
)
|
||||
@@ -198,26 +198,15 @@ var _ = Describe("Test application of the specified definition version", func()
|
||||
By("Create application")
|
||||
Expect(k8sClient.Create(ctx, &app)).Should(Succeed())
|
||||
|
||||
ac := &v1alpha2.ApplicationContext{}
|
||||
acName := appName
|
||||
By("Verify the ApplicationContext is created & reconciled successfully")
|
||||
Eventually(func() bool {
|
||||
if err := k8sClient.Get(ctx, client.ObjectKey{Name: acName, Namespace: namespace}, ac); err != nil {
|
||||
return false
|
||||
}
|
||||
return len(ac.Status.Workloads) > 0
|
||||
}, 60*time.Second, time.Second).Should(BeTrue())
|
||||
|
||||
By("Verify the workload(deployment) is created successfully")
|
||||
Expect(len(ac.Status.Workloads)).Should(Equal(len(app.Spec.Components)))
|
||||
webServiceDeploy := &appsv1.Deployment{}
|
||||
deployName := ac.Status.Workloads[0].Reference.Name
|
||||
deployName := comp1Name
|
||||
Eventually(func() error {
|
||||
return k8sClient.Get(ctx, client.ObjectKey{Name: deployName, Namespace: namespace}, webServiceDeploy)
|
||||
}, 30*time.Second, 3*time.Second).Should(Succeed())
|
||||
|
||||
workerDeploy := &appsv1.Deployment{}
|
||||
deployName = ac.Status.Workloads[1].Reference.Name
|
||||
deployName = comp2Name
|
||||
Eventually(func() error {
|
||||
return k8sClient.Get(ctx, client.ObjectKey{Name: deployName, Namespace: namespace}, workerDeploy)
|
||||
}, 30*time.Second, 3*time.Second).Should(Succeed())
|
||||
@@ -264,25 +253,29 @@ var _ = Describe("Test application of the specified definition version", func()
|
||||
}
|
||||
Expect(k8sClient.Patch(ctx, &app, client.Merge)).Should(Succeed())
|
||||
|
||||
By("Verify the ApplicationContext is update successfully")
|
||||
Eventually(func() bool {
|
||||
if err := k8sClient.Get(ctx, client.ObjectKey{Name: acName, Namespace: namespace}, ac); err != nil {
|
||||
return false
|
||||
By("Wait for dispatching v2 resources successfully")
|
||||
Eventually(func() error {
|
||||
requestReconcileNow(ctx, &app)
|
||||
rt := &v1beta1.ResourceTracker{}
|
||||
if err := k8sClient.Get(ctx, client.ObjectKey{Name: fmt.Sprintf("%s-v2-%s", appName, namespace)}, rt); err != nil {
|
||||
return err
|
||||
}
|
||||
return ac.Generation == 2
|
||||
}, 10*time.Second, time.Second).Should(BeTrue())
|
||||
if len(rt.Status.TrackedResources) != 0 {
|
||||
return nil
|
||||
}
|
||||
return errors.New("v2 resources have not been dispatched")
|
||||
}, 10*time.Second, 500*time.Millisecond).Should(Succeed())
|
||||
|
||||
By("Verify the workload(deployment) is created successfully")
|
||||
Expect(len(ac.Status.Workloads)).Should(Equal(len(app.Spec.Components)))
|
||||
webServiceV1Deploy := &appsv1.Deployment{}
|
||||
deployName = ac.Status.Workloads[0].Reference.Name
|
||||
deployName = comp1Name
|
||||
Eventually(func() error {
|
||||
return k8sClient.Get(ctx, client.ObjectKey{Name: deployName, Namespace: namespace}, webServiceV1Deploy)
|
||||
}, 30*time.Second, 3*time.Second).Should(Succeed())
|
||||
|
||||
By("Verify the workload(job) is created successfully")
|
||||
workerJob := &batchv1.Job{}
|
||||
jobName := ac.Status.Workloads[1].Reference.Name
|
||||
jobName := comp2Name
|
||||
Eventually(func() error {
|
||||
return k8sClient.Get(ctx, client.ObjectKey{Name: jobName, Namespace: namespace}, workerJob)
|
||||
}, 30*time.Second, 3*time.Second).Should(Succeed())
|
||||
@@ -417,13 +410,6 @@ var _ = Describe("Test application of the specified definition version", func()
|
||||
By("Create application")
|
||||
Expect(k8sClient.Create(ctx, &app)).Should(Succeed())
|
||||
|
||||
ac := &v1alpha2.ApplicationContext{}
|
||||
acName := appName
|
||||
By("Verify the ApplicationContext is created successfully")
|
||||
Eventually(func() error {
|
||||
return k8sClient.Get(ctx, client.ObjectKey{Name: acName, Namespace: namespace}, ac)
|
||||
}, 30*time.Second, time.Second).Should(Succeed())
|
||||
|
||||
By("Verify the workload(deployment) is created successfully by Helm")
|
||||
deploy := &appsv1.Deployment{}
|
||||
deployName := fmt.Sprintf("%s-%s-podinfo", appName, compName)
|
||||
@@ -438,7 +424,6 @@ var _ = Describe("Test application of the specified definition version", func()
|
||||
|
||||
By("Verify trait is applied to the workload")
|
||||
Eventually(func() bool {
|
||||
requestReconcileNow(ctx, ac)
|
||||
deploy := &appsv1.Deployment{}
|
||||
if err := k8sClient.Get(ctx, client.ObjectKey{Name: deployName, Namespace: namespace}, deploy); err != nil {
|
||||
return false
|
||||
@@ -471,15 +456,6 @@ var _ = Describe("Test application of the specified definition version", func()
|
||||
By("Create application")
|
||||
Expect(k8sClient.Patch(ctx, &app, client.Merge)).Should(Succeed())
|
||||
|
||||
By("Verify the ApplicationContext is updated")
|
||||
Eventually(func() bool {
|
||||
ac = &v1alpha2.ApplicationContext{}
|
||||
if err := k8sClient.Get(ctx, client.ObjectKey{Name: acName, Namespace: namespace}, ac); err != nil {
|
||||
return false
|
||||
}
|
||||
return ac.GetGeneration() == 2
|
||||
}, 15*time.Second, 3*time.Second).Should(BeTrue())
|
||||
|
||||
By("Verify the workload(deployment) is update successfully by Helm")
|
||||
deploy = &appsv1.Deployment{}
|
||||
Eventually(func() bool {
|
||||
@@ -589,19 +565,9 @@ var _ = Describe("Test application of the specified definition version", func()
|
||||
By("Create application")
|
||||
Expect(k8sClient.Create(ctx, &app)).Should(Succeed())
|
||||
|
||||
ac := &v1alpha2.ApplicationContext{}
|
||||
acName := appName
|
||||
By("Verify the ApplicationContext is created & reconciled successfully")
|
||||
Eventually(func() bool {
|
||||
if err := k8sClient.Get(ctx, client.ObjectKey{Name: acName, Namespace: namespace}, ac); err != nil {
|
||||
return false
|
||||
}
|
||||
return len(ac.Status.Workloads) > 0
|
||||
}, 60*time.Second, time.Second).Should(BeTrue())
|
||||
|
||||
By("Verify the workload(job) is created successfully")
|
||||
job := &batchv1.Job{}
|
||||
jobName := ac.Status.Workloads[0].Reference.Name
|
||||
jobName := compName
|
||||
Eventually(func() error {
|
||||
return k8sClient.Get(ctx, client.ObjectKey{Name: jobName, Namespace: namespace}, job)
|
||||
}, 30*time.Second, 3*time.Second).Should(Succeed())
|
||||
@@ -640,18 +606,9 @@ var _ = Describe("Test application of the specified definition version", func()
|
||||
}
|
||||
Expect(k8sClient.Patch(ctx, &app, client.Merge)).Should(Succeed())
|
||||
|
||||
By("Verify the ApplicationContext is update successfully")
|
||||
Eventually(func() bool {
|
||||
if err := k8sClient.Get(ctx, client.ObjectKey{Name: acName, Namespace: namespace}, ac); err != nil {
|
||||
return false
|
||||
}
|
||||
return ac.Generation == 2
|
||||
}, 10*time.Second, time.Second).Should(BeTrue())
|
||||
|
||||
By("Verify the workload(deployment) is created successfully")
|
||||
Expect(len(ac.Status.Workloads)).Should(Equal(len(app.Spec.Components)))
|
||||
deploy := &appsv1.Deployment{}
|
||||
deployName := ac.Status.Workloads[0].Reference.Name
|
||||
deployName := compName
|
||||
Eventually(func() error {
|
||||
return k8sClient.Get(ctx, client.ObjectKey{Name: deployName, Namespace: namespace}, deploy)
|
||||
}, 30*time.Second, 3*time.Second).Should(Succeed())
|
||||
|
||||
@@ -29,7 +29,7 @@ import (
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
"github.com/oam-dev/kubevela/apis/core.oam.dev/common"
|
||||
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha2"
|
||||
v1beta1 "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
|
||||
"github.com/oam-dev/kubevela/pkg/oam/util"
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
@@ -46,7 +46,7 @@ var _ = Describe("Test application containing helm module", func() {
|
||||
tdName = "virtualgroup"
|
||||
)
|
||||
var namespace string
|
||||
var app v1alpha2.Application
|
||||
var app v1beta1.Application
|
||||
var ns corev1.Namespace
|
||||
|
||||
BeforeEach(func() {
|
||||
@@ -58,7 +58,7 @@ var _ = Describe("Test application containing helm module", func() {
|
||||
},
|
||||
time.Second*3, time.Millisecond*300).Should(SatisfyAny(BeNil(), &util.AlreadyExistMatcher{}))
|
||||
|
||||
cd := v1alpha2.ComponentDefinition{}
|
||||
cd := v1beta1.ComponentDefinition{}
|
||||
cd.SetName(cdName)
|
||||
cd.SetNamespace(namespace)
|
||||
cd.Spec.Workload.Definition = common.WorkloadGVK{APIVersion: "apps/v1", Kind: "Deployment"}
|
||||
@@ -80,7 +80,7 @@ var _ = Describe("Test application containing helm module", func() {
|
||||
Expect(k8sClient.Create(ctx, &cd)).Should(Succeed())
|
||||
|
||||
By("Install a patch trait used to test CUE module")
|
||||
td := v1alpha2.TraitDefinition{}
|
||||
td := v1beta1.TraitDefinition{}
|
||||
td.SetName(tdName)
|
||||
td.SetNamespace(namespace)
|
||||
td.Spec.AppliesToWorkloads = []string{"deployments.apps"}
|
||||
@@ -107,7 +107,7 @@ var _ = Describe("Test application containing helm module", func() {
|
||||
Expect(k8sClient.Create(ctx, &td)).Should(Succeed())
|
||||
|
||||
By("Add 'deployments.apps' to scaler's appliesToWorkloads")
|
||||
scalerTd := v1alpha2.TraitDefinition{}
|
||||
scalerTd := v1beta1.TraitDefinition{}
|
||||
Expect(k8sClient.Get(ctx, client.ObjectKey{Name: "scaler", Namespace: "vela-system"}, &scalerTd)).Should(Succeed())
|
||||
scalerTd.Spec.AppliesToWorkloads = []string{"deployments.apps", "webservice", "worker"}
|
||||
scalerTd.SetResourceVersion("")
|
||||
@@ -116,15 +116,15 @@ var _ = Describe("Test application containing helm module", func() {
|
||||
|
||||
AfterEach(func() {
|
||||
By("Clean up resources after a test")
|
||||
k8sClient.DeleteAllOf(ctx, &v1alpha2.Application{}, client.InNamespace(namespace))
|
||||
k8sClient.DeleteAllOf(ctx, &v1alpha2.ComponentDefinition{}, client.InNamespace(namespace))
|
||||
k8sClient.DeleteAllOf(ctx, &v1alpha2.WorkloadDefinition{}, client.InNamespace(namespace))
|
||||
k8sClient.DeleteAllOf(ctx, &v1alpha2.TraitDefinition{}, client.InNamespace(namespace))
|
||||
k8sClient.DeleteAllOf(ctx, &v1beta1.Application{}, client.InNamespace(namespace))
|
||||
k8sClient.DeleteAllOf(ctx, &v1beta1.ComponentDefinition{}, client.InNamespace(namespace))
|
||||
k8sClient.DeleteAllOf(ctx, &v1beta1.WorkloadDefinition{}, client.InNamespace(namespace))
|
||||
k8sClient.DeleteAllOf(ctx, &v1beta1.TraitDefinition{}, client.InNamespace(namespace))
|
||||
By(fmt.Sprintf("Delete the entire namespaceName %s", ns.Name))
|
||||
Expect(k8sClient.Delete(ctx, &ns, client.PropagationPolicy(metav1.DeletePropagationForeground))).Should(Succeed())
|
||||
|
||||
By("Remove 'deployments.apps' from scaler's appliesToWorkloads")
|
||||
scalerTd := v1alpha2.TraitDefinition{}
|
||||
scalerTd := v1beta1.TraitDefinition{}
|
||||
Expect(k8sClient.Get(ctx, client.ObjectKey{Name: "scaler", Namespace: "vela-system"}, &scalerTd)).Should(Succeed())
|
||||
scalerTd.Spec.AppliesToWorkloads = []string{"webservice", "worker"}
|
||||
scalerTd.SetResourceVersion("")
|
||||
@@ -132,30 +132,30 @@ var _ = Describe("Test application containing helm module", func() {
|
||||
})
|
||||
|
||||
It("Test deploy an application containing helm module", func() {
|
||||
app = v1alpha2.Application{
|
||||
app = v1beta1.Application{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: appName,
|
||||
Namespace: namespace,
|
||||
},
|
||||
Spec: v1alpha2.ApplicationSpec{
|
||||
Components: []v1alpha2.ApplicationComponent{
|
||||
Spec: v1beta1.ApplicationSpec{
|
||||
Components: []v1beta1.ApplicationComponent{
|
||||
{
|
||||
Name: compName,
|
||||
WorkloadType: cdName,
|
||||
Settings: util.Object2RawExtension(map[string]interface{}{
|
||||
Name: compName,
|
||||
Type: cdName,
|
||||
Properties: util.Object2RawExtension(map[string]interface{}{
|
||||
"image": map[string]interface{}{
|
||||
"tag": "5.1.2",
|
||||
},
|
||||
}),
|
||||
Traits: []v1alpha2.ApplicationTrait{
|
||||
Traits: []v1beta1.ApplicationTrait{
|
||||
{
|
||||
Name: "scaler",
|
||||
Type: "scaler",
|
||||
Properties: util.Object2RawExtension(map[string]interface{}{
|
||||
"replicas": 2,
|
||||
}),
|
||||
},
|
||||
{
|
||||
Name: tdName,
|
||||
Type: tdName,
|
||||
Properties: util.Object2RawExtension(map[string]interface{}{
|
||||
"group": "my-group",
|
||||
"type": "cluster",
|
||||
@@ -169,13 +169,6 @@ var _ = Describe("Test application containing helm module", func() {
|
||||
By("Create application")
|
||||
Expect(k8sClient.Create(ctx, &app)).Should(Succeed())
|
||||
|
||||
ac := &v1alpha2.ApplicationContext{}
|
||||
acName := appName
|
||||
By("Verify the ApplicationContext is created successfully")
|
||||
Eventually(func() error {
|
||||
return k8sClient.Get(ctx, client.ObjectKey{Name: acName, Namespace: namespace}, ac)
|
||||
}, 30*time.Second, time.Second).Should(Succeed())
|
||||
|
||||
By("Verify the workload(deployment) is created successfully by Helm")
|
||||
deploy := &appsv1.Deployment{}
|
||||
deployName := fmt.Sprintf("%s-%s-podinfo", appName, compName)
|
||||
@@ -185,7 +178,6 @@ var _ = Describe("Test application containing helm module", func() {
|
||||
|
||||
By("Verify two traits are applied to the workload")
|
||||
Eventually(func() bool {
|
||||
requestReconcileNow(ctx, ac)
|
||||
deploy := &appsv1.Deployment{}
|
||||
if err := k8sClient.Get(ctx, client.ObjectKey{Name: deployName, Namespace: namespace}, deploy); err != nil {
|
||||
return false
|
||||
@@ -206,30 +198,30 @@ var _ = Describe("Test application containing helm module", func() {
|
||||
}, 120*time.Second, 10*time.Second).Should(BeTrue())
|
||||
|
||||
By("Update the application")
|
||||
app = v1alpha2.Application{
|
||||
app = v1beta1.Application{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: appName,
|
||||
Namespace: namespace,
|
||||
},
|
||||
Spec: v1alpha2.ApplicationSpec{
|
||||
Components: []v1alpha2.ApplicationComponent{
|
||||
Spec: v1beta1.ApplicationSpec{
|
||||
Components: []v1beta1.ApplicationComponent{
|
||||
{
|
||||
Name: compName,
|
||||
WorkloadType: cdName,
|
||||
Settings: util.Object2RawExtension(map[string]interface{}{
|
||||
Name: compName,
|
||||
Type: cdName,
|
||||
Properties: util.Object2RawExtension(map[string]interface{}{
|
||||
"image": map[string]interface{}{
|
||||
"tag": "5.1.3", // change 5.1.4 => 5.1.3
|
||||
},
|
||||
}),
|
||||
Traits: []v1alpha2.ApplicationTrait{
|
||||
Traits: []v1beta1.ApplicationTrait{
|
||||
{
|
||||
Name: "scaler",
|
||||
Type: "scaler",
|
||||
Properties: util.Object2RawExtension(map[string]interface{}{
|
||||
"replicas": 3, // change 2 => 3
|
||||
}),
|
||||
},
|
||||
{
|
||||
Name: tdName,
|
||||
Type: tdName,
|
||||
Properties: util.Object2RawExtension(map[string]interface{}{
|
||||
"group": "my-group-0", // change my-group => my-group-0
|
||||
"type": "cluster",
|
||||
@@ -242,19 +234,8 @@ var _ = Describe("Test application containing helm module", func() {
|
||||
}
|
||||
Expect(k8sClient.Patch(ctx, &app, client.Merge)).Should(Succeed())
|
||||
|
||||
By("Verify the ApplicationContext is updated")
|
||||
deploy = &appsv1.Deployment{}
|
||||
Eventually(func() bool {
|
||||
ac = &v1alpha2.ApplicationContext{}
|
||||
if err := k8sClient.Get(ctx, client.ObjectKey{Name: acName, Namespace: namespace}, ac); err != nil {
|
||||
return false
|
||||
}
|
||||
return ac.GetGeneration() == 2
|
||||
}, 15*time.Second, 3*time.Second).Should(BeTrue())
|
||||
|
||||
By("Verify the changes are applied to the workload")
|
||||
Eventually(func() bool {
|
||||
requestReconcileNow(ctx, ac)
|
||||
deploy := &appsv1.Deployment{}
|
||||
if err := k8sClient.Get(ctx, client.ObjectKey{Name: deployName, Namespace: namespace}, deploy); err != nil {
|
||||
return false
|
||||
@@ -277,7 +258,7 @@ var _ = Describe("Test application containing helm module", func() {
|
||||
|
||||
It("Test deploy an application containing helm module defined by workloadDefinition", func() {
|
||||
|
||||
workloaddef := v1alpha2.WorkloadDefinition{}
|
||||
workloaddef := v1beta1.WorkloadDefinition{}
|
||||
workloaddef.SetName(wdName)
|
||||
workloaddef.SetNamespace(namespace)
|
||||
workloaddef.Spec.Reference = common.DefinitionReference{Name: "deployments.apps", Version: "v1"}
|
||||
@@ -300,17 +281,17 @@ var _ = Describe("Test application containing helm module", func() {
|
||||
Expect(k8sClient.Create(ctx, &workloaddef)).Should(Succeed())
|
||||
|
||||
appTestName := "test-app-refer-to-workloaddef"
|
||||
appTest := v1alpha2.Application{
|
||||
appTest := v1beta1.Application{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: appTestName,
|
||||
Namespace: namespace,
|
||||
},
|
||||
Spec: v1alpha2.ApplicationSpec{
|
||||
Components: []v1alpha2.ApplicationComponent{
|
||||
Spec: v1beta1.ApplicationSpec{
|
||||
Components: []v1beta1.ApplicationComponent{
|
||||
{
|
||||
Name: compName,
|
||||
WorkloadType: wdName,
|
||||
Settings: util.Object2RawExtension(map[string]interface{}{
|
||||
Name: compName,
|
||||
Type: wdName,
|
||||
Properties: util.Object2RawExtension(map[string]interface{}{
|
||||
"image": map[string]interface{}{
|
||||
"tag": "5.1.2",
|
||||
},
|
||||
@@ -322,13 +303,6 @@ var _ = Describe("Test application containing helm module", func() {
|
||||
By("Create application")
|
||||
Expect(k8sClient.Create(ctx, &appTest)).Should(Succeed())
|
||||
|
||||
ac := &v1alpha2.ApplicationContext{}
|
||||
acName := appTestName
|
||||
By("Verify the AppConfig is created successfully")
|
||||
Eventually(func() error {
|
||||
return k8sClient.Get(ctx, client.ObjectKey{Name: acName, Namespace: namespace}, ac)
|
||||
}, 30*time.Second, time.Second).Should(Succeed())
|
||||
|
||||
By("Verify the workload(deployment) is created successfully by Helm")
|
||||
deploy := &appsv1.Deployment{}
|
||||
deployName := fmt.Sprintf("%s-%s-podinfo", appTestName, compName)
|
||||
@@ -338,7 +312,7 @@ var _ = Describe("Test application containing helm module", func() {
|
||||
})
|
||||
|
||||
It("Test deploy an application containing helm module and the componet refer to autodetect type worklaod", func() {
|
||||
cd := v1alpha2.ComponentDefinition{}
|
||||
cd := v1beta1.ComponentDefinition{}
|
||||
cd.SetName("podinfo")
|
||||
cd.SetNamespace(namespace)
|
||||
cd.Spec.Schematic = &common.Schematic{
|
||||
@@ -359,17 +333,17 @@ var _ = Describe("Test application containing helm module", func() {
|
||||
Expect(k8sClient.Create(ctx, &cd)).Should(Succeed())
|
||||
|
||||
newAppName := "test-autodetect"
|
||||
newApp := v1alpha2.Application{
|
||||
newApp := v1beta1.Application{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: newAppName,
|
||||
Namespace: namespace,
|
||||
},
|
||||
Spec: v1alpha2.ApplicationSpec{
|
||||
Components: []v1alpha2.ApplicationComponent{
|
||||
Spec: v1beta1.ApplicationSpec{
|
||||
Components: []v1beta1.ApplicationComponent{
|
||||
{
|
||||
Name: compName,
|
||||
WorkloadType: "podinfo",
|
||||
Settings: util.Object2RawExtension(map[string]interface{}{
|
||||
Name: compName,
|
||||
Type: "podinfo",
|
||||
Properties: util.Object2RawExtension(map[string]interface{}{
|
||||
"image": map[string]interface{}{
|
||||
"tag": "5.1.2",
|
||||
},
|
||||
|
||||
@@ -31,7 +31,6 @@ import (
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
"github.com/oam-dev/kubevela/apis/core.oam.dev/common"
|
||||
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha2"
|
||||
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
|
||||
"github.com/oam-dev/kubevela/pkg/oam/util"
|
||||
|
||||
@@ -200,26 +199,15 @@ spec:
|
||||
By("Create application")
|
||||
Expect(k8sClient.Create(ctx, &app)).Should(Succeed())
|
||||
|
||||
ac := &v1alpha2.ApplicationContext{}
|
||||
acName := appName
|
||||
By("Verify the ApplicationContext is created & reconciled successfully")
|
||||
Eventually(func() bool {
|
||||
if err := k8sClient.Get(ctx, client.ObjectKey{Name: acName, Namespace: namespace}, ac); err != nil {
|
||||
return false
|
||||
}
|
||||
return len(ac.Status.Workloads) > 0
|
||||
}, 60*time.Second, time.Second).Should(BeTrue())
|
||||
|
||||
By("Verify the workload(deployment) is created successfully")
|
||||
deploy := &appsv1.Deployment{}
|
||||
deployName := ac.Status.Workloads[0].Reference.Name
|
||||
deployName := compName
|
||||
Eventually(func() error {
|
||||
return k8sClient.Get(ctx, client.ObjectKey{Name: deployName, Namespace: namespace}, deploy)
|
||||
}, 30*time.Second, 3*time.Second).Should(Succeed())
|
||||
|
||||
By("Verify two traits are applied to the workload")
|
||||
Eventually(func() bool {
|
||||
requestReconcileNow(ctx, ac)
|
||||
deploy := &appsv1.Deployment{}
|
||||
if err := k8sClient.Get(ctx, client.ObjectKey{Name: deployName, Namespace: namespace}, deploy); err != nil {
|
||||
return false
|
||||
@@ -272,21 +260,12 @@ spec:
|
||||
}
|
||||
Expect(k8sClient.Patch(ctx, &app, client.Merge)).Should(Succeed())
|
||||
|
||||
By("Verify the ApplicationContext is update successfully")
|
||||
Eventually(func() bool {
|
||||
if err := k8sClient.Get(ctx, client.ObjectKey{Name: acName, Namespace: namespace}, ac); err != nil {
|
||||
return false
|
||||
}
|
||||
return ac.Generation == 2
|
||||
}, 10*time.Second, time.Second).Should(BeTrue())
|
||||
|
||||
By("Verify the workload(deployment) is created successfully")
|
||||
deploy = &appsv1.Deployment{}
|
||||
deployName = ac.Status.Workloads[0].Reference.Name
|
||||
deployName = compName
|
||||
|
||||
By("Verify the changes are applied to the workload")
|
||||
Eventually(func() bool {
|
||||
requestReconcileNow(ctx, ac)
|
||||
deploy := &appsv1.Deployment{}
|
||||
if err := k8sClient.Get(ctx, client.ObjectKey{Name: deployName, Namespace: namespace}, deploy); err != nil {
|
||||
return false
|
||||
@@ -348,19 +327,9 @@ spec:
|
||||
By("Create application")
|
||||
Expect(k8sClient.Create(ctx, &appTest)).Should(Succeed())
|
||||
|
||||
ac := &v1alpha2.ApplicationContext{}
|
||||
acName := appTestName
|
||||
By("Verify the ApplicationContext is created & reconciled successfully")
|
||||
Eventually(func() bool {
|
||||
if err := k8sClient.Get(ctx, client.ObjectKey{Name: acName, Namespace: namespace}, ac); err != nil {
|
||||
return false
|
||||
}
|
||||
return len(ac.Status.Workloads) > 0
|
||||
}, 15*time.Second, time.Second).Should(BeTrue())
|
||||
|
||||
By("Verify the workload(deployment) is created successfully")
|
||||
deploy := &appsv1.Deployment{}
|
||||
deployName := ac.Status.Workloads[0].Reference.Name
|
||||
deployName := compName
|
||||
Eventually(func() error {
|
||||
return k8sClient.Get(ctx, client.ObjectKey{Name: deployName, Namespace: namespace}, deploy)
|
||||
}, 15*time.Second, 3*time.Second).Should(Succeed())
|
||||
|
||||
@@ -21,24 +21,25 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/oam-dev/kubevela/pkg/oam"
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
|
||||
kruise "github.com/openkruise/kruise-api/apps/v1alpha1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
corev1beta1 "k8s.io/api/networking/v1beta1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/utils/pointer"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
kruise "github.com/openkruise/kruise-api/apps/v1alpha1"
|
||||
|
||||
oamcomm "github.com/oam-dev/kubevela/apis/core.oam.dev/common"
|
||||
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha2"
|
||||
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
|
||||
oamstd "github.com/oam-dev/kubevela/apis/standard.oam.dev/v1alpha1"
|
||||
"github.com/oam-dev/kubevela/apis/types"
|
||||
"github.com/oam-dev/kubevela/pkg/controller/core.oam.dev/v1alpha2/application/dispatch"
|
||||
"github.com/oam-dev/kubevela/pkg/controller/utils"
|
||||
"github.com/oam-dev/kubevela/pkg/oam"
|
||||
"github.com/oam-dev/kubevela/pkg/oam/util"
|
||||
"github.com/oam-dev/kubevela/pkg/utils/common"
|
||||
)
|
||||
@@ -92,6 +93,18 @@ var _ = Describe("Cloneset based rollout tests", func() {
|
||||
time.Second*3, time.Millisecond*300).Should(SatisfyAny(BeNil(), &util.AlreadyExistMatcher{}))
|
||||
}
|
||||
|
||||
CreateIngressDef := func() {
|
||||
By("Install Ingress trait definition")
|
||||
var td v1beta1.TraitDefinition
|
||||
Expect(common.ReadYamlToObject("testdata/rollout/cloneset/ingressDefinition.yaml", &td)).Should(BeNil())
|
||||
// create the traitDefinition if not exist
|
||||
Eventually(
|
||||
func() error {
|
||||
return k8sClient.Create(ctx, &td)
|
||||
},
|
||||
time.Second*3, time.Millisecond*300).Should(SatisfyAny(BeNil(), &util.AlreadyExistMatcher{}))
|
||||
}
|
||||
|
||||
applySourceApp := func(source string) {
|
||||
By("Apply an application")
|
||||
var newApp v1beta1.Application
|
||||
@@ -119,21 +132,22 @@ var _ = Describe("Cloneset based rollout tests", func() {
|
||||
Eventually(
|
||||
func() error {
|
||||
k8sClient.Get(ctx, client.ObjectKey{Namespace: namespaceName, Name: app.Name}, &app)
|
||||
app.Spec = targetApp.Spec
|
||||
return k8sClient.Update(ctx, &app)
|
||||
app.Spec = targetApp.DeepCopy().Spec
|
||||
return k8sClient.Update(ctx, app.DeepCopy())
|
||||
}, time.Second*15, time.Millisecond*500).Should(Succeed())
|
||||
|
||||
By("Get Application Revision created with more than one")
|
||||
Eventually(
|
||||
func() bool {
|
||||
var appRevList = &v1beta1.ApplicationRevisionList{}
|
||||
_ = k8sClient.List(ctx, appRevList, client.MatchingLabels(map[string]string{oam.LabelAppName: targetApp.Name}))
|
||||
_ = k8sClient.List(ctx, appRevList, client.InNamespace(namespaceName),
|
||||
client.MatchingLabels(map[string]string{oam.LabelAppName: targetApp.Name}))
|
||||
if appRevList != nil {
|
||||
return len(appRevList.Items) >= 2
|
||||
}
|
||||
return false
|
||||
},
|
||||
time.Second*30, time.Millisecond*500).Should(BeTrue())
|
||||
time.Second*15, time.Millisecond*500).Should(BeTrue())
|
||||
}
|
||||
|
||||
createAppRolling := func(newAppRollout *v1beta1.AppRollout) {
|
||||
@@ -183,53 +197,80 @@ var _ = Describe("Cloneset based rollout tests", func() {
|
||||
Expect(appRollout.Status.UpgradedReplicas).Should(BeEquivalentTo(appRollout.Status.RolloutTargetSize))
|
||||
clonesetName := appRollout.Spec.ComponentList[0]
|
||||
|
||||
By("Verify AppContext rolling status")
|
||||
var appContext v1alpha2.ApplicationContext
|
||||
Eventually(
|
||||
func() types.RollingStatus {
|
||||
k8sClient.Get(ctx, client.ObjectKey{Namespace: namespaceName, Name: targetAppName}, &appContext)
|
||||
return appContext.Status.RollingStatus
|
||||
},
|
||||
time.Second*60, time.Second).Should(BeEquivalentTo(types.RollingCompleted))
|
||||
By("Wait for resourceTracker to resume the control of cloneset")
|
||||
|
||||
By("Wait for AppContext to resume the control of cloneset")
|
||||
var clonesetOwner *metav1.OwnerReference
|
||||
Eventually(
|
||||
func() string {
|
||||
func() error {
|
||||
var clonesetOwner *metav1.OwnerReference
|
||||
err := k8sClient.Get(ctx, client.ObjectKey{Namespace: namespaceName, Name: clonesetName}, &kc)
|
||||
if err != nil {
|
||||
return ""
|
||||
return err
|
||||
}
|
||||
if kc.Status.UpdatedReplicas != *kc.Spec.Replicas {
|
||||
return fmt.Errorf("expect cloneset updated replicas %d, but got %d",
|
||||
kc.Status.UpdatedReplicas, *kc.Spec.Replicas)
|
||||
}
|
||||
clonesetOwner = metav1.GetControllerOf(&kc)
|
||||
if clonesetOwner != nil {
|
||||
return clonesetOwner.Kind
|
||||
if clonesetOwner == nil {
|
||||
return fmt.Errorf("controller owner missed")
|
||||
}
|
||||
return ""
|
||||
if clonesetOwner.Kind != v1beta1.ResourceTrackerKind {
|
||||
return fmt.Errorf("controller kind missmatch wants %s actually %s", v1beta1.ResourceTrackerKind, clonesetOwner.Kind)
|
||||
}
|
||||
resourceTrackerName := dispatch.ConstructResourceTrackerName(targetAppName, namespaceName)
|
||||
if resourceTrackerName != clonesetOwner.Name {
|
||||
return fmt.Errorf("controller name missmatch wants %s actually %s", resourceTrackerName, clonesetOwner.Name)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
time.Second*30, time.Millisecond*500).Should(BeEquivalentTo(v1alpha2.ApplicationContextKind))
|
||||
Expect(clonesetOwner.Name).Should(BeEquivalentTo(targetAppName))
|
||||
Expect(kc.Status.UpdatedReplicas).Should(BeEquivalentTo(*kc.Spec.Replicas))
|
||||
time.Second*60, time.Millisecond*500).Should(BeNil())
|
||||
// make sure all pods are upgraded
|
||||
image := kc.Spec.Template.Spec.Containers[0].Image
|
||||
podList := corev1.PodList{}
|
||||
Expect(k8sClient.List(ctx, &podList, client.MatchingLabels(kc.Spec.Template.Labels),
|
||||
client.InNamespace(namespaceName))).Should(Succeed())
|
||||
Expect(len(podList.Items)).Should(BeEquivalentTo(*kc.Spec.Replicas))
|
||||
for _, pod := range podList.Items {
|
||||
Expect(pod.Spec.Containers[0].Image).Should(Equal(image))
|
||||
Expect(pod.Status.Phase).Should(Equal(corev1.PodRunning))
|
||||
}
|
||||
Eventually(func() error {
|
||||
if err := k8sClient.List(ctx, &podList, client.MatchingLabels(kc.Spec.Template.Labels),
|
||||
client.InNamespace(namespaceName)); err != nil {
|
||||
return err
|
||||
}
|
||||
if len(podList.Items) != int(*kc.Spec.Replicas) {
|
||||
return fmt.Errorf("expect pod numbers %q, got %q", int(*kc.Spec.Replicas), len(podList.Items))
|
||||
}
|
||||
for _, pod := range podList.Items {
|
||||
gotImage := pod.Spec.Containers[0].Image
|
||||
if gotImage != image {
|
||||
return fmt.Errorf("expect pod container image %q, got %q", image, gotImage)
|
||||
}
|
||||
if pod.Status.Phase != corev1.PodRunning {
|
||||
return fmt.Errorf("expect pod phase %q, got %q", corev1.PodRunning, pod.Status.Phase)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}, 60*time.Second, 500*time.Millisecond).Should(Succeed())
|
||||
}
|
||||
|
||||
verifyAppConfigInactive := func(appContextName string) {
|
||||
var appContext v1alpha2.ApplicationContext
|
||||
By("Verify AppConfig is inactive")
|
||||
Eventually(
|
||||
func() types.RollingStatus {
|
||||
k8sClient.Get(ctx, client.ObjectKey{Namespace: namespaceName, Name: appContextName}, &appContext)
|
||||
return appContext.Status.RollingStatus
|
||||
},
|
||||
time.Second*30, time.Millisecond*500).Should(BeEquivalentTo(types.InactiveAfterRollingCompleted))
|
||||
verifyIngress := func(domain string) {
|
||||
ingress := &corev1beta1.Ingress{}
|
||||
Eventually(func() error {
|
||||
var err error
|
||||
if err = k8sClient.Get(ctx, types.NamespacedName{Namespace: namespaceName, Name: appRollout.Spec.ComponentList[0]}, ingress); err != nil {
|
||||
return err
|
||||
}
|
||||
owner := metav1.GetControllerOf(ingress)
|
||||
if owner == nil {
|
||||
return fmt.Errorf("ingress don't have controller owner")
|
||||
}
|
||||
if owner.Kind != v1beta1.ResourceTrackerKind {
|
||||
return fmt.Errorf("ingress owner kind miss match wants %s actually %s", v1beta1.ResourceTrackerKind, owner.Kind)
|
||||
}
|
||||
rtName := dispatch.ConstructResourceTrackerName(appRollout.Spec.TargetAppRevisionName, appRollout.Namespace)
|
||||
if owner.Name != rtName {
|
||||
return fmt.Errorf("ingress owner error wants %s actually %s", rtName, owner.Name)
|
||||
}
|
||||
if ingress.Spec.Rules[0].Host != domain {
|
||||
return fmt.Errorf("domain mismatch wants %s actually %s", domain, ingress.Spec.Rules[0].Host)
|
||||
}
|
||||
return nil
|
||||
}, time.Second*30, time.Microsecond*300).Should(BeNil())
|
||||
}
|
||||
|
||||
applyTwoAppVersion := func() {
|
||||
@@ -275,7 +316,6 @@ var _ = Describe("Cloneset based rollout tests", func() {
|
||||
time.Second*10, time.Millisecond*10).Should(BeEquivalentTo(oamstd.RollingInBatchesState))
|
||||
|
||||
verifyRolloutSucceeded(appRollout.Spec.TargetAppRevisionName)
|
||||
verifyAppConfigInactive(appRollout.Spec.SourceAppRevisionName)
|
||||
}
|
||||
|
||||
BeforeEach(func() {
|
||||
@@ -363,7 +403,6 @@ var _ = Describe("Cloneset based rollout tests", func() {
|
||||
RolloutBatches) - 1))
|
||||
Expect(k8sClient.Update(ctx, &appRollout)).Should(Succeed())
|
||||
verifyRolloutSucceeded(appRollout.Spec.TargetAppRevisionName)
|
||||
verifyAppConfigInactive(appRollout.Spec.SourceAppRevisionName)
|
||||
})
|
||||
|
||||
It("Test pause and modify rollout plan after rolling succeeded", func() {
|
||||
@@ -461,8 +500,6 @@ var _ = Describe("Cloneset based rollout tests", func() {
|
||||
time.Second*10, time.Millisecond*10).Should(BeEquivalentTo(oamstd.RollingInBatchesState))
|
||||
|
||||
verifyRolloutSucceeded(appRollout.Spec.TargetAppRevisionName)
|
||||
verifyAppConfigInactive(appRollout.Spec.SourceAppRevisionName)
|
||||
|
||||
rollForwardToSource()
|
||||
})
|
||||
|
||||
@@ -570,12 +607,9 @@ var _ = Describe("Cloneset based rollout tests", func() {
|
||||
appRollout.Spec.RolloutPlan.BatchPartition = nil
|
||||
return k8sClient.Update(ctx, &appRollout)
|
||||
}, time.Second*15, time.Millisecond*500).Should(Succeed())
|
||||
|
||||
verifyRolloutSucceeded(appRollout.Spec.TargetAppRevisionName)
|
||||
verifyAppConfigInactive(appRollout.Spec.SourceAppRevisionName)
|
||||
|
||||
// wait for a bit until the application takes back control
|
||||
By("Verify that application does not control the cloneset")
|
||||
By("Verify that resourceTracker control the cloneset")
|
||||
clonesetName := appRollout.Spec.ComponentList[0]
|
||||
Eventually(
|
||||
func() string {
|
||||
@@ -585,7 +619,75 @@ var _ = Describe("Cloneset based rollout tests", func() {
|
||||
return ""
|
||||
}
|
||||
return clonesetOwner.Kind
|
||||
}, time.Second*30, time.Second).Should(BeEquivalentTo(v1alpha2.ApplicationContextKind))
|
||||
}, time.Second*30, time.Second).Should(BeEquivalentTo(v1beta1.ResourceTrackerKind))
|
||||
})
|
||||
|
||||
It("Test rollout will update same name trait", func() {
|
||||
CreateClonesetDef()
|
||||
CreateIngressDef()
|
||||
applySourceApp("app-with-ingress-source.yaml")
|
||||
By("Apply the application rollout go directly to the target")
|
||||
appRollout = v1beta1.AppRollout{}
|
||||
Expect(common.ReadYamlToObject("testdata/rollout/cloneset/appRollout.yaml", &appRollout)).Should(BeNil())
|
||||
appRollout.Namespace = namespaceName
|
||||
appRollout.Spec.SourceAppRevisionName = ""
|
||||
appRollout.Spec.TargetAppRevisionName = utils.ConstructRevisionName(app.GetName(), 1)
|
||||
appRollout.Spec.RolloutPlan.TargetSize = pointer.Int32Ptr(7)
|
||||
appRollout.Spec.RolloutPlan.BatchPartition = nil
|
||||
createAppRolling(&appRollout)
|
||||
appRolloutName = appRollout.Name
|
||||
verifyRolloutSucceeded(appRollout.Spec.TargetAppRevisionName)
|
||||
By("verify ingress status")
|
||||
verifyIngress("test.example.com")
|
||||
By("rollout to revision 2")
|
||||
updateApp("app-with-ingress-target.yaml")
|
||||
Eventually(
|
||||
func() error {
|
||||
k8sClient.Get(ctx, client.ObjectKey{Namespace: namespaceName, Name: appRollout.Name}, &appRollout)
|
||||
appRollout.Spec.SourceAppRevisionName = utils.ConstructRevisionName(app.GetName(), 1)
|
||||
appRollout.Spec.TargetAppRevisionName = utils.ConstructRevisionName(app.GetName(), 2)
|
||||
appRollout.Spec.RolloutPlan.BatchPartition = nil
|
||||
return k8sClient.Update(ctx, &appRollout)
|
||||
}, time.Second*10, time.Millisecond*500).Should(Succeed())
|
||||
verifyRolloutSucceeded(appRollout.Spec.TargetAppRevisionName)
|
||||
By("verify after rollout ingress status")
|
||||
verifyIngress("test-1.example.com")
|
||||
})
|
||||
|
||||
It("Test rollout succeed will gc useless trait", func() {
|
||||
CreateClonesetDef()
|
||||
CreateIngressDef()
|
||||
applySourceApp("app-with-ingress-source.yaml")
|
||||
By("Apply the application rollout go directly to the target")
|
||||
appRollout = v1beta1.AppRollout{}
|
||||
Expect(common.ReadYamlToObject("testdata/rollout/cloneset/appRollout.yaml", &appRollout)).Should(BeNil())
|
||||
appRollout.Namespace = namespaceName
|
||||
appRollout.Spec.SourceAppRevisionName = ""
|
||||
appRollout.Spec.TargetAppRevisionName = utils.ConstructRevisionName(app.GetName(), 1)
|
||||
appRollout.Spec.RolloutPlan.TargetSize = pointer.Int32Ptr(7)
|
||||
appRollout.Spec.RolloutPlan.BatchPartition = nil
|
||||
createAppRolling(&appRollout)
|
||||
appRolloutName = appRollout.Name
|
||||
verifyRolloutSucceeded(appRollout.Spec.TargetAppRevisionName)
|
||||
By("verify ingress status")
|
||||
verifyIngress("test.example.com")
|
||||
By("rollout to revision 2 to disable ingress trait")
|
||||
|
||||
updateApp("app-remove-ingress.yaml")
|
||||
Eventually(
|
||||
func() error {
|
||||
k8sClient.Get(ctx, client.ObjectKey{Namespace: namespaceName, Name: appRollout.Name}, &appRollout)
|
||||
appRollout.Spec.SourceAppRevisionName = utils.ConstructRevisionName(app.GetName(), 1)
|
||||
appRollout.Spec.TargetAppRevisionName = utils.ConstructRevisionName(app.GetName(), 2)
|
||||
appRollout.Spec.RolloutPlan.BatchPartition = nil
|
||||
return k8sClient.Update(ctx, &appRollout)
|
||||
}, time.Second*10, time.Millisecond*500).Should(Succeed())
|
||||
verifyRolloutSucceeded(appRollout.Spec.TargetAppRevisionName)
|
||||
By("verify after rollout ingress have been removed")
|
||||
Eventually(func() error {
|
||||
ingress := &corev1beta1.Ingress{}
|
||||
return k8sClient.Get(ctx, types.NamespacedName{Namespace: namespaceName, Name: appRollout.Spec.ComponentList[0]}, ingress)
|
||||
}, time.Second*30, 300*time.Microsecond).Should(util.NotFoundMatcher{})
|
||||
})
|
||||
|
||||
PIt("Test rolling by changing the definition", func() {
|
||||
@@ -611,7 +713,6 @@ var _ = Describe("Cloneset based rollout tests", func() {
|
||||
createAppRolling(&newAppRollout)
|
||||
|
||||
verifyRolloutSucceeded(appRollout.Spec.TargetAppRevisionName)
|
||||
verifyAppConfigInactive(appRollout.Spec.SourceAppRevisionName)
|
||||
// Clean up
|
||||
k8sClient.Delete(ctx, &appRollout)
|
||||
})
|
||||
|
||||
17
test/e2e-test/testdata/rollout/cloneset/app-remove-ingress.yaml
vendored
Normal file
17
test/e2e-test/testdata/rollout/cloneset/app-remove-ingress.yaml
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
apiVersion: core.oam.dev/v1beta1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: test-e2e-rolling
|
||||
annotations:
|
||||
"app.oam.dev/rollout-template": "true"
|
||||
spec:
|
||||
components:
|
||||
- name: metrics-provider
|
||||
type: clonesetservice
|
||||
properties:
|
||||
cmd:
|
||||
- ./podinfo
|
||||
- stress-cpu=1
|
||||
image: stefanprodan/podinfo:5.0.2
|
||||
port: 8080
|
||||
updateStrategyType: InPlaceOnly
|
||||
23
test/e2e-test/testdata/rollout/cloneset/app-with-ingress-source.yaml
vendored
Normal file
23
test/e2e-test/testdata/rollout/cloneset/app-with-ingress-source.yaml
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
apiVersion: core.oam.dev/v1beta1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: test-e2e-rolling
|
||||
annotations:
|
||||
"app.oam.dev/rollout-template": "true"
|
||||
spec:
|
||||
components:
|
||||
- name: metrics-provider
|
||||
type: clonesetservice
|
||||
properties:
|
||||
cmd:
|
||||
- ./podinfo
|
||||
- stress-cpu=1
|
||||
image: stefanprodan/podinfo:4.0.3
|
||||
port: 8080
|
||||
updateStrategyType: InPlaceOnly
|
||||
traits:
|
||||
- type: ingress
|
||||
properties:
|
||||
domain: test.example.com
|
||||
http:
|
||||
"/": 8080
|
||||
23
test/e2e-test/testdata/rollout/cloneset/app-with-ingress-target.yaml
vendored
Normal file
23
test/e2e-test/testdata/rollout/cloneset/app-with-ingress-target.yaml
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
apiVersion: core.oam.dev/v1beta1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: test-e2e-rolling
|
||||
annotations:
|
||||
"app.oam.dev/rollout-template": "true"
|
||||
spec:
|
||||
components:
|
||||
- name: metrics-provider
|
||||
type: clonesetservice
|
||||
properties:
|
||||
cmd:
|
||||
- ./podinfo
|
||||
- stress-cpu=1
|
||||
image: stefanprodan/podinfo:5.0.2
|
||||
port: 8080
|
||||
updateStrategyType: InPlaceOnly
|
||||
traits:
|
||||
- type: ingress
|
||||
properties:
|
||||
domain: test-1.example.com
|
||||
http:
|
||||
"/": 8080
|
||||
79
test/e2e-test/testdata/rollout/cloneset/ingressDefinition.yaml
vendored
Normal file
79
test/e2e-test/testdata/rollout/cloneset/ingressDefinition.yaml
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
apiVersion: core.oam.dev/v1beta1
|
||||
kind: TraitDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
definition.oam.dev/description: "Enable public web traffic for the component."
|
||||
name: ingress
|
||||
namespace: vela-system
|
||||
spec:
|
||||
status:
|
||||
customStatus: |-
|
||||
let igs = context.outputs.ingress.status.loadBalancer.ingress
|
||||
if igs == _|_ {
|
||||
message: "No loadBalancer found, visiting by using 'vela port-forward " + context.appName + " --route'\n"
|
||||
}
|
||||
if len(igs) > 0 {
|
||||
if igs[0].ip != _|_ {
|
||||
message: "Visiting URL: " + context.outputs.ingress.spec.rules[0].host + ", IP: " + igs[0].ip
|
||||
}
|
||||
if igs[0].ip == _|_ {
|
||||
message: "Visiting URL: " + context.outputs.ingress.spec.rules[0].host
|
||||
}
|
||||
}
|
||||
healthPolicy: |
|
||||
isHealth: len(context.outputs.service.spec.clusterIP) > 0
|
||||
appliesToWorkloads:
|
||||
- deployments.apps
|
||||
podDisruptive: false
|
||||
schematic:
|
||||
cue:
|
||||
template: |
|
||||
// trait template can have multiple outputs in one trait
|
||||
outputs: service: {
|
||||
apiVersion: "v1"
|
||||
kind: "Service"
|
||||
metadata:
|
||||
name: context.name
|
||||
spec: {
|
||||
selector: {
|
||||
"app.oam.dev/component": context.name
|
||||
}
|
||||
ports: [
|
||||
for k, v in parameter.http {
|
||||
port: v
|
||||
targetPort: v
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
outputs: ingress: {
|
||||
apiVersion: "networking.k8s.io/v1beta1"
|
||||
kind: "Ingress"
|
||||
metadata:
|
||||
name: context.name
|
||||
spec: {
|
||||
rules: [{
|
||||
host: parameter.domain
|
||||
http: {
|
||||
paths: [
|
||||
for k, v in parameter.http {
|
||||
path: k
|
||||
backend: {
|
||||
serviceName: context.name
|
||||
servicePort: v
|
||||
}
|
||||
},
|
||||
]
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
parameter: {
|
||||
// +usage=Specify the domain you want to expose
|
||||
domain: string
|
||||
|
||||
// +usage=Specify the mapping relationship between the http path and the workload port
|
||||
http: [string]: int
|
||||
}
|
||||
Reference in New Issue
Block a user