Unverified Commit dbc4593b authored by wyike's avatar wyike Committed by GitHub
Browse files

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
parent 11bc937f
Showing with 315 additions and 0 deletions
+315 -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/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
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment