...

Source file src/k8s.io/kubernetes/pkg/volume/util/operationexecutor/node_expander_test.go

Documentation: k8s.io/kubernetes/pkg/volume/util/operationexecutor

     1  /*
     2  Copyright 2022 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    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  		// desired size, defaults to pv.Spec.Capacity
    41  		desiredSize *resource.Quantity
    42  		// actualSize, defaults to pvc.Status.Capacity
    43  		actualSize *resource.Quantity
    44  
    45  		// expectations of test
    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