Skip to content

Commit

Permalink
add test cases
Browse files Browse the repository at this point in the history
  • Loading branch information
Eikykun committed Dec 26, 2023
1 parent c65c619 commit 36fa388
Show file tree
Hide file tree
Showing 4 changed files with 369 additions and 9 deletions.
82 changes: 82 additions & 0 deletions pkg/controllers/controllers_suit_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
Copyright 2023 The KusionStack 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

import (
"context"
"os"
"path/filepath"

. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
appsv1 "k8s.io/api/apps/v1"
"k8s.io/client-go/kubernetes/scheme"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/envtest"
logf "sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/log/zap"
"sigs.k8s.io/controller-runtime/pkg/manager"

appsv1alpha1 "kusionstack.io/operating/apis/apps/v1alpha1"
"kusionstack.io/operating/pkg/utils/inject"
)

var (
env *envtest.Environment
mgr manager.Manager
ctx context.Context
cancel context.CancelFunc
c client.Client
)

var _ = BeforeSuite(func() {
By("bootstrapping test environment")

ctx, cancel = context.WithCancel(context.TODO())
logf.SetLogger(zap.New(zap.WriteTo(os.Stdout), zap.UseDevMode(true)))

env = &envtest.Environment{
CRDDirectoryPaths: []string{filepath.Join("..", "..", "config", "crd", "bases")},
}

config, err := env.Start()
Expect(err).NotTo(HaveOccurred())
Expect(config).NotTo(BeNil())

sch := scheme.Scheme
Expect(appsv1.SchemeBuilder.AddToScheme(sch)).NotTo(HaveOccurred())
Expect(appsv1alpha1.SchemeBuilder.AddToScheme(sch)).NotTo(HaveOccurred())
mgr, err = manager.New(config, manager.Options{
MetricsBindAddress: "0",
NewCache: inject.NewCacheWithFieldIndex,
})
Expect(err).NotTo(HaveOccurred())
c = mgr.GetClient()
Expect(AddToManager(mgr)).NotTo(HaveOccurred())

go func() {
err = mgr.Start(ctx)
Expect(err).NotTo(HaveOccurred())
}()
})

var _ = AfterSuite(func() {
By("tearing down the test environment")
cancel()
err := env.Stop()
Expect(err).NotTo(HaveOccurred())
})
41 changes: 41 additions & 0 deletions pkg/controllers/controllers_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
Copyright 2023 The KusionStack 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

import (
"fmt"
"testing"

. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)

func TestControllers(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Controllers Tests")
}

