Skip to content

Commit

Permalink
add functional tests
Browse files Browse the repository at this point in the history
  • Loading branch information
jmdeal authored and AndrewSirenko committed Jul 26, 2024
1 parent 20c2a75 commit 2e30250
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 4 deletions.
74 changes: 74 additions & 0 deletions pkg/controllers/node/termination/suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -763,6 +763,80 @@ var _ = Describe("Termination", func() {
ExpectSingletonReconciled(ctx, queue)
ExpectDeleted(ctx, env.Client, pod)
})
Context("VolumeAttachments", func() {
It("should wait for volume attachments", func() {
va := test.VolumeAttachment(test.VolumeAttachmentOptions{
NodeName: node.Name,
VolumeName: "foo",
})
ExpectApplied(ctx, env.Client, node, nodeClaim, nodePool, va)
Expect(env.Client.Delete(ctx, node)).To(Succeed())

ExpectObjectReconciled(ctx, env.Client, terminationController, node)
ExpectObjectReconciled(ctx, env.Client, terminationController, node)
ExpectExists(ctx, env.Client, node)

ExpectDeleted(ctx, env.Client, va)
ExpectObjectReconciled(ctx, env.Client, terminationController, node)
ExpectObjectReconciled(ctx, env.Client, terminationController, node)
ExpectNotFound(ctx, env.Client, node)
})
It("should only wait for volume attachments associated with drainable pods", func() {
vaDrainable := test.VolumeAttachment(test.VolumeAttachmentOptions{
NodeName: node.Name,
VolumeName: "foo",
})
vaNonDrainable := test.VolumeAttachment(test.VolumeAttachmentOptions{
NodeName: node.Name,
VolumeName: "bar",
})
pvc := test.PersistentVolumeClaim(test.PersistentVolumeClaimOptions{
VolumeName: "bar",
})
pod := test.Pod(test.PodOptions{
ObjectMeta: metav1.ObjectMeta{
OwnerReferences: defaultOwnerRefs,
},
Tolerations: []corev1.Toleration{{
Key: v1.DisruptionTaintKey,
Operator: corev1.TolerationOpExists,
}},
PersistentVolumeClaims: []string{pvc.Name},
})
ExpectApplied(ctx, env.Client, node, nodeClaim, nodePool, vaDrainable, vaNonDrainable, pod, pvc)
ExpectManualBinding(ctx, env.Client, pod, node)
Expect(env.Client.Delete(ctx, node)).To(Succeed())

ExpectObjectReconciled(ctx, env.Client, terminationController, node)
ExpectObjectReconciled(ctx, env.Client, terminationController, node)
ExpectExists(ctx, env.Client, node)

ExpectDeleted(ctx, env.Client, vaDrainable)
ExpectObjectReconciled(ctx, env.Client, terminationController, node)
ExpectObjectReconciled(ctx, env.Client, terminationController, node)
ExpectNotFound(ctx, env.Client, node)
})
It("should wait for volume attachments until the nodeclaim's termination grace period expires", func() {
va := test.VolumeAttachment(test.VolumeAttachmentOptions{
NodeName: node.Name,
VolumeName: "foo",
})
nodeClaim.Annotations = map[string]string{
v1.NodeClaimTerminationTimestampAnnotationKey: fakeClock.Now().Add(time.Minute).Format(time.RFC3339),
}
ExpectApplied(ctx, env.Client, node, nodeClaim, nodePool, va)
Expect(env.Client.Delete(ctx, node)).To(Succeed())

ExpectObjectReconciled(ctx, env.Client, terminationController, node)
ExpectObjectReconciled(ctx, env.Client, terminationController, node)
ExpectExists(ctx, env.Client, node)

fakeClock.Step(5 * time.Minute)
ExpectObjectReconciled(ctx, env.Client, terminationController, node)
ExpectObjectReconciled(ctx, env.Client, terminationController, node)
ExpectNotFound(ctx, env.Client, node)
})
})
})
Context("Metrics", func() {
It("should fire the terminationSummary metric when deleting nodes", func() {
Expand Down
25 changes: 25 additions & 0 deletions pkg/test/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,3 +153,28 @@ func StorageClass(overrides ...StorageClassOptions) *storagev1.StorageClass {
VolumeBindingMode: options.VolumeBindingMode,
}
}

type VolumeAttachmentOptions struct {
metav1.ObjectMeta
NodeName string
VolumeName string
}

func VolumeAttachment(overrides ...VolumeAttachmentOptions) *storagev1.VolumeAttachment {
options := VolumeAttachmentOptions{}
for _, opts := range overrides {
if err := mergo.Merge(&options, opts, mergo.WithOverride); err != nil {
panic(fmt.Sprintf("Failed to merge options: %s", err))
}
}
return &storagev1.VolumeAttachment{
ObjectMeta: ObjectMeta(options.ObjectMeta),
Spec: storagev1.VolumeAttachmentSpec{
NodeName: options.NodeName,
Attacher: "fake-csi",
Source: storagev1.VolumeAttachmentSource{
PersistentVolumeName: lo.ToPtr(options.VolumeName),
},
},
}
}
6 changes: 2 additions & 4 deletions pkg/utils/node/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,9 @@ func GetProvisionablePods(ctx context.Context, kubeClient client.Client) ([]*cor
func GetVolumeAttachments(ctx context.Context, kubeClient client.Client, node *corev1.Node) ([]*storagev1.VolumeAttachment, error) {
var volumeAttachmentList storagev1.VolumeAttachmentList
if err := kubeClient.List(ctx, &volumeAttachmentList, client.MatchingFields{"spec.nodeName": node.Name}); err != nil {
return nil, fmt.Errorf("listing volumeattachments, %w", err)
return nil, fmt.Errorf("listing volumeAttachments, %w", err)
}
return lo.FilterMap(volumeAttachmentList.Items, func(v storagev1.VolumeAttachment, _ int) (*storagev1.VolumeAttachment, bool) {
return &v, v.Spec.NodeName == node.Name
}), nil
return lo.ToSlicePtr(volumeAttachmentList.Items), nil
}

func GetCondition(n *corev1.Node, match corev1.NodeConditionType) corev1.NodeCondition {
Expand Down

0 comments on commit 2e30250

Please sign in to comment.