Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 4 additions & 5 deletions internal/controller/node_eviction_label_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,9 @@ func (r *NodeEvictionLabelReconciler) Reconcile(ctx context.Context, req ctrl.Re
}

maintenanceValue, found := node.Labels[labelEvictionRequired]
name := fmt.Sprintf("maintenance-required-%v", hostname)
eviction := &kvmv1.Eviction{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Name: hostname,
},
}

Expand Down Expand Up @@ -100,7 +99,7 @@ func (r *NodeEvictionLabelReconciler) Reconcile(ctx context.Context, req ctrl.Re
value = "true"
} else {
// check for existing eviction, else create it
value, err = r.reconcileEviction(ctx, eviction, node, hostname, maintenanceValue)
value, err = r.reconcileEviction(ctx, eviction, hv, hostname, maintenanceValue)
if err != nil {
return ctrl.Result{}, err
}
Expand All @@ -126,13 +125,13 @@ func (r *NodeEvictionLabelReconciler) Reconcile(ctx context.Context, req ctrl.Re
return ctrl.Result{}, k8sclient.IgnoreNotFound(err)
}

func (r *NodeEvictionLabelReconciler) reconcileEviction(ctx context.Context, eviction *kvmv1.Eviction, node *corev1.Node, hostname, maintenanceValue string) (string, error) {
func (r *NodeEvictionLabelReconciler) reconcileEviction(ctx context.Context, eviction *kvmv1.Eviction, hypervisor *kvmv1.Hypervisor, hostname, maintenanceValue string) (string, error) {
log := logger.FromContext(ctx)
if err := r.Get(ctx, k8sclient.ObjectKeyFromObject(eviction), eviction); err != nil {
if !k8serrors.IsNotFound(err) {
return "", err
}
if err := controllerutil.SetOwnerReference(node, eviction, r.Scheme); err != nil {
if err := controllerutil.SetOwnerReference(hypervisor, eviction, r.Scheme); err != nil {
return "", err
}
log.Info("Creating new eviction", "name", eviction.Name)
Expand Down
129 changes: 66 additions & 63 deletions internal/controller/node_eviction_label_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ package controller

import (
"context"
"fmt"
"os"

"github.com/gophercloud/gophercloud/v2/testhelper"
Expand All @@ -43,64 +42,81 @@ var _ = Describe("Node Eviction Label Controller", func() {
zone = "zone"
)
var (
nodeReconciler *NodeEvictionLabelReconciler
req = ctrl.Request{NamespacedName: types.NamespacedName{Name: nodeName}}
fakeServer testhelper.FakeServer
)

Context("When reconciling a node", func() {
ctx := context.Background() //nolint:govet

reconcileNodeLoop := func(steps int) (res ctrl.Result, err error) {
reconciler *NodeEvictionLabelReconciler
req = ctrl.Request{NamespacedName: types.NamespacedName{Name: nodeName}}
fakeServer testhelper.FakeServer
reconcileNodeLoop = func(ctx context.Context, steps int) (res ctrl.Result, err error) {
for range steps {
res, err = nodeReconciler.Reconcile(ctx, req)
res, err = reconciler.Reconcile(ctx, req)
if err != nil {
return
}
}
return
}
)

BeforeEach(func() {
fakeServer = testhelper.SetupHTTP()
Expect(os.Setenv("KVM_HA_SERVICE_URL", fakeServer.Endpoint())).To(Succeed())
nodeReconciler = &NodeEvictionLabelReconciler{
Client: k8sClient,
Scheme: k8sClient.Scheme(),
}
BeforeEach(func(ctx context.Context) {
fakeServer = testhelper.SetupHTTP()
Expect(os.Setenv("KVM_HA_SERVICE_URL", fakeServer.Endpoint())).To(Succeed())

By("creating the namespace for the reconciler")
ns := &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "monsoon3"}}
Expect(client.IgnoreAlreadyExists(k8sClient.Create(ctx, ns))).To(Succeed())

By("creating the node resource")
resource := &corev1.Node{
ObjectMeta: metav1.ObjectMeta{
Name: nodeName,
Labels: map[string]string{
corev1.LabelHostname: hostName,
corev1.LabelTopologyRegion: region,
corev1.LabelTopologyZone: zone,
labelEvictionRequired: "true",
},
},
}
Expect(k8sClient.Create(ctx, resource)).To(Succeed())

By("creating the hypervisor resource")
hypervisor := &kvmv1.Hypervisor{
ObjectMeta: metav1.ObjectMeta{
Name: nodeName,
Labels: map[string]string{
corev1.LabelHostname: nodeName,
},
DeferCleanup(func() {
Expect(os.Unsetenv("KVM_HA_SERVICE_URL")).To(Succeed())
fakeServer.Teardown()
})

reconciler = &NodeEvictionLabelReconciler{
Client: k8sClient,
Scheme: k8sClient.Scheme(),
}

By("creating the namespace for the reconciler")
ns := &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "monsoon3"}}
Expect(client.IgnoreAlreadyExists(k8sClient.Create(ctx, ns))).To(Succeed())

By("creating the node resource")
resource := &corev1.Node{
ObjectMeta: metav1.ObjectMeta{
Name: nodeName,
Labels: map[string]string{
corev1.LabelHostname: hostName,
corev1.LabelTopologyRegion: region,
corev1.LabelTopologyZone: zone,
labelEvictionRequired: "true",
},
Spec: kvmv1.HypervisorSpec{
LifecycleEnabled: true,
},
}
Expect(k8sClient.Create(ctx, resource)).To(Succeed())

DeferCleanup(func(ctx context.Context) {
By("Cleanup the specific node")
Expect(k8sClient.Delete(ctx, resource)).To(Succeed())
})

By("creating the hypervisor resource")
hypervisor := &kvmv1.Hypervisor{
ObjectMeta: metav1.ObjectMeta{
Name: nodeName,
Labels: map[string]string{
corev1.LabelHostname: nodeName,
},
}
Expect(client.IgnoreAlreadyExists(k8sClient.Create(ctx, hypervisor))).To(Succeed())
},
Spec: kvmv1.HypervisorSpec{
LifecycleEnabled: true,
},
}
Expect(k8sClient.Create(ctx, hypervisor)).To(Succeed())
DeferCleanup(func(ctx context.Context) {
By("Cleanup the specific hypervisor")
Expect(client.IgnoreNotFound(k8sClient.Delete(ctx, hypervisor))).To(Succeed())
})

})

Context("When reconciling a node", func() {
BeforeEach(func(ctx context.Context) {
hypervisor := &kvmv1.Hypervisor{}
Expect(k8sClient.Get(ctx, types.NamespacedName{Name: nodeName}, hypervisor)).To(Succeed())
By("updating the hypervisor status sub-resource")
meta.SetStatusCondition(&hypervisor.Status.Conditions, metav1.Condition{
Type: ConditionTypeOnboarding,
Expand All @@ -111,27 +127,14 @@ var _ = Describe("Node Eviction Label Controller", func() {
Expect(k8sClient.Status().Update(ctx, hypervisor)).To(Succeed())
})

AfterEach(func() {
// Cleanup the hypervisor created for the test
hypervisor := &kvmv1.Hypervisor{ObjectMeta: metav1.ObjectMeta{Name: nodeName}}
By("Cleanup the specific hypervisor")
Expect(client.IgnoreNotFound(k8sClient.Delete(ctx, hypervisor))).To(Succeed())

// Cleanup the node created for the test
node := &corev1.Node{ObjectMeta: metav1.ObjectMeta{Name: nodeName}}
By("Cleanup the specific node")
Expect(client.IgnoreNotFound(k8sClient.Delete(ctx, node))).To(Succeed())
fakeServer.Teardown()
})

It("should successfully reconcile the resource", func() {
It("should successfully reconcile the resource", func(ctx context.Context) {
By("ConditionType the created resource")
_, err := reconcileNodeLoop(5)
_, err := reconcileNodeLoop(ctx, 5)
Expect(err).NotTo(HaveOccurred())

// expect node controller to create an eviction for the node
err = k8sClient.Get(ctx, types.NamespacedName{
Name: fmt.Sprintf("maintenance-required-%v", hostName),
Name: hostName,
Namespace: "monsoon3",
}, &kvmv1.Eviction{})
Expect(err).NotTo(HaveOccurred())
Expand Down