Skip to content

Commit e92b0c3

Browse files
Add controller tests
1 parent 04e1c00 commit e92b0c3

File tree

1 file changed

+155
-2
lines changed

1 file changed

+155
-2
lines changed

internal/controller/hypervisor_controller_test.go

Lines changed: 155 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,20 @@ package controller
1919

2020
import (
2121
"context"
22+
"errors"
23+
"time"
2224

2325
kvmv1 "github.com/cobaltcore-dev/openstack-hypervisor-operator/api/v1"
2426
"github.com/coreos/go-systemd/v22/dbus"
27+
golibvirt "github.com/digitalocean/go-libvirt"
2528
. "github.com/onsi/ginkgo/v2"
2629
. "github.com/onsi/gomega"
27-
"k8s.io/apimachinery/pkg/api/errors"
30+
apierrors "k8s.io/apimachinery/pkg/api/errors"
2831
"k8s.io/apimachinery/pkg/api/resource"
2932
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3033
"k8s.io/apimachinery/pkg/types"
34+
ctrl "sigs.k8s.io/controller-runtime"
35+
"sigs.k8s.io/controller-runtime/pkg/event"
3136
"sigs.k8s.io/controller-runtime/pkg/reconcile"
3237

3338
"github.com/cobaltcore-dev/kvm-node-agent/internal/libvirt"
@@ -36,6 +41,154 @@ import (
3641
)
3742

3843
var _ = Describe("Hypervisor Controller", func() {
44+
Context("When testing Start method", func() {
45+
It("should successfully start and subscribe to libvirt events", func() {
46+
ctx := context.Background()
47+
eventCallbackCalled := false
48+
49+
controllerReconciler := &HypervisorReconciler{
50+
Client: k8sClient,
51+
Scheme: k8sClient.Scheme(),
52+
Libvirt: &libvirt.InterfaceMock{
53+
ConnectFunc: func() error {
54+
return nil
55+
},
56+
WatchDomainChangesFunc: func(eventId golibvirt.DomainEventID, handlerId string, handler func(context.Context, any)) {
57+
eventCallbackCalled = true
58+
Expect(handlerId).To(Equal("reconcile-on-domain-lifecycle"))
59+
},
60+
},
61+
reconcileCh: make(chan event.GenericEvent, 1),
62+
}
63+
64+
err := controllerReconciler.Start(ctx)
65+
Expect(err).NotTo(HaveOccurred())
66+
Expect(eventCallbackCalled).To(BeTrue())
67+
})
68+
69+
It("should fail when libvirt connection fails", func() {
70+
ctx := context.Background()
71+
72+
controllerReconciler := &HypervisorReconciler{
73+
Client: k8sClient,
74+
Scheme: k8sClient.Scheme(),
75+
Libvirt: &libvirt.InterfaceMock{
76+
ConnectFunc: func() error {
77+
return errors.New("connection failed")
78+
},
79+
},
80+
reconcileCh: make(chan event.GenericEvent, 1),
81+
}
82+
83+
err := controllerReconciler.Start(ctx)
84+
Expect(err).To(HaveOccurred())
85+
Expect(err.Error()).To(ContainSubstring("connection failed"))
86+
})
87+
})
88+
89+
Context("When testing triggerReconcile method", func() {
90+
It("should send an event to reconcile channel", func() {
91+
const testHostname = "test-host"
92+
const testNamespace = "test-namespace"
93+
94+
// Override hostname and namespace for this test
95+
originalHostname := sys.Hostname
96+
originalNamespace := sys.Namespace
97+
sys.Hostname = testHostname
98+
sys.Namespace = testNamespace
99+
defer func() {
100+
sys.Hostname = originalHostname
101+
sys.Namespace = originalNamespace
102+
}()
103+
104+
controllerReconciler := &HypervisorReconciler{
105+
Client: k8sClient,
106+
Scheme: k8sClient.Scheme(),
107+
reconcileCh: make(chan event.GenericEvent, 1),
108+
}
109+
110+
// Trigger reconcile in a goroutine to avoid blocking
111+
go controllerReconciler.triggerReconcile()
112+
113+
// Wait for the event with a timeout
114+
select {
115+
case evt := <-controllerReconciler.reconcileCh:
116+
Expect(evt.Object).NotTo(BeNil())
117+
hv, ok := evt.Object.(*kvmv1.Hypervisor)
118+
Expect(ok).To(BeTrue())
119+
Expect(hv.Name).To(Equal(testHostname))
120+
Expect(hv.Namespace).To(Equal(testNamespace))
121+
Expect(hv.Kind).To(Equal("Hypervisor"))
122+
Expect(hv.APIVersion).To(Equal("kvm.cloud.sap/v1"))
123+
case <-time.After(2 * time.Second):
124+
Fail("timeout waiting for reconcile event")
125+
}
126+
})
127+
})
128+
129+
Context("When testing SetupWithManager method", func() {
130+
It("should successfully setup controller with manager", func() {
131+
// Create a test manager
132+
mgr, err := ctrl.NewManager(cfg, ctrl.Options{
133+
Scheme: k8sClient.Scheme(),
134+
})
135+
Expect(err).NotTo(HaveOccurred())
136+
137+
controllerReconciler := &HypervisorReconciler{
138+
Client: k8sClient,
139+
Scheme: k8sClient.Scheme(),
140+
Systemd: &systemd.InterfaceMock{
141+
DescribeFunc: func(ctx context.Context) (*systemd.Descriptor, error) {
142+
return &systemd.Descriptor{
143+
OperatingSystemReleaseData: []string{
144+
"PRETTY_NAME=\"Garden Linux 1877.8\"",
145+
"GARDENLINUX_VERSION=1877.8",
146+
},
147+
KernelVersion: "6.1.0",
148+
KernelRelease: "6.1.0-gardenlinux",
149+
KernelName: "Linux",
150+
HardwareVendor: "Test Vendor",
151+
HardwareModel: "Test Model",
152+
HardwareSerial: "TEST123",
153+
FirmwareVersion: "1.0",
154+
FirmwareVendor: "Test BIOS",
155+
FirmwareDate: time.Now().UnixMicro(),
156+
}, nil
157+
},
158+
},
159+
}
160+
161+
err = controllerReconciler.SetupWithManager(mgr)
162+
Expect(err).NotTo(HaveOccurred())
163+
Expect(controllerReconciler.reconcileCh).NotTo(BeNil())
164+
Expect(controllerReconciler.osDescriptor).NotTo(BeNil())
165+
Expect(controllerReconciler.osDescriptor.OperatingSystemReleaseData).To(HaveLen(2))
166+
})
167+
168+
It("should fail when systemd Describe returns error", func() {
169+
// Create a test manager
170+
mgr, err := ctrl.NewManager(cfg, ctrl.Options{
171+
Scheme: k8sClient.Scheme(),
172+
})
173+
Expect(err).NotTo(HaveOccurred())
174+
175+
controllerReconciler := &HypervisorReconciler{
176+
Client: k8sClient,
177+
Scheme: k8sClient.Scheme(),
178+
Systemd: &systemd.InterfaceMock{
179+
DescribeFunc: func(ctx context.Context) (*systemd.Descriptor, error) {
180+
return nil, errors.New("systemd describe failed")
181+
},
182+
},
183+
}
184+
185+
err = controllerReconciler.SetupWithManager(mgr)
186+
Expect(err).To(HaveOccurred())
187+
Expect(err.Error()).To(ContainSubstring("unable to get Systemd hostname describe()"))
188+
Expect(err.Error()).To(ContainSubstring("systemd describe failed"))
189+
})
190+
})
191+
39192
Context("When reconciling a resource", func() {
40193
const resourceName = "test-resource"
41194

@@ -50,7 +203,7 @@ var _ = Describe("Hypervisor Controller", func() {
50203
BeforeEach(func() {
51204
By("creating the custom resource for the Kind Hypervisor")
52205
err := k8sClient.Get(ctx, typeNamespacedName, hypervisor)
53-
if err != nil && errors.IsNotFound(err) {
206+
if err != nil && apierrors.IsNotFound(err) {
54207
resource := &kvmv1.Hypervisor{
55208
ObjectMeta: metav1.ObjectMeta{
56209
Name: resourceName,

0 commit comments

Comments
 (0)