github.com/oam-dev/kubevela@v1.9.11/test/e2e-multicluster-test/multicluster_cli_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 e2e_multicluster_test 18 19 import ( 20 "context" 21 "io" 22 "net/http" 23 "os" 24 "os/exec" 25 "strings" 26 "time" 27 28 . "github.com/onsi/ginkgo/v2" 29 . "github.com/onsi/gomega" 30 "github.com/onsi/gomega/gbytes" 31 "github.com/onsi/gomega/gexec" 32 appsv1 "k8s.io/api/apps/v1" 33 v1 "k8s.io/api/core/v1" 34 apierrors "k8s.io/apimachinery/pkg/api/errors" 35 apitypes "k8s.io/apimachinery/pkg/types" 36 "sigs.k8s.io/controller-runtime/pkg/client" 37 "sigs.k8s.io/yaml" 38 39 "github.com/oam-dev/kubevela/apis/core.oam.dev/common" 40 "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" 41 "github.com/oam-dev/kubevela/apis/types" 42 "github.com/oam-dev/kubevela/pkg/oam/util" 43 ) 44 45 var _ = Describe("Test multicluster CLI commands", func() { 46 47 var namespace string 48 var hubCtx context.Context 49 var workerCtx context.Context 50 var app *v1beta1.Application 51 52 BeforeEach(func() { 53 hubCtx, workerCtx, namespace = initializeContextAndNamespace() 54 app = &v1beta1.Application{} 55 bs, err := os.ReadFile("./testdata/app/example-vela-cli-tool-test-app.yaml") 56 Expect(err).Should(Succeed()) 57 appYaml := strings.ReplaceAll(string(bs), "TEST_NAMESPACE", namespace) 58 Expect(yaml.Unmarshal([]byte(appYaml), app)).Should(Succeed()) 59 app.SetNamespace(namespace) 60 Expect(k8sClient.Create(hubCtx, app)).Should(Succeed()) 61 Expect(err).Should(Succeed()) 62 Eventually(func(g Gomega) { 63 pods := &v1.PodList{} 64 g.Expect(k8sClient.List(workerCtx, pods, client.InNamespace(namespace), client.MatchingLabels(map[string]string{ 65 "app.oam.dev/name": app.Name, 66 }))).Should(Succeed()) 67 g.Expect(len(pods.Items)).Should(Equal(1)) 68 g.Expect(pods.Items[0].Status.Phase).Should(Equal(v1.PodRunning)) 69 g.Expect(k8sClient.Get(hubCtx, client.ObjectKeyFromObject(app), app)).Should(Succeed()) 70 g.Expect(len(app.Status.AppliedResources)).ShouldNot(Equal(0)) 71 }, 2*time.Minute, time.Second*3).Should(Succeed()) 72 }) 73 74 AfterEach(func() { 75 Expect(k8sClient.Get(hubCtx, client.ObjectKeyFromObject(app), app)).Should(Succeed()) 76 Expect(k8sClient.Delete(hubCtx, app)).Should(Succeed()) 77 cleanUpNamespace(hubCtx, workerCtx, namespace) 78 }) 79 80 Context("Test debugging tools in multicluster", func() { 81 82 It("Test vela exec", func() { 83 command := exec.Command("vela", "exec", app.Name, "-n", namespace, "-i=false", "-t=false", "--", "pwd") 84 outputs, err := command.CombinedOutput() 85 Expect(string(outputs)).Should(ContainSubstring("/")) 86 Expect(err).Should(Succeed()) 87 }) 88 89 It("Test vela port-forward", func() { 90 stopChannel := make(chan struct{}, 1) 91 go func() { 92 defer GinkgoRecover() 93 command := exec.Command("vela", "port-forward", app.Name, "-n", namespace) 94 session, err := gexec.Start(command, io.Discard, io.Discard) 95 Expect(err).Should(Succeed()) 96 <-stopChannel 97 session.Terminate() 98 }() 99 defer func() { 100 stopChannel <- struct{}{} 101 }() 102 var resp *http.Response 103 var err error 104 Eventually(func(g Gomega) { 105 resp, err = http.Get("http://127.0.0.1:8000") 106 g.Expect(err).Should(Succeed()) 107 }, time.Minute).Should(Succeed()) 108 bs := make([]byte, 128) 109 _, err = resp.Body.Read(bs) 110 Expect(err).Should(Succeed()) 111 Expect(string(bs)).Should(ContainSubstring("Hello World")) 112 }) 113 114 It("Test vela status --tree", func() { 115 _, err := execCommand("cluster", "alias", WorkerClusterName, "alias-worker-tree") 116 Expect(err).Should(Succeed()) 117 for _, format := range []string{"inline", "wide", "table", "list"} { 118 outputs, err := execCommand("status", app.Name, "-n", namespace, "--tree", "--detail", "--detail-format", format) 119 Expect(err).Should(Succeed()) 120 Expect(outputs).Should(SatisfyAll( 121 ContainSubstring("alias-worker-tree"), 122 ContainSubstring("Deployment/exec-podinfo"), 123 ContainSubstring("updated"), 124 ContainSubstring("1/1"), 125 )) 126 } 127 }) 128 129 It("Test vela logs", func() { 130 var ( 131 err error 132 session *gexec.Session 133 waitingTime = 2 * time.Minute 134 ) 135 podViewCMFile, err := os.ReadFile("./testdata/view/component-pod-view.yaml") 136 Expect(err).Should(BeNil()) 137 podViewCM := &v1.ConfigMap{} 138 Expect(yaml.Unmarshal(podViewCMFile, podViewCM)).Should(BeNil()) 139 Expect(k8sClient.Create(hubCtx, podViewCM)).Should(SatisfyAny(BeNil(), &util.AlreadyExistMatcher{})) 140 141 stopChannel := make(chan struct{}, 1) 142 defer func() { 143 stopChannel <- struct{}{} 144 }() 145 146 command := exec.Command("vela", "logs", app.Name, "-n", namespace, "--cluster", WorkerClusterName) 147 session, err = gexec.Start(command, nil, nil) 148 Expect(err).Should(Succeed()) 149 go func() { 150 defer GinkgoRecover() 151 <-stopChannel 152 session.Terminate() 153 Eventually(session, 10*time.Second).Should(gexec.Exit()) 154 }() 155 Expect(err).Should(Succeed()) 156 Eventually(session, waitingTime).ShouldNot(BeNil()) 157 Eventually(session, waitingTime).Should(gbytes.Say("exec-podinfo")) 158 Eventually(session, waitingTime).Should(gbytes.Say("httpd started")) 159 }) 160 }) 161 162 }) 163 164 var _ = Describe("Test kube commands", func() { 165 166 Context("Test apply command", func() { 167 168 var namespace string 169 var hubCtx context.Context 170 var workerCtx context.Context 171 172 BeforeEach(func() { 173 hubCtx, workerCtx, namespace = initializeContextAndNamespace() 174 }) 175 176 AfterEach(func() { 177 cleanUpNamespace(hubCtx, workerCtx, namespace) 178 }) 179 180 It("Test vela kube apply & delete", func() { 181 _, err := execCommand("kube", "apply", 182 "--cluster", types.ClusterLocalName, "--cluster", WorkerClusterName, "-n", namespace, 183 "-f", "./testdata/kube", 184 "-f", "https://gist.githubusercontent.com/Somefive/b189219a9222eaa70b8908cf4379402b/raw/e603987b3e0989e01e50f69ebb1e8bb436461326/example-busybox-deployment.yaml", 185 ) 186 Expect(err).Should(Succeed()) 187 Expect(k8sClient.Get(hubCtx, apitypes.NamespacedName{Namespace: namespace, Name: "busybox"}, &appsv1.Deployment{})).Should(Succeed()) 188 Expect(k8sClient.Get(workerCtx, apitypes.NamespacedName{Namespace: namespace, Name: "busybox"}, &appsv1.Deployment{})).Should(Succeed()) 189 Expect(k8sClient.Get(hubCtx, apitypes.NamespacedName{Namespace: namespace, Name: "busybox"}, &v1.Service{})).Should(Succeed()) 190 Expect(k8sClient.Get(workerCtx, apitypes.NamespacedName{Namespace: namespace, Name: "busybox"}, &v1.Service{})).Should(Succeed()) 191 Expect(k8sClient.Get(hubCtx, apitypes.NamespacedName{Namespace: namespace, Name: "busybox-1"}, &v1.ConfigMap{})).Should(Succeed()) 192 Expect(k8sClient.Get(workerCtx, apitypes.NamespacedName{Namespace: namespace, Name: "busybox-1"}, &v1.ConfigMap{})).Should(Succeed()) 193 Expect(k8sClient.Get(hubCtx, apitypes.NamespacedName{Namespace: namespace, Name: "busybox-2"}, &v1.ConfigMap{})).Should(Succeed()) 194 Expect(k8sClient.Get(workerCtx, apitypes.NamespacedName{Namespace: namespace, Name: "busybox-2"}, &v1.ConfigMap{})).Should(Succeed()) 195 _, err = execCommand("kube", "delete", 196 "--cluster", types.ClusterLocalName, "--cluster", WorkerClusterName, "-n", namespace, 197 "deployment", "busybox", 198 ) 199 Expect(err).Should(Succeed()) 200 Expect(apierrors.IsNotFound(k8sClient.Get(hubCtx, apitypes.NamespacedName{Namespace: namespace, Name: "busybox"}, &appsv1.Deployment{}))).Should(BeTrue()) 201 Expect(apierrors.IsNotFound(k8sClient.Get(workerCtx, apitypes.NamespacedName{Namespace: namespace, Name: "busybox"}, &appsv1.Deployment{}))).Should(BeTrue()) 202 _, err = execCommand("kube", "delete", 203 "--cluster", types.ClusterLocalName, "--cluster", WorkerClusterName, "-n", namespace, 204 "configmap", "--all", 205 ) 206 Expect(err).Should(Succeed()) 207 Expect(apierrors.IsNotFound(k8sClient.Get(hubCtx, apitypes.NamespacedName{Namespace: namespace, Name: "busybox-1"}, &v1.ConfigMap{}))).Should(BeTrue()) 208 Expect(apierrors.IsNotFound(k8sClient.Get(workerCtx, apitypes.NamespacedName{Namespace: namespace, Name: "busybox-1"}, &v1.ConfigMap{}))).Should(BeTrue()) 209 Expect(apierrors.IsNotFound(k8sClient.Get(hubCtx, apitypes.NamespacedName{Namespace: namespace, Name: "busybox-2"}, &v1.ConfigMap{}))).Should(BeTrue()) 210 Expect(apierrors.IsNotFound(k8sClient.Get(workerCtx, apitypes.NamespacedName{Namespace: namespace, Name: "busybox-2"}, &v1.ConfigMap{}))).Should(BeTrue()) 211 }) 212 213 }) 214 215 }) 216 217 var _ = Describe("Test delete commands", func() { 218 219 Context("Test delete command", func() { 220 221 var namespace string 222 var hubCtx context.Context 223 var workerCtx context.Context 224 225 BeforeEach(func() { 226 hubCtx, workerCtx, namespace = initializeContextAndNamespace() 227 }) 228 229 AfterEach(func() { 230 cleanUpNamespace(hubCtx, workerCtx, namespace) 231 }) 232 233 It("Test delete with orphan option", func() { 234 bs, err := os.ReadFile("./testdata/app/app-orphan-delete.yaml") 235 Expect(err).Should(Succeed()) 236 app := &v1beta1.Application{} 237 Expect(yaml.Unmarshal(bs, app)).Should(Succeed()) 238 app.SetNamespace(namespace) 239 Expect(k8sClient.Create(hubCtx, app)).Should(Succeed()) 240 key := client.ObjectKeyFromObject(app) 241 cmKey := apitypes.NamespacedName{Namespace: namespace, Name: "orphan-cm"} 242 Eventually(func(g Gomega) { 243 g.Expect(k8sClient.Get(hubCtx, key, app)).Should(Succeed()) 244 g.Expect(app.Status.Phase).Should(Equal(common.ApplicationRunning)) 245 g.Expect(k8sClient.Get(workerCtx, cmKey, &v1.ConfigMap{})).To(Succeed()) 246 }).WithTimeout(20 * time.Second).WithPolling(2 * time.Second).Should(Succeed()) 247 _, err = execCommand("delete", key.Name, "-n", key.Namespace, "--orphan", "-y") 248 Expect(err).Should(Succeed()) 249 Eventually(func(g Gomega) { 250 g.Expect(apierrors.IsNotFound(k8sClient.Get(hubCtx, key, app))).Should(BeTrue()) 251 }).WithTimeout(10 * time.Second).WithPolling(2 * time.Second).Should(Succeed()) 252 Expect(k8sClient.Get(workerCtx, cmKey, &v1.ConfigMap{})).To(Succeed()) 253 }) 254 255 }) 256 257 })