Files
kubevela/test/e2e-test/kube_app_test.go
Somefive 7103f8ff52 Feat: merge master into apiserver (#2660)
* Feat(rollout): fill rolloutBatches if empty when scale up/down (#2569)

* Feat: fill rolloutBatches if empty

* Fix: fix unit-test

* Test: add more test

Fix: lint

Fix: fix lint

* Update release.yml (#2537)

* Feat: add registry, merge registry and cap center (#2528)

* Feat: add registry command

* Refactor: comp/trait command combine with registry

* Feat: refactor `vela comp/trait`

* Fix: import

* Fix: fix if type is autodetects.core.oam.dev

* Fix: fix list from url

* Fix: test

* Feat: add test

* Fix: remove dup test

* Fix: test

* Fix: test

* Fix: fix label filter

* Fix: reviewable

* Fix test

* fix personal repo in test

* Fix test

* Fix test

* add some boundary check

* reviewable

* Fix: fix nocalhost trait (#2577)

* fix incorrect addon status (#2576)

* Fix(cli): client-side throttling in vela CLI (#2581)

* fix cli throttling

* fix import

* set to a lower value

* remove addon with no defs (#2574)

* Feat: vela logs support multicluster (#2593)

* Feat: add basic multiple cluster logs

* fix context

* Fix select style

* Fix select style

* remove useless env

* fix naming

* Feat: vela cluster support use ocm to join/list/detach cluster (#2599)

* Feat: add render component and apply component remaining (#2587)

* Feat: add render component and apply component remaining

* fix ut

* fix e2e

* allow import package in custom status cue template (#2585)

Co-authored-by: chwetion <chwetion@foxmail.com>

* Fix: abnormal aux name (#2612)

* Feat: store workflow step def properties in cm (#2592)

* Fix: fix notification def

* Feat: store workflow step def properties in cm

* fix ci

* fix data race

* Fix: change Initializer to Application for addon Observability (#2615)

In this doc, updated the Observability implementation from initializer
to Application. I also store definitions as it's not well stored in
vela-templates/addons/observability

* Fix: fix backport param (#2611)

* Fix: add owner reference in workflow context cm (#2573)

* Fix: add owner reference in workflow context cm

* fix ci

* delete useless test case

* Fix: op.delete bugs (#2622)

* Fix: op.delete some bugs

* Fix: app status update error

Fix: make reviewable

* Fix: show reconcile error log (#2626)

* Feat: add reconcile timeout configuration for vela-core (#2630)

* Fix: patch status retry while conflict happens (#2629)

* Fix: allow definition schema cm can be same name in different definition type (#2618)

* Fix: fix definition schema cm name

* fix ut

* fix ut

* fix show

* add switch default case

* Feat: remove envbinding policy into workflow (#2556)

Fix: add more test

* Feat: add vela prob to test cluster (#2635)

* Fix: upgrade stern lib to avoid panic for vela logs (#2650)

* Fix: filter loggable workload in vela logs (#2651)

* Fix: filter loggable workload in vela logs

* reviewable

* Feat: add vela exec for multi cluster (#2299)

fix

support vela exec

* Fix: health check will check for multiclusters (#2645)

* Fix: minor fix for vela cli printing (#2655)

* Fix: minor fix for vela cli printing

* add dockerfile go mod cache

* Feat: support apiserver-related multicluster features (#2625)

* Feat: remove envbinding policy into workflow

Feat: add support for env change (env gc)

Fix: fix rollout timeout setting bug

* Feat: support disable trait and env without workflow

* Fix: add hint for replaced value

Co-authored-by: wyike <wangyike_wyk@163.com>
Co-authored-by: basefas <basefas@hotmail.com>
Co-authored-by: qiaozp <47812250+chivalryq@users.noreply.github.com>
Co-authored-by: Tianxin Dong <dongtianxin.tx@alibaba-inc.com>
Co-authored-by: yangsoon <yangsoonlx@gmail.com>
Co-authored-by: Chwetion <137953601@qq.com>
Co-authored-by: chwetion <chwetion@foxmail.com>
Co-authored-by: Jian.Li <74582607+leejanee@users.noreply.github.com>
Co-authored-by: Zheng Xi Zhou <zzxwill@gmail.com>
Co-authored-by: Jianbo Sun <jianbo.sjb@alibaba-inc.com>
2021-11-09 13:06:55 +08:00

358 lines
11 KiB
Go

/*
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"
"errors"
"fmt"
"time"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/utils/pointer"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/yaml"
"github.com/oam-dev/kubevela/apis/core.oam.dev/common"
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
"github.com/oam-dev/kubevela/apis/types"
"github.com/oam-dev/kubevela/pkg/oam/util"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
var _ = Describe("Test application containing kube module", func() {
ctx := context.Background()
var (
appName = "test-app"
compName = "test-comp"
cdName = "test-kube-worker"
wdName = "test-kube-worker-wd"
tdName = "test-virtualgroup"
)
var namespace string
var app v1beta1.Application
var ns corev1.Namespace
var testTemplate = func() runtime.RawExtension {
yamlStr := `apiVersion: apps/v1
kind: Deployment
spec:
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
ports:
- containerPort: 80 `
b, _ := yaml.YAMLToJSON([]byte(yamlStr))
return runtime.RawExtension{Raw: b}
}
BeforeEach(func() {
namespace = randomNamespaceName("kube-e2e-test")
ns = corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: namespace}}
Eventually(
func() error {
return k8sClient.Create(ctx, &ns)
},
time.Second*3, time.Millisecond*300).Should(SatisfyAny(BeNil(), &util.AlreadyExistMatcher{}))
cd := v1beta1.ComponentDefinition{}
cd.SetName(cdName)
cd.SetNamespace(namespace)
cd.Spec.Workload.Definition = common.WorkloadGVK{APIVersion: "apps/v1", Kind: "Deployment"}
cd.Spec.Schematic = &common.Schematic{
KUBE: &common.Kube{
Template: testTemplate(),
Parameters: []common.KubeParameter{
{
Name: "image",
ValueType: common.StringType,
FieldPaths: []string{"spec.template.spec.containers[0].image"},
Required: pointer.BoolPtr(true),
Description: pointer.StringPtr("test description"),
},
},
},
}
Expect(k8sClient.Create(ctx, &cd)).Should(Succeed())
By("Install a patch trait used to test CUE module")
td := v1beta1.TraitDefinition{}
td.SetName(tdName)
td.SetNamespace(namespace)
td.Spec.AppliesToWorkloads = []string{"deployments.apps"}
td.Spec.Schematic = &common.Schematic{
CUE: &common.CUE{
Template: `patch: {
spec: template: {
metadata: labels: {
if parameter.type == "namespace" {
"app.namespace.virtual.group": parameter.group
}
if parameter.type == "cluster" {
"app.cluster.virtual.group": parameter.group
}
}
}
}
parameter: {
group: *"default" | string
type: *"namespace" | string
}`,
},
}
Expect(k8sClient.Create(ctx, &td)).Should(Succeed())
By("Verify ComponentDefinition and TraitDefinition are created successfully")
Eventually(func() error {
if err := k8sClient.Get(ctx, client.ObjectKey{Name: cdName, Namespace: namespace}, &v1beta1.ComponentDefinition{}); err != nil {
return err
}
if err := k8sClient.Get(ctx, client.ObjectKey{Name: tdName, Namespace: namespace}, &v1beta1.TraitDefinition{}); err != nil {
return err
}
return nil
}, 20*time.Second, 500*time.Millisecond).Should(Succeed())
By("Add 'deployments.apps' to scaler's appliesToWorkloads")
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("")
Expect(k8sClient.Patch(ctx, &scalerTd, client.Merge)).Should(Succeed())
})
AfterEach(func() {
By("Clean up resources after a test")
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 := v1beta1.TraitDefinition{}
Expect(k8sClient.Get(ctx, client.ObjectKey{Name: "scaler", Namespace: "vela-system"}, &scalerTd)).Should(Succeed())
scalerTd.Spec.AppliesToWorkloads = []string{"webservice", "worker"}
scalerTd.SetResourceVersion("")
Expect(k8sClient.Patch(ctx, &scalerTd, client.Merge)).Should(Succeed())
})
It("Test deploy an application containing kube module", func() {
app = v1beta1.Application{
ObjectMeta: metav1.ObjectMeta{
Name: appName,
Namespace: namespace,
},
Spec: v1beta1.ApplicationSpec{
Components: []common.ApplicationComponent{
{
Name: compName,
Type: cdName,
Properties: util.Object2RawExtension(map[string]interface{}{
"image": "nginx:1.14.0",
}),
Traits: []common.ApplicationTrait{
{
Type: "scaler",
Properties: util.Object2RawExtension(map[string]interface{}{
"replicas": 2,
}),
},
{
Type: tdName,
Properties: util.Object2RawExtension(map[string]interface{}{
"group": "my-group",
"type": "cluster",
}),
},
},
},
},
},
}
By("Create application")
Eventually(func() error {
return k8sClient.Create(ctx, app.DeepCopy())
}, 10*time.Second, 500*time.Millisecond).Should(Succeed())
By("Verify the workload(deployment) is created successfully")
deploy := &appsv1.Deployment{}
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 {
deploy := &appsv1.Deployment{}
if err := k8sClient.Get(ctx, client.ObjectKey{Name: deployName, Namespace: namespace}, deploy); err != nil {
return false
}
By("Verify patch trait is applied")
templateLabels := deploy.Spec.Template.Labels
if templateLabels["app.cluster.virtual.group"] != "my-group" {
return false
}
By("Verify scaler trait is applied")
if *deploy.Spec.Replicas != 2 {
return false
}
By("Verify parameter is applied")
return deploy.Spec.Template.Spec.Containers[0].Image == "nginx:1.14.0"
}, 15*time.Second, 3*time.Second).Should(BeTrue())
By("Update the application")
app = v1beta1.Application{
ObjectMeta: metav1.ObjectMeta{
Name: appName,
Namespace: namespace,
},
Spec: v1beta1.ApplicationSpec{
Components: []common.ApplicationComponent{
{
Name: compName,
Type: cdName,
Properties: util.Object2RawExtension(map[string]interface{}{
"image": "nginx:1.14.1", // nginx:1.14.0 => nginx:1.14.1
}),
Traits: []common.ApplicationTrait{
{
Type: "scaler",
Properties: util.Object2RawExtension(map[string]interface{}{
"replicas": 3, // change 2 => 3
}),
},
{
Type: tdName,
Properties: util.Object2RawExtension(map[string]interface{}{
"group": "my-group-0", // change my-group => my-group-0
"type": "cluster",
}),
},
},
},
},
},
}
Expect(k8sClient.Patch(ctx, &app, client.Merge)).Should(Succeed())
By("Verify the workload(deployment) is created successfully")
deploy = &appsv1.Deployment{}
deployName = compName
By("Verify the changes are applied to the workload")
Eventually(func() bool {
deploy := &appsv1.Deployment{}
if err := k8sClient.Get(ctx, client.ObjectKey{Name: deployName, Namespace: namespace}, deploy); err != nil {
return false
}
By("Verify new patch trait is applied")
templateLabels := deploy.Spec.Template.Labels
if templateLabels["app.cluster.virtual.group"] != "my-group-0" {
return false
}
By("Verify new scaler trait is applied")
if *deploy.Spec.Replicas != 3 {
return false
}
By("Verify new parameter is applied")
return deploy.Spec.Template.Spec.Containers[0].Image == "nginx:1.14.1"
}, 60*time.Second, 10*time.Second).Should(BeTrue())
})
It("Test deploy an application containing kube module defined by workloadDefinition", func() {
workloaddef := v1beta1.WorkloadDefinition{}
workloaddef.SetName(wdName)
workloaddef.SetNamespace(namespace)
workloaddef.Spec.Reference = common.DefinitionReference{Name: "deployments.apps", Version: "v1"}
workloaddef.Spec.Schematic = &common.Schematic{
KUBE: &common.Kube{
Template: testTemplate(),
Parameters: []common.KubeParameter{
{
Name: "image",
ValueType: common.StringType,
FieldPaths: []string{"spec.template.spec.containers[0].image"},
Required: pointer.BoolPtr(true),
Description: pointer.StringPtr("test description"),
},
},
},
}
By("register workloadDefinition")
Expect(k8sClient.Create(ctx, &workloaddef)).Should(Succeed())
appTestName := "test-app-refer-to-workloaddef"
appTest := v1beta1.Application{
ObjectMeta: metav1.ObjectMeta{
Name: appTestName,
Namespace: namespace,
},
Spec: v1beta1.ApplicationSpec{
Components: []common.ApplicationComponent{
{
Name: compName,
Type: cdName,
Properties: util.Object2RawExtension(map[string]interface{}{
"image": "nginx:1.14.0",
}),
},
},
},
}
By("Create application")
Eventually(func() error {
return k8sClient.Create(ctx, appTest.DeepCopy())
}, 10*time.Second, 500*time.Millisecond).Should(Succeed())
By("Verify the workload(deployment) is created successfully")
deploy := &appsv1.Deployment{}
deployName := compName
Eventually(func() error {
return k8sClient.Get(ctx, client.ObjectKey{Name: deployName, Namespace: namespace}, deploy)
}, 15*time.Second, 3*time.Second).Should(Succeed())
})
It("Test store JSON schema of Kube parameter in ConfigMap", func() {
By("Get the ConfigMap")
cmName := fmt.Sprintf("component-schema-%s", cdName)
Eventually(func() error {
cm := &corev1.ConfigMap{}
if err := k8sClient.Get(ctx, client.ObjectKey{Name: cmName, Namespace: namespace}, cm); err != nil {
return err
}
if cm.Data[types.OpenapiV3JSONSchema] == "" {
return errors.New("json schema is not found in the ConfigMap")
}
return nil
}, 60*time.Second, 5*time.Second).Should(Succeed())
})
})