mirror of
https://github.com/kubevela/kubevela.git
synced 2026-02-14 18:10:21 +00:00
Add e2e test for App Context (#1240)
* add e2e test for context add workload check should not create AC add test trait render update e2e-test logic add switching context write status back to AppRevision logic add create and pull apprevision test quick fix for appContext ownerReference problem add more tests fix test * add boilerplate * rebase master fix issue * rebase master and fix test * fix check interval time
This commit is contained in:
315
test/e2e-test/appcontext_test.go
Normal file
315
test/e2e-test/appcontext_test.go
Normal file
@@ -0,0 +1,315 @@
|
||||
/*
|
||||
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/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: convertComponentList2Map([]*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: convertComponentList2Map([]*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 reconcil logic ", func() {
|
||||
By("Test AppRevision1 only have 1 workload on trait")
|
||||
Expect(k8sClient.Create(ctx, appContext)).Should(Succeed())
|
||||
Eventually(func() error {
|
||||
appCtx := new(v1alpha2.ApplicationContext)
|
||||
err := k8sClient.Get(ctx, key, appCtx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
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")
|
||||
Expect(k8sClient.Get(ctx, key, appContext)).Should(BeNil())
|
||||
appContext.Spec.ApplicationRevisionName = arName2
|
||||
Expect(k8sClient.Update(ctx, appContext)).Should(Succeed())
|
||||
Eventually(func() error {
|
||||
appCtx := new(v1alpha2.ApplicationContext)
|
||||
err := k8sClient.Get(ctx, types.NamespacedName{Namespace: namespace, Name: appContextName}, appCtx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
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())
|
||||
Expect(k8sClient.Get(ctx, key, appContext)).Should(BeNil())
|
||||
appContext.Spec.ApplicationRevisionName = arName1
|
||||
Expect(k8sClient.Update(ctx, appContext)).Should(Succeed())
|
||||
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())
|
||||
Expect(k8sClient.Get(ctx, key, appContext)).Should(BeNil())
|
||||
appContext.Spec.ApplicationRevisionName = arName2
|
||||
Expect(k8sClient.Update(ctx, appContext)).Should(Succeed())
|
||||
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{})
|
||||
})
|
||||
})
|
||||
|
||||
func convertComponentList2Map(comps []*v1alpha2.Component) map[string]v1alpha2.Component {
|
||||
objs := map[string]v1alpha2.Component{}
|
||||
for _, comp := range comps {
|
||||
obj := comp.DeepCopy()
|
||||
objs[comp.Name] = *obj
|
||||
}
|
||||
return objs
|
||||
}
|
||||
Reference in New Issue
Block a user