var _ = Describe("test controllers", func() {
Describe("other controller tests", func() {
It("test case a", func() {
fmt.Println("case a tests")
})
AfterEach(func() {

})
})
})
245 changes: 241 additions & 4 deletions pkg/controllers/poddecoration/poddecoration_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -465,10 +465,6 @@ var _ = Describe("PodDecoration controller", func() {

getter, err := collasetutils.NewPodDecorationGetter(ctx, c, testcase)
Expect(err).Should(BeNil())
if len(getter.GetLatestDecorations()) != 0 {
bt, _ := json.Marshal(getter.GetLatestDecorations()[0])
fmt.Printf("test : %s\n", string(bt))
}
Expect(len(getter.GetLatestDecorations())).Should(Equal(0))

Eventually(func() bool {
Expand Down Expand Up @@ -694,7 +690,248 @@ var _ = Describe("PodDecoration controller", func() {
})

It("test no group PodDecoration", func() {
testcase := "test-pd-4"
Expect(createNamespace(c, testcase)).Should(BeNil())
collaSetA := &appsv1alpha1.CollaSet{
ObjectMeta: metav1.ObjectMeta{
Namespace: testcase,
Name: "foo-a",
},
Spec: appsv1alpha1.CollaSetSpec{
Replicas: int32Pointer(2),
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"app": "foo",
"zone": "a",
},
},
Template: corev1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: map[string]string{
"app": "foo",
"zone": "a",
},
},
Spec: corev1.PodSpec{
Containers: []corev1.Container{
{
Name: "foo",
Image: "nginx:v1",
},
},
},
},
},
}
podDecorationA := &appsv1alpha1.PodDecoration{
ObjectMeta: metav1.ObjectMeta{
Namespace: testcase,
Name: "foo-a",
},
Spec: appsv1alpha1.PodDecorationSpec{
HistoryLimit: 5,
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"app": "foo",
},
},
InjectStrategy: appsv1alpha1.PodDecorationInjectStrategy{
Group: "group-a",
Weight: int32Pointer(10),
},
UpdateStrategy: appsv1alpha1.PodDecorationUpdateStrategy{
RollingUpdate: &appsv1alpha1.PodDecorationRollingUpdate{
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{},
},
},
},
Template: appsv1alpha1.PodDecorationPodTemplate{
Containers: []*appsv1alpha1.ContainerPatch{
{
InjectPolicy: appsv1alpha1.AfterPrimaryContainer,
Container: corev1.Container{
Name: "sidecar-1",
Image: "nginx:v2",
},
},
},
},
},
}
podDecorationB := &appsv1alpha1.PodDecoration{
ObjectMeta: metav1.ObjectMeta{
Namespace: testcase,
Name: "foo-b",
},
Spec: appsv1alpha1.PodDecorationSpec{
HistoryLimit: 5,
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"app": "foo",
},
},
InjectStrategy: appsv1alpha1.PodDecorationInjectStrategy{
Weight: int32Pointer(10),
},
Template: appsv1alpha1.PodDecorationPodTemplate{
Containers: []*appsv1alpha1.ContainerPatch{
{
InjectPolicy: appsv1alpha1.AfterPrimaryContainer,
Container: corev1.Container{
Name: "sidecar-2",
Image: "nginx:v3",
},
},
},
},
},
}
podDecorationC := &appsv1alpha1.PodDecoration{
ObjectMeta: metav1.ObjectMeta{
Namespace: testcase,
Name: "foo-c",
},
Spec: appsv1alpha1.PodDecorationSpec{
HistoryLimit: 5,
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"app": "foo",
},
},
InjectStrategy: appsv1alpha1.PodDecorationInjectStrategy{
Weight: int32Pointer(11),
},
Template: appsv1alpha1.PodDecorationPodTemplate{
Containers: []*appsv1alpha1.ContainerPatch{
{
InjectPolicy: appsv1alpha1.AfterPrimaryContainer,
Container: corev1.Container{
Name: "sidecar-3",
Image: "nginx:v4",
},
},
},
},
},
}
Expect(c.Create(ctx, podDecorationA)).Should(BeNil())
Eventually(func() bool {
if err := c.Get(ctx, types.NamespacedName{Name: podDecorationA.Name, Namespace: testcase}, podDecorationA); err == nil {
if podDecorationA.Status.IsEffective != nil {
return *podDecorationA.Status.IsEffective
}
}
return false
}, 5*time.Second, 1*time.Second).Should(BeTrue())
Expect(c.Create(ctx, collaSetA)).Should(BeNil())
podList := &corev1.PodList{}
// 2 pods injected by PodDecoration-A
Eventually(func() int {
cnt := 0
Expect(c.List(ctx, podList, client.InNamespace(testcase))).Should(BeNil())
for _, po := range podList.Items {
if len(po.Spec.Containers) == 2 {
cnt++
}
}
return cnt
}, 5*time.Second, 1*time.Second).Should(BeEquivalentTo(2))

Eventually(func() bool {
if err := c.Get(ctx, types.NamespacedName{Name: podDecorationA.Name, Namespace: testcase}, podDecorationA); err == nil {
return podDecorationA.Status.CurrentRevision == podDecorationA.Status.UpdatedRevision
}
return false
}, 5*time.Second, 1*time.Second).Should(BeTrue())

// create PodDecoration-B
Expect(c.Create(ctx, podDecorationB)).Should(BeNil())

