github.com/oam-dev/kubevela@v1.9.11/test/e2e-test/resource_policy_test.go (about)

     1  /*
     2  Copyright 2021 The KubeVela Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8  	http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package controllers_test
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  	"time"
    23  
    24  	. "github.com/onsi/ginkgo/v2"
    25  	. "github.com/onsi/gomega"
    26  	v13 "k8s.io/api/apps/v1"
    27  	v1 "k8s.io/api/core/v1"
    28  	"k8s.io/apimachinery/pkg/api/errors"
    29  	v12 "k8s.io/apimachinery/pkg/apis/meta/v1"
    30  	"k8s.io/apimachinery/pkg/runtime"
    31  	"k8s.io/apimachinery/pkg/types"
    32  	"k8s.io/utils/pointer"
    33  	"sigs.k8s.io/controller-runtime/pkg/client"
    34  
    35  	"github.com/kubevela/pkg/util/rand"
    36  
    37  	common2 "github.com/oam-dev/kubevela/apis/core.oam.dev/common"
    38  	"github.com/oam-dev/kubevela/apis/core.oam.dev/condition"
    39  	"github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
    40  	"github.com/oam-dev/kubevela/pkg/utils/common"
    41  )
    42  
    43  var _ = Describe("Application Resource-Related Policy Tests", func() {
    44  	ctx := context.Background()
    45  	var namespace string
    46  	BeforeEach(func() {
    47  		namespace = "test-resource-policy-" + rand.RandomString(4)
    48  		Expect(k8sClient.Create(ctx, &v1.Namespace{ObjectMeta: v12.ObjectMeta{Name: namespace}})).Should(Succeed())
    49  	})
    50  
    51  	AfterEach(func() {
    52  		ns := &v1.Namespace{}
    53  		Expect(k8sClient.Get(ctx, types.NamespacedName{Name: namespace}, ns)).Should(Succeed())
    54  		Expect(k8sClient.Delete(ctx, ns)).Should(Succeed())
    55  	})
    56  
    57  	It("Test ApplyOnce Policy", func() {
    58  		By("create apply-once app(apply-once disabled)")
    59  		app := &v1beta1.Application{}
    60  		Expect(common.ReadYamlToObject("testdata/app/app_apply_once.yaml", app)).Should(BeNil())
    61  		app.SetNamespace(namespace)
    62  		Expect(k8sClient.Create(ctx, app)).Should(Succeed())
    63  		appKey := client.ObjectKeyFromObject(app)
    64  		Eventually(func(g Gomega) {
    65  			g.Expect(k8sClient.Get(ctx, appKey, app)).Should(Succeed())
    66  			g.Expect(app.Status.Phase).Should(Equal(common2.ApplicationRunning))
    67  		}, 30*time.Second, time.Second*3).Should(Succeed())
    68  
    69  		By("test state-keep")
    70  		deploy := &v13.Deployment{}
    71  		Eventually(func(g Gomega) {
    72  			g.Expect(k8sClient.Get(ctx, types.NamespacedName{Namespace: namespace, Name: "hello-world"}, deploy)).Should(Succeed())
    73  			deploy.Spec.Replicas = pointer.Int32(0)
    74  			g.Expect(k8sClient.Update(ctx, deploy)).Should(Succeed())
    75  		}, 10*time.Second, time.Second*2).Should(Succeed())
    76  		Eventually(func(g Gomega) {
    77  			g.Expect(k8sClient.Get(ctx, appKey, app)).Should(Succeed())
    78  			app.Status.SetConditions(condition.Condition{Type: "StateKeep", Status: "True", Reason: condition.ReasonAvailable, LastTransitionTime: v12.Now()})
    79  			g.Expect(k8sClient.Status().Update(ctx, app)).Should(Succeed())
    80  		}, 10*time.Second, time.Second*2).Should(Succeed())
    81  		Eventually(func(g Gomega) {
    82  			g.Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(deploy), deploy)).Should(Succeed())
    83  			g.Expect(deploy.Spec.Replicas).Should(Equal(pointer.Int32(1)))
    84  		}, 30*time.Second, time.Second*3).Should(Succeed())
    85  
    86  		By("test apply-once policy(apply-once enabled)")
    87  		Eventually(func(g Gomega) {
    88  			g.Expect(k8sClient.Get(ctx, appKey, app)).Should(Succeed())
    89  			app.Spec.Policies[0].Properties = &runtime.RawExtension{Raw: []byte(`{"enable":true}`)}
    90  			g.Expect(k8sClient.Update(ctx, app)).Should(Succeed())
    91  		}, 10*time.Second).Should(Succeed())
    92  		Eventually(func(g Gomega) {
    93  			g.Expect(k8sClient.Get(ctx, appKey, app)).Should(Succeed())
    94  			g.Expect(app.Status.ObservedGeneration).Should(Equal(app.Generation))
    95  			g.Expect(app.Status.Phase).Should(Equal(common2.ApplicationRunning))
    96  		}, 30*time.Second).Should(Succeed())
    97  		Eventually(func(g Gomega) {
    98  			g.Expect(k8sClient.Get(ctx, types.NamespacedName{Namespace: namespace, Name: "hello-world"}, deploy)).Should(Succeed())
    99  			deploy.Spec.Replicas = pointer.Int32(0)
   100  			g.Expect(k8sClient.Update(ctx, deploy)).Should(Succeed())
   101  		}, 10*time.Second).Should(Succeed())
   102  		Eventually(func(g Gomega) {
   103  			g.Expect(k8sClient.Get(ctx, appKey, app)).Should(Succeed())
   104  			app.Status.SetConditions(condition.Condition{Type: "ApplyOnce", Status: "True", Reason: condition.ReasonAvailable, LastTransitionTime: v12.Now()})
   105  			g.Expect(k8sClient.Status().Update(ctx, app)).Should(Succeed())
   106  		}, 10*time.Second).Should(Succeed())
   107  		time.Sleep(30 * time.Second)
   108  		Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(deploy), deploy)).Should(Succeed())
   109  		Expect(deploy.Spec.Replicas).Should(Equal(pointer.Int32(0)))
   110  	})
   111  
   112  	It("Test GarbageCollect Policy", func() {
   113  		By("create garbage-collect app")
   114  		app := &v1beta1.Application{}
   115  		Expect(common.ReadYamlToObject("testdata/app/app_garbage_collect.yaml", app)).Should(BeNil())
   116  		app.SetNamespace(namespace)
   117  		Expect(k8sClient.Create(ctx, app)).Should(Succeed())
   118  		appKey := client.ObjectKeyFromObject(app)
   119  		Eventually(func(g Gomega) {
   120  			g.Expect(k8sClient.Get(ctx, appKey, app)).Should(Succeed())
   121  			g.Expect(app.Status.Phase).Should(Equal(common2.ApplicationRunning))
   122  		}, 30*time.Second).Should(Succeed())
   123  
   124  		By("upgrade to v2 (same component)")
   125  		Eventually(func(g Gomega) {
   126  			g.Expect(k8sClient.Get(ctx, appKey, app)).Should(Succeed())
   127  			app.Spec.Components[0].Traits[0].Properties = &runtime.RawExtension{Raw: []byte(`{"port":[8001]}`)}
   128  			g.Expect(k8sClient.Update(ctx, app)).Should(Succeed())
   129  		}, 10*time.Second).Should(Succeed())
   130  		Eventually(func(g Gomega) {
   131  			g.Expect(k8sClient.Get(ctx, appKey, app)).Should(Succeed())
   132  			g.Expect(app.Status.ObservedGeneration).Should(Equal(app.Generation))
   133  			g.Expect(app.Status.Phase).Should(Equal(common2.ApplicationRunning))
   134  		}, 30*time.Second).Should(Succeed())
   135  
   136  		By("upgrade to v3 (new component)")
   137  		Eventually(func(g Gomega) {
   138  			g.Expect(k8sClient.Get(ctx, appKey, app)).Should(Succeed())
   139  			app.Spec.Components[0].Name = "hello-world-new"
   140  			g.Expect(k8sClient.Update(ctx, app)).Should(Succeed())
   141  		}, 10*time.Second).Should(Succeed())
   142  		Eventually(func(g Gomega) {
   143  			g.Expect(k8sClient.Get(ctx, appKey, app)).Should(Succeed())
   144  			g.Expect(app.Status.ObservedGeneration).Should(Equal(app.Generation))
   145  			g.Expect(app.Status.Phase).Should(Equal(common2.ApplicationRunning))
   146  		}, 30*time.Second).Should(Succeed())
   147  
   148  		By("upgrade to v4 (new component)")
   149  		Eventually(func(g Gomega) {
   150  			g.Expect(k8sClient.Get(ctx, appKey, app)).Should(Succeed())
   151  			app.Spec.Components[0].Name = "hello-world-latest"
   152  			g.Expect(k8sClient.Update(ctx, app)).Should(Succeed())
   153  		}, 10*time.Second).Should(Succeed())
   154  		Eventually(func(g Gomega) {
   155  			g.Expect(k8sClient.Get(ctx, appKey, app)).Should(Succeed())
   156  			g.Expect(app.Status.ObservedGeneration).Should(Equal(app.Generation))
   157  			g.Expect(app.Status.Phase).Should(Equal(common2.ApplicationRunning))
   158  		}, 30*time.Second).Should(Succeed())
   159  
   160  		deployments := &v13.DeploymentList{}
   161  		Expect(k8sClient.List(ctx, deployments, client.InNamespace(namespace))).Should(Succeed())
   162  		Expect(len(deployments.Items)).Should(Equal(3))
   163  		services := &v1.ServiceList{}
   164  		Expect(k8sClient.List(ctx, services, client.InNamespace(namespace))).Should(Succeed())
   165  		Expect(len(services.Items)).Should(Equal(3))
   166  
   167  		By("delete v3")
   168  		rt := &v1beta1.ResourceTracker{}
   169  		Expect(k8sClient.Get(ctx, types.NamespacedName{Name: fmt.Sprintf("%s-v3-%s", app.Name, namespace)}, rt)).Should(Succeed())
   170  		Expect(k8sClient.Delete(ctx, rt)).Should(Succeed())
   171  		Eventually(func(g Gomega) {
   172  			err := k8sClient.Get(ctx, types.NamespacedName{Name: fmt.Sprintf("%s-v3-%s", app.Name, namespace)}, rt)
   173  			g.Expect(errors.IsNotFound(err)).Should(BeTrue())
   174  		}, 15*time.Second).Should(Succeed())
   175  		Expect(k8sClient.List(ctx, deployments, client.InNamespace(namespace))).Should(Succeed())
   176  		Expect(len(deployments.Items)).Should(Equal(2))
   177  		Expect(k8sClient.List(ctx, services, client.InNamespace(namespace))).Should(Succeed())
   178  		Expect(len(services.Items)).Should(Equal(3))
   179  
   180  		By("delete latest deploy, auto gc rt v4")
   181  		deploy := &v13.Deployment{}
   182  		Expect(k8sClient.Get(ctx, types.NamespacedName{Namespace: namespace, Name: "hello-world-latest"}, deploy)).Should(Succeed())
   183  		Expect(k8sClient.Delete(ctx, deploy)).Should(Succeed())
   184  		Eventually(func(g Gomega) {
   185  			g.Expect(k8sClient.Get(ctx, appKey, app)).Should(Succeed())
   186  			app.Status.SetConditions(condition.Condition{Type: "GC", Status: "True", Reason: condition.ReasonAvailable, LastTransitionTime: v12.Now()})
   187  			g.Expect(k8sClient.Status().Update(ctx, app)).Should(Succeed())
   188  		}, 10*time.Second).Should(Succeed())
   189  		Eventually(func(g Gomega) {
   190  			err := k8sClient.Get(ctx, types.NamespacedName{Name: fmt.Sprintf("%s-%s-v4", app.Name, namespace)}, rt)
   191  			g.Expect(errors.IsNotFound(err)).Should(BeTrue())
   192  		}, 15*time.Second).Should(Succeed())
   193  		Expect(k8sClient.List(ctx, deployments, client.InNamespace(namespace))).Should(Succeed())
   194  		Expect(len(deployments.Items)).Should(Equal(1))
   195  		Expect(k8sClient.List(ctx, services, client.InNamespace(namespace))).Should(Succeed())
   196  		Expect(len(services.Items)).Should(Equal(3))
   197  
   198  		By("delete application")
   199  		Expect(k8sClient.Get(ctx, appKey, app)).Should(Succeed())
   200  		Expect(k8sClient.Delete(ctx, app)).Should(Succeed())
   201  		Eventually(func(g Gomega) {
   202  			err := k8sClient.Get(ctx, appKey, app)
   203  			g.Expect(errors.IsNotFound(err)).Should(BeTrue())
   204  		}, 15*time.Second).Should(Succeed())
   205  		Expect(k8sClient.List(ctx, deployments, client.InNamespace(namespace))).Should(Succeed())
   206  		Expect(len(deployments.Items)).Should(Equal(0))
   207  		Expect(k8sClient.List(ctx, services, client.InNamespace(namespace))).Should(Succeed())
   208  		Expect(len(services.Items)).Should(Equal(0))
   209  	})
   210  
   211  	It("Test state keep during suspending", func() {
   212  		By("create suspending app")
   213  		app := &v1beta1.Application{}
   214  		Expect(common.ReadYamlToObject("testdata/app/app_suspending.yaml", app)).Should(BeNil())
   215  		app.SetNamespace(namespace)
   216  		Expect(k8sClient.Create(ctx, app)).Should(Succeed())
   217  		appKey := client.ObjectKeyFromObject(app)
   218  		Eventually(func(g Gomega) {
   219  			g.Expect(k8sClient.Get(ctx, appKey, app)).Should(Succeed())
   220  			g.Expect(app.Status.Phase).Should(Equal(common2.ApplicationWorkflowSuspending))
   221  		}, 30*time.Second).Should(Succeed())
   222  
   223  		By("test suspending app state-keep")
   224  		deploy := &v13.Deployment{}
   225  		Eventually(func(g Gomega) {
   226  			g.Expect(k8sClient.Get(ctx, types.NamespacedName{Namespace: namespace, Name: "busybox"}, deploy)).Should(Succeed())
   227  			deploy.Spec.Replicas = pointer.Int32(0)
   228  			g.Expect(k8sClient.Update(ctx, deploy)).Should(Succeed())
   229  		}, 10*time.Second).Should(Succeed())
   230  		Eventually(func(g Gomega) {
   231  			g.Expect(k8sClient.Get(ctx, appKey, app)).Should(Succeed())
   232  			app.Status.SetConditions(condition.Condition{Type: "StateKeep", Status: "True", Reason: condition.ReasonAvailable, LastTransitionTime: v12.Now()})
   233  			g.Expect(k8sClient.Status().Update(ctx, app)).Should(Succeed())
   234  		}, 10*time.Second).Should(Succeed())
   235  		Eventually(func(g Gomega) {
   236  			g.Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(deploy), deploy)).Should(Succeed())
   237  			g.Expect(deploy.Spec.Replicas).Should(Equal(pointer.Int32(1)))
   238  		}, 30*time.Second).Should(Succeed())
   239  	})
   240  })