1
16
17 package operationexecutor
18
19 import (
20 "testing"
21
22 v1 "k8s.io/api/core/v1"
23 "k8s.io/apimachinery/pkg/api/resource"
24 utilfeature "k8s.io/apiserver/pkg/util/feature"
25 featuregatetesting "k8s.io/component-base/featuregate/testing"
26 "k8s.io/kubernetes/pkg/features"
27 "k8s.io/kubernetes/pkg/volume"
28 volumetesting "k8s.io/kubernetes/pkg/volume/testing"
29 )
30
31 func TestNodeExpander(t *testing.T) {
32 nodeResizeFailed := v1.PersistentVolumeClaimNodeResizeFailed
33
34 nodeResizePending := v1.PersistentVolumeClaimNodeResizePending
35 var tests = []struct {
36 name string
37 pvc *v1.PersistentVolumeClaim
38 pv *v1.PersistentVolume
39
40
41 desiredSize *resource.Quantity
42
43 actualSize *resource.Quantity
44
45
46 expectedResizeStatus v1.ClaimResourceStatus
47 expectedStatusSize resource.Quantity
48 expectResizeCall bool
49 assumeResizeOpAsFinished bool
50 expectError bool
51 }{
52 {
53 name: "pv.spec.cap > pvc.status.cap, resizeStatus=node_expansion_failed",
54 pvc: getTestPVC("test-vol0", "2G", "1G", "", &nodeResizeFailed),
55 pv: getTestPV("test-vol0", "2G"),
56
57 expectedResizeStatus: nodeResizeFailed,
58 expectResizeCall: false,
59 assumeResizeOpAsFinished: true,
60 expectedStatusSize: resource.MustParse("1G"),
61 },
62 {
63 name: "pv.spec.cap > pvc.status.cap, resizeStatus=node_expansion_pending",
64 pvc: getTestPVC("test-vol0", "2G", "1G", "2G", &nodeResizePending),
65 pv: getTestPV("test-vol0", "2G"),
66 expectedResizeStatus: "",
67 expectResizeCall: true,
68 assumeResizeOpAsFinished: true,
69 expectedStatusSize: resource.MustParse("2G"),
70 },
71 {
72 name: "pv.spec.cap > pvc.status.cap, resizeStatus=node_expansion_pending, reize_op=failing",
73 pvc: getTestPVC(volumetesting.AlwaysFailNodeExpansion, "2G", "1G", "2G", &nodeResizePending),
74 pv: getTestPV(volumetesting.AlwaysFailNodeExpansion, "2G"),
75 expectError: true,
76 expectedResizeStatus: nodeResizeFailed,
77 expectResizeCall: true,
78 assumeResizeOpAsFinished: true,
79 expectedStatusSize: resource.MustParse("1G"),
80 },
81 {
82 name: "pv.spec.cap = pvc.status.cap, resizeStatus='', desiredSize > actualSize",
83 pvc: getTestPVC("test-vol0", "2G", "2G", "2G", nil),
84 pv: getTestPV("test-vol0", "2G"),
85
86 expectedResizeStatus: "",
87 expectResizeCall: true,
88 assumeResizeOpAsFinished: true,
89 expectedStatusSize: resource.MustParse("2G"),
90 },
91 }
92
93 for i := range tests {
94 test := tests[i]
95 t.Run(test.name, func(t *testing.T) {
96 defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.RecoverVolumeExpansionFailure, true)()
97 volumePluginMgr, fakePlugin := volumetesting.GetTestKubeletVolumePluginMgr(t)
98
99 pvc := test.pvc
100 pv := test.pv
101 pod := getTestPod("test-pod", pvc.Name)
102 og := getTestOperationGenerator(volumePluginMgr, pvc, pv)
103
104 vmt := VolumeToMount{
105 Pod: pod,
106 VolumeName: v1.UniqueVolumeName(pv.Name),
107 VolumeSpec: volume.NewSpecFromPersistentVolume(pv, false),
108 }
109 desiredSize := test.desiredSize
110 if desiredSize == nil {
111 desiredSize = pv.Spec.Capacity.Storage()
112 }
113 actualSize := test.actualSize
114 if actualSize == nil {
115 actualSize = pvc.Status.Capacity.Storage()
116 }
117 resizeOp := nodeResizeOperationOpts{
118 pvc: pvc,
119 pv: pv,
120 volumePlugin: fakePlugin,
121 vmt: vmt,
122 actualStateOfWorld: nil,
123 pluginResizeOpts: volume.NodeResizeOptions{
124 VolumeSpec: vmt.VolumeSpec,
125 NewSize: *desiredSize,
126 OldSize: *actualSize,
127 },
128 }
129 ogInstance, _ := og.(*operationGenerator)
130 nodeExpander := newNodeExpander(resizeOp, ogInstance.kubeClient, ogInstance.recorder)
131
132 _, err, expansionResponse := nodeExpander.expandOnPlugin()
133
134 pvc = nodeExpander.pvc
135 pvcStatusCap := pvc.Status.Capacity[v1.ResourceStorage]
136
137 if !test.expectError && err != nil {
138 t.Errorf("For test %s, expected no error got: %v", test.name, err)
139 }
140 if test.expectError && err == nil {
141 t.Errorf("For test %s, expected error but got none", test.name)
142 }
143
144 if test.expectResizeCall != expansionResponse.resizeCalledOnPlugin {
145 t.Errorf("For test %s, expected resize called %t, got %t", test.name, test.expectResizeCall, expansionResponse.resizeCalledOnPlugin)
146 }
147 if test.assumeResizeOpAsFinished != expansionResponse.assumeResizeFinished {
148 t.Errorf("For test %s, expected assumeResizeOpAsFinished %t, got %t", test.name, test.assumeResizeOpAsFinished, expansionResponse.assumeResizeFinished)
149 }
150 allocatedResourceStatus := pvc.Status.AllocatedResourceStatuses
151 resizeStatus := allocatedResourceStatus[v1.ResourceStorage]
152
153 if test.expectedResizeStatus != resizeStatus {
154 t.Errorf("For test %s, expected resizeStatus %v, got %v", test.name, test.expectedResizeStatus, resizeStatus)
155 }
156 if pvcStatusCap.Cmp(test.expectedStatusSize) != 0 {
157 t.Errorf("For test %s, expected status size %s, got %s", test.name, test.expectedStatusSize.String(), pvcStatusCap.String())
158 }
159 })
160 }
161 }
162
View as plain text