github.com/oam-dev/kubevela@v1.9.11/test/e2e-test/definition_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 "path/filepath" 23 "runtime" 24 "strings" 25 "time" 26 27 testdef "github.com/kubevela/pkg/util/test/definition" 28 . "github.com/onsi/ginkgo/v2" 29 . "github.com/onsi/gomega" 30 corev1 "k8s.io/api/core/v1" 31 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 32 "sigs.k8s.io/controller-runtime/pkg/client" 33 34 "github.com/oam-dev/kubevela/apis/core.oam.dev/common" 35 "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" 36 "github.com/oam-dev/kubevela/apis/types" 37 "github.com/oam-dev/kubevela/pkg/oam" 38 "github.com/oam-dev/kubevela/pkg/oam/util" 39 utilcommon "github.com/oam-dev/kubevela/pkg/utils/common" 40 ) 41 42 var _ = Describe("ComponentDefinition Normal tests", func() { 43 ctx := context.Background() 44 45 var namespace string 46 var ns corev1.Namespace 47 48 BeforeEach(func() { 49 namespace = randomNamespaceName("def-e2e-test") 50 ns = corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: namespace}} 51 52 Eventually(func() error { 53 return k8sClient.Create(ctx, &ns) 54 }, time.Second*3, time.Microsecond*300).Should(SatisfyAny(BeNil(), &util.AlreadyExistMatcher{})) 55 }) 56 57 AfterEach(func() { 58 By("Clean up resources after a test") 59 k8sClient.DeleteAllOf(ctx, &v1beta1.ComponentDefinition{}, client.InNamespace(namespace)) 60 k8sClient.DeleteAllOf(ctx, &v1beta1.WorkloadDefinition{}, client.InNamespace(namespace)) 61 k8sClient.DeleteAllOf(ctx, &v1beta1.TraitDefinition{}, client.InNamespace(namespace)) 62 k8sClient.DeleteAllOf(ctx, &v1beta1.WorkflowStepDefinition{}, client.InNamespace(namespace)) 63 k8sClient.DeleteAllOf(ctx, &v1beta1.DefinitionRevision{}, client.InNamespace(namespace)) 64 65 By(fmt.Sprintf("Delete the entire namespaceName %s", ns.Name)) 66 Expect(k8sClient.Delete(ctx, &ns, client.PropagationPolicy(metav1.DeletePropagationForeground))).Should(Succeed()) 67 }) 68 69 Context("Test dynamic admission control for componentDefinition", func() { 70 71 It("Test componentDefinition which only set type field", func() { 72 workDef := &v1beta1.WorkloadDefinition{ 73 TypeMeta: metav1.TypeMeta{ 74 Kind: "WorkloadDefinition", 75 APIVersion: "core.oam.dev/v1beta1", 76 }, 77 ObjectMeta: metav1.ObjectMeta{ 78 Name: "deployments.apps", 79 }, 80 Spec: v1beta1.WorkloadDefinitionSpec{ 81 Reference: common.DefinitionReference{ 82 Name: "deployments.apps", 83 Version: "v1", 84 }, 85 }, 86 } 87 workDef.SetNamespace(namespace) 88 Expect(k8sClient.Create(ctx, workDef)).Should(BeNil()) 89 getWd := new(v1beta1.WorkloadDefinition) 90 Eventually(func() error { 91 return k8sClient.Get(ctx, client.ObjectKey{Name: workDef.Name, Namespace: namespace}, getWd) 92 }, 15*time.Second, time.Second).Should(BeNil()) 93 94 cd := webServiceWithNoTemplate.DeepCopy() 95 cd.Spec.Workload.Definition = common.WorkloadGVK{} 96 cd.Spec.Workload.Type = "deployments.apps" 97 cd.SetNamespace(namespace) 98 cd.SetName("test-componentdef") 99 cd.Spec.Schematic.CUE.Template = webServiceV1Template 100 101 Eventually(func() error { 102 return k8sClient.Create(ctx, cd) 103 }, 5*time.Second, time.Second).Should(BeNil()) 104 105 defRev := new(v1beta1.DefinitionRevision) 106 Eventually(func() error { 107 return k8sClient.Get(ctx, client.ObjectKey{Name: "test-componentdef-v1", Namespace: namespace}, defRev) 108 }).Should(BeNil()) 109 }) 110 111 It("Test componentDefinition only set definition field", func() { 112 testCd := webServiceWithNoTemplate.DeepCopy() 113 testCd.Spec.Schematic.CUE.Template = webServiceV1Template 114 testCd.SetName("test-componentdef-v1") 115 testCd.SetNamespace(namespace) 116 Expect(k8sClient.Create(ctx, testCd)).Should(Succeed()) 117 118 By("check MutatingWebhook fill the type filed") 119 newCd := new(v1beta1.ComponentDefinition) 120 Eventually(func() error { 121 return k8sClient.Get(ctx, client.ObjectKey{Name: testCd.Name, Namespace: namespace}, newCd) 122 }, 15*time.Second, time.Second).Should(BeNil()) 123 124 Expect(newCd.Spec.Workload.Type).Should(Equal("deployments.apps")) 125 126 By("check workloadDefinition created by MutatingWebhook") 127 newWd := new(v1beta1.WorkloadDefinition) 128 wdName := newCd.Spec.Workload.Type 129 Eventually(func() error { 130 return k8sClient.Get(ctx, client.ObjectKey{Name: wdName, Namespace: namespace}, newWd) 131 }, 15*time.Second, time.Second).Should(BeNil()) 132 133 Expect(newWd.Spec.Reference.Name).Should(Equal(wdName)) 134 Expect(newWd.Spec.Reference.Version).To(Equal("v1")) 135 }) 136 137 It("Test componentDefinition which definition and type fields are all empty", func() { 138 testCd1 := webServiceWithNoTemplate.DeepCopy() 139 testCd1.SetName("test-componentdef-v2") 140 testCd1.Spec.Workload.Definition = common.WorkloadGVK{} 141 testCd1.Spec.Schematic.CUE.Template = webServiceV1Template 142 testCd1.SetNamespace(namespace) 143 Expect(k8sClient.Create(ctx, testCd1)).Should(BeNil()) 144 145 newCd := new(v1beta1.ComponentDefinition) 146 Eventually(func() error { 147 return k8sClient.Get(ctx, client.ObjectKey{Name: testCd1.Name, Namespace: namespace}, newCd) 148 }, 15*time.Second, time.Second).Should(BeNil()) 149 Expect(newCd.Spec.Workload.Type).Should(Equal(types.AutoDetectWorkloadDefinition)) 150 }) 151 152 It("Test componentDefinition which definition and type point to same workload type", func() { 153 testCd2 := webServiceWithNoTemplate.DeepCopy() 154 testCd2.SetName("test-componentdef-v3") 155 testCd2.Spec.Workload.Type = "deployments.apps" 156 testCd2.Spec.Schematic.CUE.Template = webServiceV1Template 157 testCd2.SetNamespace(namespace) 158 Expect(k8sClient.Create(ctx, testCd2)).Should(Succeed()) 159 }) 160 161 It("Test componentDefinition which definition and type point to different workload type", func() { 162 testCd3 := webServiceWithNoTemplate.DeepCopy() 163 testCd3.SetName("test-componentdef-v4") 164 testCd3.Spec.Workload.Type = "jobs.batch" 165 testCd3.Spec.Schematic.CUE.Template = webServiceV1Template 166 testCd3.SetNamespace(namespace) 167 Expect(k8sClient.Create(ctx, testCd3)).Should(HaveOccurred()) 168 }) 169 170 It("Test componentDefinition which specify the name of definitionRevision", func() { 171 By("create componentDefinition") 172 cd := webServiceWithNoTemplate.DeepCopy() 173 cd.SetNamespace(namespace) 174 cd.SetName("test-def-specify-revision") 175 cd.SetAnnotations(map[string]string{ 176 oam.AnnotationDefinitionRevisionName: "1.1.1", 177 }) 178 cd.Spec.Schematic.CUE.Template = webServiceV1Template 179 Expect(k8sClient.Create(ctx, cd)).Should(Succeed()) 180 181 By("check definitionRevision created by controller") 182 defRev := new(v1beta1.DefinitionRevision) 183 Eventually(func() error { 184 return k8sClient.Get(ctx, client.ObjectKey{Name: fmt.Sprintf("%s-v%s", cd.Name, "1.1.1"), Namespace: namespace}, defRev) 185 }, 15*time.Second, time.Second).Should(BeNil()) 186 187 By("update componentDefinition") 188 oldCd := new(v1beta1.ComponentDefinition) 189 Eventually(func() error { 190 return k8sClient.Get(ctx, client.ObjectKey{Name: cd.Name, Namespace: namespace}, oldCd) 191 }, 15*time.Second, time.Second).Should(BeNil()) 192 193 newCd := oldCd.DeepCopy() 194 cd.Spec.Schematic.CUE.Template = webServiceV2Template 195 Expect(k8sClient.Create(ctx, newCd)).Should(HaveOccurred()) 196 }) 197 }) 198 199 Context("Test dynamic admission control for traitDefinition", func() { 200 It("Test traitDefinition which specify the name of definitionRevision", func() { 201 By("create traitDefinition") 202 td := exposeWithNoTemplate.DeepCopy() 203 td.SetNamespace(namespace) 204 td.SetName("test-td-specify-revision") 205 td.SetAnnotations(map[string]string{ 206 oam.AnnotationDefinitionRevisionName: "1.1.1", 207 }) 208 td.Spec.Schematic.CUE.Template = exposeV1Template 209 Expect(k8sClient.Create(ctx, td)).Should(Succeed()) 210 211 By("check definitionRevision created by controller") 212 defRev := new(v1beta1.DefinitionRevision) 213 Eventually(func() error { 214 return k8sClient.Get(ctx, client.ObjectKey{Name: fmt.Sprintf("%s-v%s", td.Name, "1.1.1"), Namespace: namespace}, defRev) 215 }, 15*time.Second, time.Second).Should(BeNil()) 216 217 By("update traitDefinition spec, should be ejected") 218 oldTd := new(v1beta1.TraitDefinition) 219 Eventually(func() error { 220 return k8sClient.Get(ctx, client.ObjectKey{Name: td.Name, Namespace: namespace}, oldTd) 221 }, 15*time.Second, time.Second).Should(BeNil()) 222 223 newTd := oldTd.DeepCopy() 224 newTd.Spec.Schematic.CUE.Template = exposeV2Template 225 Expect(k8sClient.Create(ctx, newTd)).Should(HaveOccurred()) 226 }) 227 }) 228 229 It("Test notification step definition", func() { 230 By("Install notification workflow step definition") 231 _, file, _, _ := runtime.Caller(0) 232 Expect(testdef.InstallDefinitionFromYAML(ctx, k8sClient, filepath.Join(file, "../../../charts/vela-core/templates/defwithtemplate/notification.yaml"), func(s string) string { 233 return strings.ReplaceAll(s, `{{ include "systemDefinitionNamespace" . }}`, "vela-system") 234 })).Should(SatisfyAny(Succeed(), &util.AlreadyExistMatcher{})) 235 236 By("Create a secret for the notification step") 237 Expect(k8sClient.Create(ctx, &corev1.Secret{ 238 ObjectMeta: metav1.ObjectMeta{ 239 Name: "my-secret", 240 Namespace: namespace, 241 }, 242 StringData: map[string]string{"url": "https://kubevela.io"}, 243 })).Should(SatisfyAny(Succeed(), &util.AlreadyExistMatcher{})) 244 245 By("Create application with notification step consuming a secret") 246 var newApp v1beta1.Application 247 Expect(utilcommon.ReadYamlToObject("testdata/app/app_notification_secret.yaml", &newApp)).Should(BeNil()) 248 newApp.Namespace = namespace 249 Expect(k8sClient.Create(ctx, &newApp)).Should(BeNil()) 250 251 By("Verify application is running") 252 verifyApplicationPhase(context.TODO(), newApp.Namespace, newApp.Name, common.ApplicationRunning) 253 254 By("Create application with notification step") 255 newApp = v1beta1.Application{} 256 Expect(utilcommon.ReadYamlToObject("testdata/app/app_notification.yaml", &newApp)).Should(BeNil()) 257 newApp.Namespace = namespace 258 Expect(k8sClient.Create(ctx, &newApp)).Should(BeNil()) 259 260 By("Verify application is running") 261 verifyApplicationPhase(context.TODO(), newApp.Namespace, newApp.Name, common.ApplicationRunning) 262 }) 263 })