github.com/1aal/kubeblocks@v0.0.0-20231107070852-e1c03e598921/pkg/cli/delete/delete_test.go (about) 1 /* 2 Copyright (C) 2022-2023 ApeCloud Co., Ltd 3 4 This file is part of KubeBlocks project 5 6 This program is free software: you can redistribute it and/or modify 7 it under the terms of the GNU Affero General Public License as published by 8 the Free Software Foundation, either version 3 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU Affero General Public License for more details. 15 16 You should have received a copy of the GNU Affero General Public License 17 along with this program. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 package delete 21 22 import ( 23 "bytes" 24 "fmt" 25 "net/http" 26 27 . "github.com/onsi/ginkgo/v2" 28 . "github.com/onsi/gomega" 29 "github.com/spf13/cobra" 30 "k8s.io/apimachinery/pkg/runtime" 31 "k8s.io/apimachinery/pkg/runtime/schema" 32 "k8s.io/cli-runtime/pkg/genericiooptions" 33 "k8s.io/cli-runtime/pkg/resource" 34 clientfake "k8s.io/client-go/rest/fake" 35 cmdtesting "k8s.io/kubectl/pkg/cmd/testing" 36 "k8s.io/kubectl/pkg/scheme" 37 38 appsv1alpha1 "github.com/1aal/kubeblocks/apis/apps/v1alpha1" 39 "github.com/1aal/kubeblocks/pkg/cli/testing" 40 "github.com/1aal/kubeblocks/pkg/cli/types" 41 ) 42 43 var _ = Describe("Delete", func() { 44 var ( 45 streams genericiooptions.IOStreams 46 in *bytes.Buffer 47 tf *cmdtesting.TestFactory 48 o *DeleteOptions 49 ) 50 51 const ( 52 namespace = "test" 53 clusterName = "clusterName" 54 ) 55 56 BeforeEach(func() { 57 streams, in, _, _ = genericiooptions.NewTestIOStreams() 58 tf = testing.NewTestFactory(namespace) 59 60 _ = appsv1alpha1.AddToScheme(scheme.Scheme) 61 codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...) 62 cluster := testing.FakeCluster(clusterName, namespace) 63 httpResp := func(obj runtime.Object) *http.Response { 64 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, obj)} 65 } 66 67 tf.UnstructuredClient = &clientfake.RESTClient{ 68 GroupVersion: schema.GroupVersion{Group: types.AppsAPIGroup, Version: types.AppsAPIVersion}, 69 NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer, 70 Client: clientfake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { 71 return httpResp(cluster), nil 72 }), 73 } 74 75 tf.Client = tf.UnstructuredClient 76 tf.FakeDynamicClient = testing.FakeDynamicClient(cluster, testing.FakeClusterDef(), testing.FakeClusterVersion()) 77 o = NewDeleteOptions(tf, streams, types.ClusterGVR()) 78 }) 79 80 AfterEach(func() { 81 tf.Cleanup() 82 }) 83 84 It("validate", func() { 85 o.Names = []string{"foo"} 86 By("set force and GracePeriod") 87 o.Force = true 88 o.GracePeriod = 1 89 o.Now = false 90 Expect(o.validate()).Should(HaveOccurred()) 91 92 o.Force = true 93 o.GracePeriod = 0 94 o.Now = false 95 Expect(o.validate()).Should(Succeed()) 96 97 By("set now and GracePeriod") 98 o.Force = false 99 o.Now = true 100 o.GracePeriod = 1 101 Expect(o.validate()).Should(HaveOccurred()) 102 103 o.Force = false 104 o.Now = true 105 o.GracePeriod = -1 106 Expect(o.validate()).Should(Succeed()) 107 108 By("set force only") 109 o.Force = true 110 o.Now = false 111 o.GracePeriod = -1 112 Expect(o.validate()).Should(Succeed()) 113 114 By("set GracePeriod only") 115 o.Force = false 116 o.Now = false 117 o.GracePeriod = 1 118 Expect(o.validate()).Should(Succeed()) 119 120 o.Force = false 121 o.GracePeriod = -1 122 o.Now = false 123 124 By("set name and label") 125 o.Names = []string{"foo"} 126 o.LabelSelector = "foo=bar" 127 o.AllNamespaces = false 128 Expect(o.validate()).Should(HaveOccurred()) 129 130 By("set name and all") 131 o.Names = []string{"foo"} 132 o.LabelSelector = "" 133 o.AllNamespaces = true 134 Expect(o.validate()).Should(HaveOccurred()) 135 136 By("set all and label") 137 o.Names = nil 138 o.AllNamespaces = true 139 o.LabelSelector = "foo=bar" 140 Expect(o.validate()).Should(Succeed()) 141 142 By("set name") 143 o.Names = []string{"foo"} 144 o.AllNamespaces = false 145 o.LabelSelector = "" 146 Expect(o.validate()).Should(Succeed()) 147 148 By("set nothing") 149 o.Names = nil 150 o.LabelSelector = "" 151 Expect(o.validate()).Should(MatchError(MatchRegexp("no name was specified"))) 152 }) 153 154 It("complete", func() { 155 o.Names = []string{"foo"} 156 Expect(o.validate()).Should(Succeed()) 157 158 By("confirm") 159 in.Reset() 160 Expect(o.complete()).Should(HaveOccurred()) 161 in.Reset() 162 _, _ = in.Write([]byte("bar\n")) 163 Expect(o.complete()).Should(HaveOccurred()) 164 in.Reset() 165 _, _ = in.Write([]byte("foo\n")) 166 Expect(o.complete()).Should(Succeed()) 167 168 Expect(o.Result).ShouldNot(BeNil()) 169 }) 170 171 It("build a delete command", func() { 172 cmd := &cobra.Command{ 173 Use: "test-delete", 174 Short: "Test a delete command", 175 Example: "Test command example", 176 RunE: func(cmd *cobra.Command, args []string) error { 177 o.Names = args 178 return o.Run() 179 }, 180 } 181 o.AddFlags(cmd) 182 183 Expect(cmd).ShouldNot(BeNil()) 184 185 By("do not use pre-delete hook") 186 _, _ = in.Write([]byte(clusterName + "\n")) 187 Expect(cmd.RunE(cmd, []string{clusterName})).Should(Succeed()) 188 189 By("set pre-delete hook") 190 // block cluster deletion 191 fakePreDeleteHook := func(o *DeleteOptions, object runtime.Object) error { 192 if object.GetObjectKind().GroupVersionKind().Kind == appsv1alpha1.ClusterKind { 193 return fmt.Errorf("fake pre-delete hook error") 194 } else { 195 return nil 196 } 197 } 198 o.PreDeleteHook = fakePreDeleteHook 199 _, _ = in.Write([]byte(clusterName + "\n")) 200 Expect(cmd.RunE(cmd, []string{clusterName})).Should(HaveOccurred()) 201 }) 202 })