@@ -30,6 +30,8 @@ import (
3030 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3131 "k8s.io/apimachinery/pkg/types"
3232 ctrl "sigs.k8s.io/controller-runtime"
33+ k8sclient "sigs.k8s.io/controller-runtime/pkg/client"
34+ "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
3335
3436 kvmv1 "github.com/cobaltcore-dev/openstack-hypervisor-operator/api/v1"
3537)
@@ -72,7 +74,7 @@ var _ = Describe("HypervisorMaintenanceController", func() {
7274
7375 w .WriteHeader (http .StatusOK )
7476 _ , err = fmt .Fprint (w , ServiceEnabledResponse )
75- Expect (err ).NotTo ( HaveOccurred ())
77+ Expect (err ).To ( Succeed ())
7678 })
7779 }
7880
@@ -113,6 +115,16 @@ var _ = Describe("HypervisorMaintenanceController", func() {
113115 Expect (err ).NotTo (HaveOccurred ())
114116 })
115117
118+ AfterEach (func (ctx context.Context ) {
119+ eviction := & kvmv1.Eviction {
120+ ObjectMeta : metav1.ObjectMeta {
121+ Name : hypervisorName .Name ,
122+ Namespace : hypervisorName .Namespace ,
123+ },
124+ }
125+ Expect (k8sclient .IgnoreNotFound (k8sClient .Delete (ctx , eviction ))).To (Succeed ())
126+ })
127+
116128 // Tests
117129 Context ("Onboarded Hypervisor" , func () {
118130 BeforeEach (func () {
@@ -127,7 +139,6 @@ var _ = Describe("HypervisorMaintenanceController", func() {
127139 Message : "random text" ,
128140 },
129141 )
130-
131142 Expect (k8sClient .Status ().Update (ctx , hypervisor )).To (Succeed ())
132143 })
133144
@@ -169,9 +180,6 @@ var _ = Describe("HypervisorMaintenanceController", func() {
169180 Expect (k8sClient .Update (ctx , hypervisor )).To (Succeed ())
170181 expectedBody := fmt .Sprintf (`{"disabled_reason": "Hypervisor CRD: spec.maintenance=%v", "status": "disabled"}` , mode )
171182 mockServiceUpdate (expectedBody )
172- req := ctrl.Request {NamespacedName : hypervisorName }
173- _ , err := controller .Reconcile (ctx , req )
174- Expect (err ).NotTo (HaveOccurred ())
175183 })
176184
177185 It ("should set the ConditionTypeHypervisorDisabled to true" , func () {
@@ -192,5 +200,153 @@ var _ = Describe("HypervisorMaintenanceController", func() {
192200 }) // Spec.Maintenance="<mode>"
193201 }
194202
203+ Describe ("Eviction reconciliation" , func () {
204+ Context ("Spec.Maintenance=\" \" " , func () {
205+ BeforeEach (func () {
206+ hypervisor := & kvmv1.Hypervisor {}
207+ Expect (k8sClient .Get (ctx , hypervisorName , hypervisor )).To (Succeed ())
208+ hypervisor .Spec .Maintenance = ""
209+ Expect (k8sClient .Update (ctx , hypervisor )).To (Succeed ())
210+ Expect (k8sClient .Get (ctx , hypervisorName , hypervisor )).To (Succeed ())
211+ meta .SetStatusCondition (& hypervisor .Status .Conditions ,
212+ metav1.Condition {
213+ Type : kvmv1 .ConditionTypeEvicting ,
214+ Reason : "dontcare" ,
215+ Status : metav1 .ConditionUnknown ,
216+ Message : "dontcare" ,
217+ })
218+ Expect (k8sClient .Status ().Update (ctx , hypervisor )).To (Succeed ())
219+ expectedBody := `{"status": "enabled"}`
220+ mockServiceUpdate (expectedBody )
221+
222+ eviction := & kvmv1.Eviction {
223+ ObjectMeta : metav1.ObjectMeta {Name : hypervisorName .Name },
224+ Spec : kvmv1.EvictionSpec {
225+ Hypervisor : hypervisorName .Name ,
226+ Reason : "test" ,
227+ },
228+ }
229+ Expect (controllerutil .SetControllerReference (hypervisor , eviction , controller .Scheme )).To (Succeed ())
230+ Expect (k8sClient .Create (ctx , eviction )).To (Succeed ())
231+ })
232+
233+ It ("should delete the created eviction" , func () {
234+ eviction := & kvmv1.Eviction {}
235+ err := k8sClient .Get (ctx , hypervisorName , eviction )
236+ By (fmt .Sprintf ("%+v" , * eviction ))
237+ Expect (err ).To (HaveOccurred ())
238+ Expect (k8sclient .IgnoreNotFound (err )).To (Succeed ())
239+ })
240+ }) // Spec.Maintenance=""
241+
242+ Context ("Spec.Maintenance=\" ha\" " , func () {
243+ BeforeEach (func () {
244+ hypervisor := & kvmv1.Hypervisor {}
245+ Expect (k8sClient .Get (ctx , hypervisorName , hypervisor )).To (Succeed ())
246+ hypervisor .Spec .Maintenance = "ha"
247+ Expect (k8sClient .Update (ctx , hypervisor )).To (Succeed ())
248+ expectedBody := `{"disabled_reason": "Hypervisor CRD: spec.maintenance=ha", "status": "disabled"}`
249+ mockServiceUpdate (expectedBody )
250+ })
251+ It ("should not create an eviction resource" , func () {
252+ eviction := & kvmv1.Eviction {}
253+ err := k8sClient .Get (ctx , hypervisorName , eviction )
254+ Expect (err ).To (HaveOccurred ())
255+ Expect (k8sclient .IgnoreNotFound (err )).To (Succeed ())
256+ })
257+ }) // Spec.Maintenance="ha"
258+
259+ for _ , mode := range []string {"auto" , "manual" } {
260+ Context (fmt .Sprintf ("Spec.Maintenance=\" %v\" " , mode ), func () {
261+ BeforeEach (func () {
262+ hypervisor := & kvmv1.Hypervisor {}
263+ Expect (k8sClient .Get (ctx , hypervisorName , hypervisor )).To (Succeed ())
264+ hypervisor .Spec .Maintenance = mode
265+ Expect (k8sClient .Update (ctx , hypervisor )).To (Succeed ())
266+ expectedBody := fmt .Sprintf (`{"disabled_reason": "Hypervisor CRD: spec.maintenance=%v", "status": "disabled"}` , mode )
267+ mockServiceUpdate (expectedBody )
268+ })
269+
270+ When ("there is no eviction yet" , func () {
271+ It ("should create an eviction resource named as the hypervisor" , func () {
272+ eviction := & kvmv1.Eviction {}
273+ Expect (k8sClient .Get (ctx , hypervisorName , eviction )).To (Succeed ())
274+ })
275+
276+ It ("should create an evicting condition" , func () {
277+ hypervisor := & kvmv1.Hypervisor {}
278+ Expect (k8sClient .Get (ctx , hypervisorName , hypervisor )).To (Succeed ())
279+ Expect (hypervisor .Status .Conditions ).To (ContainElement (
280+ SatisfyAll (
281+ HaveField ("Type" , kvmv1 .ConditionTypeEvicting ),
282+ HaveField ("Status" , metav1 .ConditionTrue ),
283+ HaveField ("Reason" , kvmv1 .ConditionReasonRunning ),
284+ ),
285+ ))
286+ })
287+
288+ It ("should reflect it in the hypervisor evicted status" , func () {
289+ hypervisor := & kvmv1.Hypervisor {}
290+ Expect (k8sClient .Get (ctx , hypervisorName , hypervisor )).To (Succeed ())
291+ Expect (hypervisor .Status .Evicted ).To (BeFalse ())
292+ })
293+ })
294+
295+ When ("there is a finished eviction" , func () {
296+ BeforeEach (func () {
297+ eviction := & kvmv1.Eviction {
298+ ObjectMeta : metav1.ObjectMeta {Name : hypervisorName .Name },
299+ Spec : kvmv1.EvictionSpec {
300+ Hypervisor : hypervisorName .Name ,
301+ Reason : "test" ,
302+ },
303+ }
304+ hypervisor := & kvmv1.Hypervisor {}
305+ Expect (k8sClient .Get (ctx , hypervisorName , hypervisor )).To (Succeed ())
306+ Expect (controllerutil .SetControllerReference (hypervisor , eviction , controller .Scheme )).To (Succeed ())
307+ Expect (k8sClient .Create (ctx , eviction )).To (Succeed ())
308+
309+ Expect (k8sClient .Get (ctx , hypervisorName , hypervisor )).To (Succeed ())
310+ meta .SetStatusCondition (& eviction .Status .Conditions , metav1.Condition {
311+ Type : kvmv1 .ConditionTypeEvicting ,
312+ Status : metav1 .ConditionFalse ,
313+ Message : "whatever" ,
314+ Reason : kvmv1 .ConditionReasonSucceeded ,
315+ })
316+ Expect (k8sClient .Status ().Update (ctx , eviction )).To (Succeed ())
317+ })
318+
319+ It ("should reflect it in the hypervisor evicting condition" , func () {
320+ hypervisor := & kvmv1.Hypervisor {}
321+ Expect (k8sClient .Get (ctx , hypervisorName , hypervisor )).To (Succeed ())
322+ Expect (hypervisor .Status .Conditions ).To (ContainElement (
323+ SatisfyAll (
324+ HaveField ("Type" , kvmv1 .ConditionTypeEvicting ),
325+ HaveField ("Status" , metav1 .ConditionFalse ),
326+ HaveField ("Reason" , kvmv1 .ConditionReasonSucceeded ),
327+ ),
328+ ))
329+ })
330+
331+ It ("should reflect it in the hypervisor evicted status" , func () {
332+ hypervisor := & kvmv1.Hypervisor {}
333+ Expect (k8sClient .Get (ctx , hypervisorName , hypervisor )).To (Succeed ())
334+ Expect (hypervisor .Status .Evicted ).To (BeTrue ())
335+ })
336+
337+ It ("should set the ConditionTypeReady to false and reason to evicted" , func () {
338+ updated := & kvmv1.Hypervisor {}
339+ Expect (k8sClient .Get (ctx , hypervisorName , updated )).To (Succeed ())
340+ Expect (updated .Status .Conditions ).To (ContainElement (
341+ SatisfyAll (
342+ HaveField ("Type" , kvmv1 .ConditionTypeReady ),
343+ HaveField ("Status" , metav1 .ConditionFalse ),
344+ HaveField ("Reason" , kvmv1 .ConditionReasonReadyEvicted ),
345+ )))
346+ })
347+ })
348+ }) // Spec.Maintenance="<mode>"
349+ }
350+ })
195351 }) // Context Onboarded Hypervisor
196352})
0 commit comments