1
19
20 package kubecli
21
22 import (
23 "context"
24 "fmt"
25 "net/http"
26 "path"
27
28 . "github.com/onsi/ginkgo/v2"
29 . "github.com/onsi/gomega"
30 "github.com/onsi/gomega/ghttp"
31 k8sv1 "k8s.io/api/core/v1"
32 "k8s.io/apimachinery/pkg/api/errors"
33 k8smetav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
34 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
35 "k8s.io/apimachinery/pkg/runtime/schema"
36 "k8s.io/apimachinery/pkg/types"
37
38 v1 "kubevirt.io/api/core/v1"
39 virtv1 "kubevirt.io/api/core/v1"
40 )
41
42 var _ = Describe("Kubevirt VirtualMachine Client", func() {
43
44 var server *ghttp.Server
45 basePath := "/apis/kubevirt.io/v1/namespaces/default/virtualmachines"
46 vmPath := path.Join(basePath, "testvm")
47 subBasePath := fmt.Sprintf("/apis/subresources.kubevirt.io/%s/namespaces/default/virtualmachines", v1.SubresourceStorageGroupVersion.Version)
48 subVMPath := path.Join(subBasePath, "testvm")
49 proxyPath := "/proxy/path"
50
51 BeforeEach(func() {
52 server = ghttp.NewServer()
53 })
54
55 DescribeTable("should fetch a VirtualMachineInstance", func(proxyPath string) {
56 client, err := GetKubevirtClientFromFlags(server.URL()+proxyPath, "")
57 Expect(err).ToNot(HaveOccurred())
58
59 vm := NewMinimalVM("testvm")
60 server.AppendHandlers(ghttp.CombineHandlers(
61 ghttp.VerifyRequest("GET", path.Join(proxyPath, vmPath)),
62 ghttp.RespondWithJSONEncoded(http.StatusOK, vm),
63 ))
64 fetchedVM, err := client.VirtualMachine(k8sv1.NamespaceDefault).Get(context.Background(), "testvm", k8smetav1.GetOptions{})
65
66 Expect(server.ReceivedRequests()).To(HaveLen(1))
67 Expect(err).ToNot(HaveOccurred())
68 Expect(fetchedVM).To(Equal(vm))
69 },
70 Entry("with regular server URL", ""),
71 Entry("with proxied server URL", proxyPath),
72 )
73
74 DescribeTable("should detect non existent VirtualMachines", func(proxyPath string) {
75 client, err := GetKubevirtClientFromFlags(server.URL()+proxyPath, "")
76 Expect(err).ToNot(HaveOccurred())
77
78 server.AppendHandlers(ghttp.CombineHandlers(
79 ghttp.VerifyRequest("GET", path.Join(proxyPath, vmPath)),
80 ghttp.RespondWithJSONEncoded(http.StatusNotFound, errors.NewNotFound(schema.GroupResource{}, "testvm")),
81 ))
82 _, err = client.VirtualMachine(k8sv1.NamespaceDefault).Get(context.Background(), "testvm", k8smetav1.GetOptions{})
83
84 Expect(server.ReceivedRequests()).To(HaveLen(1))
85 Expect(err).To(HaveOccurred())
86 Expect(errors.IsNotFound(err)).To(BeTrue())
87 },
88 Entry("with regular server URL", ""),
89 Entry("with proxied server URL", proxyPath),
90 )
91
92 DescribeTable("should fetch a VirtualMachine list", func(proxyPath string) {
93 client, err := GetKubevirtClientFromFlags(server.URL()+proxyPath, "")
94 Expect(err).ToNot(HaveOccurred())
95
96 vm := NewMinimalVM("testvm")
97 server.AppendHandlers(ghttp.CombineHandlers(
98 ghttp.VerifyRequest("GET", path.Join(proxyPath, basePath)),
99 ghttp.RespondWithJSONEncoded(http.StatusOK, NewVMList(*vm)),
100 ))
101 fetchedVMList, err := client.VirtualMachine(k8sv1.NamespaceDefault).List(context.Background(), k8smetav1.ListOptions{})
102 apiVersion, kind := v1.VirtualMachineGroupVersionKind.ToAPIVersionAndKind()
103
104 Expect(server.ReceivedRequests()).To(HaveLen(1))
105 Expect(err).ToNot(HaveOccurred())
106 Expect(fetchedVMList.Items).To(HaveLen(1))
107 Expect(fetchedVMList.Items[0].APIVersion).To(Equal(apiVersion))
108 Expect(fetchedVMList.Items[0].Kind).To(Equal(kind))
109 Expect(fetchedVMList.Items[0]).To(Equal(*vm))
110 },
111 Entry("with regular server URL", ""),
112 Entry("with proxied server URL", proxyPath),
113 )
114
115 DescribeTable("should create a VirtualMachine", func(proxyPath string) {
116 client, err := GetKubevirtClientFromFlags(server.URL()+proxyPath, "")
117 Expect(err).ToNot(HaveOccurred())
118
119 vm := NewMinimalVM("testvm")
120 server.AppendHandlers(ghttp.CombineHandlers(
121 ghttp.VerifyRequest("POST", path.Join(proxyPath, basePath)),
122 ghttp.RespondWithJSONEncoded(http.StatusCreated, vm),
123 ))
124 createdVM, err := client.VirtualMachine(k8sv1.NamespaceDefault).Create(context.Background(), vm, k8smetav1.CreateOptions{})
125
126 Expect(server.ReceivedRequests()).To(HaveLen(1))
127 Expect(err).ToNot(HaveOccurred())
128 Expect(createdVM).To(Equal(vm))
129 },
130 Entry("with regular server URL", ""),
131 Entry("with proxied server URL", proxyPath),
132 )
133
134 DescribeTable("should update a VirtualMachine", func(proxyPath string) {
135 client, err := GetKubevirtClientFromFlags(server.URL()+proxyPath, "")
136 Expect(err).ToNot(HaveOccurred())
137
138 vm := NewMinimalVM("testvm")
139 server.AppendHandlers(ghttp.CombineHandlers(
140 ghttp.VerifyRequest("PUT", path.Join(proxyPath, vmPath)),
141 ghttp.RespondWithJSONEncoded(http.StatusOK, vm),
142 ))
143 updatedVM, err := client.VirtualMachine(k8sv1.NamespaceDefault).Update(context.Background(), vm, metav1.UpdateOptions{})
144
145 Expect(server.ReceivedRequests()).To(HaveLen(1))
146 Expect(err).ToNot(HaveOccurred())
147 Expect(updatedVM).To(Equal(vm))
148 },
149 Entry("with regular server URL", ""),
150 Entry("with proxied server URL", proxyPath),
151 )
152
153 DescribeTable("should patch a VirtualMachine", func(proxyPath string) {
154 client, err := GetKubevirtClientFromFlags(server.URL()+proxyPath, "")
155 Expect(err).ToNot(HaveOccurred())
156
157 vm := NewMinimalVM("testvm")
158 running := true
159 vm.Spec.Running = &running
160
161 server.AppendHandlers(ghttp.CombineHandlers(
162 ghttp.VerifyRequest("PATCH", path.Join(proxyPath, vmPath)),
163 ghttp.VerifyBody([]byte("{\"spec\":{\"running\":true}}")),
164 ghttp.RespondWithJSONEncoded(http.StatusOK, vm),
165 ))
166
167 patchedVM, err := client.VirtualMachine(k8sv1.NamespaceDefault).Patch(context.Background(), vm.Name, types.MergePatchType, []byte("{\"spec\":{\"running\":true}}"), k8smetav1.PatchOptions{})
168
169 Expect(server.ReceivedRequests()).To(HaveLen(1))
170 Expect(err).ToNot(HaveOccurred())
171 Expect(vm.Spec.Running).To(Equal(patchedVM.Spec.Running))
172 },
173 Entry("with regular server URL", ""),
174 Entry("with proxied server URL", proxyPath),
175 )
176
177 DescribeTable("should fail on patch a VirtualMachine", func(proxyPath string) {
178 client, err := GetKubevirtClientFromFlags(server.URL()+proxyPath, "")
179 Expect(err).ToNot(HaveOccurred())
180
181 vm := NewMinimalVM("testvm")
182
183 server.AppendHandlers(ghttp.CombineHandlers(
184 ghttp.VerifyRequest("PATCH", path.Join(proxyPath, vmPath)),
185 ghttp.VerifyBody([]byte("{\"spec\":{\"running\":true}}")),
186 ghttp.RespondWithJSONEncoded(http.StatusNotFound, vm),
187 ))
188
189 patchedVM, err := client.VirtualMachine(k8sv1.NamespaceDefault).Patch(context.Background(), vm.Name, types.MergePatchType, []byte("{\"spec\":{\"running\":true}}"), k8smetav1.PatchOptions{})
190
191 Expect(server.ReceivedRequests()).To(HaveLen(1))
192 Expect(err).To(HaveOccurred())
193 Expect(vm.Spec.Running).To(Equal(patchedVM.Spec.Running))
194 },
195 Entry("with regular server URL", ""),
196 Entry("with proxied server URL", proxyPath),
197 )
198
199 DescribeTable("should delete a VirtualMachineInstance", func(proxyPath string) {
200 client, err := GetKubevirtClientFromFlags(server.URL()+proxyPath, "")
201 Expect(err).ToNot(HaveOccurred())
202
203 server.AppendHandlers(ghttp.CombineHandlers(
204 ghttp.VerifyRequest("DELETE", path.Join(proxyPath, vmPath)),
205 ghttp.RespondWithJSONEncoded(http.StatusOK, nil),
206 ))
207 err = client.VirtualMachine(k8sv1.NamespaceDefault).Delete(context.Background(), "testvm", k8smetav1.DeleteOptions{})
208
209 Expect(server.ReceivedRequests()).To(HaveLen(1))
210 Expect(err).ToNot(HaveOccurred())
211 },
212 Entry("with regular server URL", ""),
213 Entry("with proxied server URL", proxyPath),
214 )
215
216 DescribeTable("should restart a VirtualMachine", func(proxyPath string) {
217 client, err := GetKubevirtClientFromFlags(server.URL()+proxyPath, "")
218 Expect(err).ToNot(HaveOccurred())
219
220 server.AppendHandlers(ghttp.CombineHandlers(
221 ghttp.VerifyRequest("PUT", path.Join(proxyPath, subVMPath, "restart")),
222 ghttp.RespondWithJSONEncoded(http.StatusOK, nil),
223 ))
224 err = client.VirtualMachine(k8sv1.NamespaceDefault).Restart(context.Background(), "testvm", &v1.RestartOptions{})
225
226 Expect(server.ReceivedRequests()).To(HaveLen(1))
227 Expect(err).ToNot(HaveOccurred())
228 },
229 Entry("with regular server URL", ""),
230 Entry("with proxied server URL", proxyPath),
231 )
232
233 DescribeTable("should migrate a VirtualMachine", func(proxyPath string) {
234 client, err := GetKubevirtClientFromFlags(server.URL()+proxyPath, "")
235 Expect(err).ToNot(HaveOccurred())
236
237 server.AppendHandlers(ghttp.CombineHandlers(
238 ghttp.VerifyRequest("PUT", path.Join(proxyPath, subVMPath, "migrate")),
239 ghttp.RespondWithJSONEncoded(http.StatusOK, nil),
240 ))
241 err = client.VirtualMachine(k8sv1.NamespaceDefault).Migrate(context.Background(), "testvm", &virtv1.MigrateOptions{})
242
243 Expect(server.ReceivedRequests()).To(HaveLen(1))
244 Expect(err).ToNot(HaveOccurred())
245 },
246 Entry("with regular server URL", ""),
247 Entry("with proxied server URL", proxyPath),
248 )
249
250 AfterEach(func() {
251 server.Close()
252 })
253 })
254
View as plain text