// 2 pods during ops
Eventually(func() int {
Expect(c.List(ctx, podList, client.InNamespace(testcase))).ShouldNot(HaveOccurred())
cnt := 0
for i := range podList.Items {
if podopslifecycle.IsDuringOps(collasetutils.UpdateOpsLifecycleAdapter, &podList.Items[i]) {
cnt++
}
}
return cnt
}, 5*time.Second, 1*time.Second).Should(BeEquivalentTo(2))
// allow Pod to do update
Expect(c.List(ctx, podList, client.InNamespace(testcase))).ShouldNot(HaveOccurred())
for i := range podList.Items {
pod := &podList.Items[i]
// allow Pod to do update
Expect(updatePodWithRetry(ctx, c, pod.Namespace, pod.Name, func(pod *corev1.Pod) bool {
labelOperate := fmt.Sprintf("%s/%s", appsv1alpha1.PodOperateLabelPrefix, collasetutils.UpdateOpsLifecycleAdapter.GetID())
pod.Labels[labelOperate] = fmt.Sprintf("%d", time.Now().UnixNano())
return true
})).Should(BeNil())
}
// 2 pods inject PodDecoration-B
Eventually(func() int {
Expect(c.List(ctx, podList, client.InNamespace(testcase))).Should(BeNil())
Expect(c.Get(ctx, types.NamespacedName{Name: podDecorationB.Name, Namespace: podDecorationB.Namespace}, podDecorationB)).Should(BeNil())
updatedCnt := 0
for _, po := range podList.Items {
info := utilspoddecoration.GetDecorationRevisionInfo(&po)
if info.Size() == 2 &&
info.GetRevision(podDecorationB.Name) != nil &&
*info.GetRevision(podDecorationB.Name) == podDecorationB.Status.UpdatedRevision &&
info.GetRevision(podDecorationA.Name) != nil &&
*info.GetRevision(podDecorationA.Name) == podDecorationA.Status.UpdatedRevision {
updatedCnt++
}
}
return updatedCnt
}, 5*time.Second, 1*time.Second).Should(BeEquivalentTo(2))

// create PodDecoration-C
Expect(c.Create(ctx, podDecorationC)).Should(BeNil())
// 2 pods during ops
Eventually(func() int {
Expect(c.List(ctx, podList, client.InNamespace(testcase))).ShouldNot(HaveOccurred())
cnt := 0
for i := range podList.Items {
if podopslifecycle.IsDuringOps(collasetutils.UpdateOpsLifecycleAdapter, &podList.Items[i]) {
cnt++
}
}
return cnt
}, 5*time.Second, 1*time.Second).Should(BeEquivalentTo(2))
// allow Pod to do update
Expect(c.List(ctx, podList, client.InNamespace(testcase))).ShouldNot(HaveOccurred())
for i := range podList.Items {
pod := &podList.Items[i]
// allow Pod to do update
Expect(updatePodWithRetry(ctx, c, pod.Namespace, pod.Name, func(pod *corev1.Pod) bool {
labelOperate := fmt.Sprintf("%s/%s", appsv1alpha1.PodOperateLabelPrefix, collasetutils.UpdateOpsLifecycleAdapter.GetID())
pod.Labels[labelOperate] = fmt.Sprintf("%d", time.Now().UnixNano())
return true
})).Should(BeNil())
}
// 2 pods inject PodDecoration-C
Eventually(func() int {
Expect(c.List(ctx, podList, client.InNamespace(testcase))).Should(BeNil())
Expect(c.Get(ctx, types.NamespacedName{Name: podDecorationC.Name, Namespace: podDecorationC.Namespace}, podDecorationC)).Should(BeNil())
updatedCnt := 0
for _, po := range podList.Items {
info := utilspoddecoration.GetDecorationRevisionInfo(&po)
if info.Size() == 3 {
updatedCnt++
}
}
return updatedCnt
}, 5*time.Second, 1*time.Second).Should(BeEquivalentTo(2))
Expect(len(podList.Items[0].Spec.Containers)).Should(BeEquivalentTo(4))
// B -> C -> A
// foo -> sidecar-3 -> sidecar-2 -> sidecar-1
Expect(podList.Items[0].Spec.Containers[0].Name).Should(BeEquivalentTo("foo"))
Expect(podList.Items[0].Spec.Containers[1].Name).Should(BeEquivalentTo("sidecar-3"))
Expect(podList.Items[0].Spec.Containers[2].Name).Should(BeEquivalentTo("sidecar-2"))
Expect(podList.Items[0].Spec.Containers[3].Name).Should(BeEquivalentTo("sidecar-1"))
})
})

Expand Down
Loading

0 comments on commit 36fa388

Please sign in to comment.