github.com/rancher/elemental/tests@v0.0.0-20240517125144-ae048c615b3f/e2e/uninstall-operator_test.go (about) 1 /* 2 Copyright © 2024 SUSE LLC 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 http://www.apache.org/licenses/LICENSE-2.0 8 Unless required by applicable law or agreed to in writing, software 9 distributed under the License is distributed on an "AS IS" BASIS, 10 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 See the License for the specific language governing permissions and 12 limitations under the License. 13 */ 14 15 package e2e_test 16 17 import ( 18 "strings" 19 "sync" 20 "time" 21 22 . "github.com/onsi/ginkgo/v2" 23 . "github.com/onsi/gomega" 24 "github.com/rancher-sandbox/ele-testhelpers/kubectl" 25 "github.com/rancher-sandbox/ele-testhelpers/rancher" 26 "github.com/rancher-sandbox/ele-testhelpers/tools" 27 "github.com/rancher/elemental/tests/e2e/helpers/elemental" 28 ) 29 30 func deleteFinalizers(ns, object, value string) { 31 _, err := kubectl.RunWithoutErr("patch", object, 32 "--namespace", ns, value, "--type", "merge", 33 "--patch", "{\"metadata\":{\"finalizers\":null}}") 34 Expect(err).To(Not(HaveOccurred())) 35 36 } 37 38 func testClusterAvailability(ns, cluster string) { 39 Eventually(func() string { 40 out, _ := kubectl.RunWithoutErr("get", "cluster.v1.provisioning.cattle.io", 41 "--namespace", ns, cluster, 42 "-o", "jsonpath={.metadata.name}") 43 return out 44 }, tools.SetTimeout(3*time.Minute), 5*time.Second).Should(Equal(clusterName)) 45 } 46 47 var _ = Describe("E2E - Uninstall Elemental Operator", Label("uninstall-operator"), func() { 48 // Create kubectl context 49 // Default timeout is too small, so New() cannot be used 50 k := &kubectl.Kubectl{ 51 Namespace: "", 52 PollTimeout: tools.SetTimeout(300 * time.Second), 53 PollInterval: 500 * time.Millisecond, 54 } 55 56 It("Uninstall Elemental Operator", func() { 57 // Report to Qase 58 testCaseID = 70 59 60 By("Testing cluster resource availability BEFORE operator uninstallation", func() { 61 testClusterAvailability(clusterNS, clusterName) 62 }) 63 64 By("Uninstalling Operator via Helm", func() { 65 for _, chart := range []string{"elemental-operator", "elemental-operator-crds"} { 66 RunHelmCmdWithRetry( 67 "uninstall", chart, 68 "--namespace", "cattle-elemental-system", 69 ) 70 } 71 }) 72 73 By("Testing cluster resource availability AFTER operator uninstallation", func() { 74 testClusterAvailability(clusterNS, clusterName) 75 }) 76 77 By("Checking that Elemental resources are gone", func() { 78 Eventually(func() string { 79 out, _ := kubectl.Run("get", "MachineInventorySelectorTemplate", 80 "--namespace", clusterNS, 81 "-o", "jsonpath={.items[*].metadata.name}") 82 return out 83 }, tools.SetTimeout(3*time.Minute), 5*time.Second).Should(ContainSubstring("NotFound")) 84 }) 85 86 // NOTE: the operator cannot be reinstall now because there are still CRDs pending to be removed 87 By("Checking that Elemental operator CRDs cannot be reinstalled", func() { 88 chart := "elemental-operator-crds" 89 out, err := kubectl.RunHelmBinaryWithOutput("upgrade", "--install", chart, 90 operatorRepo+"/"+chart+"-chart", 91 "--namespace", "cattle-elemental-system", 92 "--create-namespace", 93 "--wait", "--wait-for-jobs", 94 ) 95 Expect(err).To(HaveOccurred(), out) 96 Expect(out).To(ContainSubstring("CRDs from previous installations are pending to be removed")) 97 }) 98 99 // NOTE: we have to run this in background to be able to apply the workaround! 100 var wg sync.WaitGroup 101 wg.Add(1) 102 go func(ns, name string) { 103 defer wg.Done() 104 defer GinkgoRecover() 105 106 By("Deleting cluster resource", func() { 107 Eventually(func() error { 108 _, err := kubectl.RunWithoutErr("delete", "cluster", 109 "--namespace", ns, name) 110 return err 111 }, tools.SetTimeout(2*time.Minute), 10*time.Second).Should(Not(HaveOccurred())) 112 }) 113 }(clusterNS, clusterName) 114 115 // Removing finalizers from MachineInventory and Machine 116 By("Removing finalizers from MachineInventory/Machine", func() { 117 // NOTE: wait a bit for the cluster deletion to be started (it's running in background) 118 time.Sleep(1 * time.Minute) 119 120 machineList, err := kubectl.RunWithoutErr("get", "MachineInventory", 121 "--namespace", clusterNS, "-o", "jsonpath={.items[*].metadata.name}") 122 Expect(err).To(Not(HaveOccurred())) 123 124 for _, machine := range strings.Fields(machineList) { 125 internalMachine, err := elemental.GetInternalMachine(clusterNS, machine) 126 Expect(err).To(Not(HaveOccurred())) 127 128 // Delete blocking Finalizers 129 GinkgoWriter.Printf("Deleting Finalizers for MachineInventory '%s'...\n", machine) 130 deleteFinalizers(clusterNS, "MachineInventory", machine) 131 132 // Only if Machine is still present 133 if internalMachine != "" { 134 GinkgoWriter.Printf("Deleting Finalizers for Machine '%s'...\n", internalMachine) 135 deleteFinalizers(clusterNS, "Machine", internalMachine) 136 } 137 } 138 }) 139 140 // Wait for cluster deletion to be completed 141 wg.Wait() 142 143 By("Testing cluster resource unavailability", func() { 144 out, err := kubectl.Run("get", "cluster.v1.provisioning.cattle.io", 145 "--namespace", clusterNS, clusterName, 146 "-o", "jsonpath={.metadata.name}") 147 Expect(err).To(HaveOccurred(), out) 148 Expect(out).To(ContainSubstring("NotFound")) 149 }) 150 }) 151 152 It("Re-install Elemental Operator", func() { 153 // Report to Qase 154 testCaseID = 62 155 156 By("Installing Operator via Helm", func() { 157 for _, chart := range []string{"elemental-operator-crds", "elemental-operator"} { 158 RunHelmCmdWithRetry("upgrade", "--install", chart, 159 operatorRepo+"/"+chart+"-chart", 160 "--namespace", "cattle-elemental-system", 161 "--create-namespace", 162 "--wait", "--wait-for-jobs", 163 ) 164 } 165 166 // Wait for pod to be started 167 Eventually(func() error { 168 return rancher.CheckPod(k, [][]string{{"cattle-elemental-system", "app=elemental-operator"}}) 169 }, tools.SetTimeout(4*time.Minute), 30*time.Second).Should(BeNil()) 170 }) 171 172 By("Creating a dumb MachineRegistration", func() { 173 err := kubectl.Apply(clusterNS, dumbRegistrationYaml) 174 Expect(err).To(Not(HaveOccurred())) 175 }) 176 177 By("Creating cluster", func() { 178 // NOTE: we can re-use clusterYaml as it has already been configured correctly 179 err := kubectl.Apply(clusterNS, clusterYaml) 180 Expect(err).To(Not(HaveOccurred())) 181 }) 182 183 By("Testing cluster resource availability", func() { 184 testClusterAvailability(clusterNS, clusterName) 185 }) 186 }) 187 })