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 })