Skip to content
Open
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
4 changes: 3 additions & 1 deletion api/v1/hypervisor_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,9 @@ const (
// ConditionTypeReady is the type of condition for ready status of a hypervisor
ConditionTypeReady = "Ready"

// ConditionTypeTerminating is the type of condition for terminating status of a hypervisor
// ConditionTypeTerminating is set when the underlying Node is terminating —
// either because the legacy gardener node condition "Terminating" is present,
// or because the Node's deletionTimestamp has been set (gardener's future path).
ConditionTypeTerminating = "Terminating"

// ConditionTypeTainted is the type of condition for tainted status of a hypervisor
Expand Down
16 changes: 9 additions & 7 deletions internal/controller/hypervisor_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,15 +130,16 @@ func (hv *HypervisorController) Reconcile(ctx context.Context, req ctrl.Request)
}
}

// update terminating condition
// update terminating condition — fired by either the legacy gardener
// node condition or the node's deletion timestamp (gardener's future path)
nodeTerminationCondition := FindNodeStatusCondition(node.Status.Conditions, "Terminating")
if nodeTerminationCondition != nil && nodeTerminationCondition.Status == corev1.ConditionTrue {
// Node might be terminating, propagate condition to hypervisor
if (nodeTerminationCondition != nil && nodeTerminationCondition.Status == corev1.ConditionTrue) ||
!node.DeletionTimestamp.IsZero() {
meta.SetStatusCondition(&hypervisor.Status.Conditions, metav1.Condition{
Type: kvmv1.ConditionTypeTerminating,
Status: metav1.ConditionStatus(nodeTerminationCondition.Status),
Reason: nodeTerminationCondition.Reason,
Message: nodeTerminationCondition.Message,
Status: metav1.ConditionTrue,
Reason: kvmv1.ConditionReasonTerminating,
Message: "Node is terminating",
})
}

Expand Down Expand Up @@ -188,7 +189,8 @@ func (hv *HypervisorController) Reconcile(ctx context.Context, req ctrl.Request)
return ctrl.Result{}, fmt.Errorf("failed setting controller reference: %w", err)
}

if IsNodeConditionPresentAndEqual(node.Status.Conditions, "Terminating", corev1.ConditionTrue) {
if IsNodeConditionPresentAndEqual(node.Status.Conditions, "Terminating", corev1.ConditionTrue) ||
!node.DeletionTimestamp.IsZero() {
hypervisor.Spec.Maintenance = kvmv1.MaintenanceTermination
}

Expand Down
41 changes: 37 additions & 4 deletions internal/controller/hypervisor_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -318,13 +318,12 @@ var _ = Describe("Hypervisor Controller", func() {
}

By("should have set the terminating condition on the Hypervisor resource")
// Get the Hypervisor resource
updatedHypervisor := &kvmv1.Hypervisor{}
Expect(hypervisorController.Get(ctx, hypervisorName, updatedHypervisor)).To(Succeed())
Expect(updatedHypervisor.Status.Conditions).To(ContainElement(
SatisfyAll(
HaveField("Type", kvmv1.ConditionTypeTerminating),
HaveField("Reason", terminatingReason),
HaveField("Reason", kvmv1.ConditionReasonTerminating),
HaveField("Status", metav1.ConditionTrue),
),
))
Expand Down Expand Up @@ -366,8 +365,42 @@ var _ = Describe("Hypervisor Controller", func() {
Expect(updatedHypervisor.Status.Conditions).To(ContainElement(
SatisfyAll(
HaveField("Type", kvmv1.ConditionTypeTerminating),
HaveField("Reason", terminatingReason),
HaveField("Reason", kvmv1.ConditionReasonTerminating),
HaveField("Status", metav1.ConditionTrue),
),
))
})
})
Context("when only the deletion timestamp is set (no Terminating node condition)", func() {
BeforeEach(func(ctx SpecContext) {
// Use a different node that has no Terminating condition — only
// a deletion timestamp — to verify the new gardener signal path.
resource.Status.Conditions = nil
Expect(k8sClient.Status().Update(ctx, resource)).To(Succeed())

By("creating a Hypervisor so the existing-hypervisor path is exercised")
hypervisor := &kvmv1.Hypervisor{
ObjectMeta: metav1.ObjectMeta{Name: resource.Name},
}
Expect(k8sClient.Create(ctx, hypervisor)).To(Succeed())
DeferCleanup(func(ctx SpecContext) {
Expect(client.IgnoreNotFound(k8sClient.Delete(ctx, hypervisor))).To(Succeed())
})
})

It("should set the Terminating condition from the deletion timestamp", func(ctx SpecContext) {
_, err := hypervisorController.Reconcile(ctx, ctrl.Request{
NamespacedName: types.NamespacedName{Name: resource.Name},
})
Expect(err).NotTo(HaveOccurred())

hypervisor := &kvmv1.Hypervisor{}
Expect(k8sClient.Get(ctx, hypervisorName, hypervisor)).To(Succeed())
Expect(hypervisor.Status.Conditions).To(ContainElement(
SatisfyAll(
HaveField("Type", kvmv1.ConditionTypeTerminating),
HaveField("Status", metav1.ConditionTrue),
HaveField("Reason", kvmv1.ConditionReasonTerminating),
),
))
})
Expand Down Expand Up @@ -602,7 +635,7 @@ var _ = Describe("Hypervisor Controller", func() {
SatisfyAll(
HaveField("Type", kvmv1.ConditionTypeTerminating),
HaveField("Status", metav1.ConditionTrue),
HaveField("Reason", terminatingReason),
HaveField("Reason", kvmv1.ConditionReasonTerminating),
),
))
})
Expand Down
Loading