k8s.io/kubernetes@v1.29.3/pkg/volume/csi/csi_metrics_test.go (about) 1 /* 2 Copyright 2019 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 csi 18 19 import ( 20 "io" 21 "reflect" 22 "testing" 23 24 csipbv1 "github.com/container-storage-interface/spec/lib/go/csi" 25 "k8s.io/apimachinery/pkg/api/resource" 26 "k8s.io/kubernetes/pkg/volume" 27 "k8s.io/kubernetes/pkg/volume/csi/fake" 28 volumetypes "k8s.io/kubernetes/pkg/volume/util/types" 29 ) 30 31 func TestGetMetrics(t *testing.T) { 32 tests := []struct { 33 name string 34 volumeID string 35 targetPath string 36 expectSuccess bool 37 }{ 38 { 39 name: "with valid name and volume id", 40 expectSuccess: true, 41 volumeID: "foobar", 42 targetPath: "/mnt/foo", 43 }, 44 } 45 46 for _, tc := range tests { 47 metricsGetter := &metricsCsi{volumeID: tc.volumeID, targetPath: tc.targetPath} 48 metricsGetter.csiClient = &csiDriverClient{ 49 driverName: "com.google.gcepd", 50 nodeV1ClientCreator: func(addr csiAddr, m *MetricsManager) (csipbv1.NodeClient, io.Closer, error) { 51 nodeClient := fake.NewNodeClientWithVolumeStats(true /* VolumeStatsCapable */) 52 fakeCloser := fake.NewCloser(t) 53 nodeClient.SetNodeVolumeStatsResp(getRawVolumeInfo()) 54 return nodeClient, fakeCloser, nil 55 }, 56 } 57 metrics, err := metricsGetter.GetMetrics() 58 if err != nil { 59 t.Fatalf("for %s: unexpected error : %v", tc.name, err) 60 } 61 if metrics == nil { 62 t.Fatalf("unexpected nil metrics") 63 } 64 expectedMetrics := getRawVolumeInfo() 65 for _, usage := range expectedMetrics.Usage { 66 if usage.Unit == csipbv1.VolumeUsage_BYTES { 67 availableBytes := resource.NewQuantity(usage.Available, resource.BinarySI) 68 totalBytes := resource.NewQuantity(usage.Total, resource.BinarySI) 69 usedBytes := resource.NewQuantity(usage.Used, resource.BinarySI) 70 if metrics.Available.Cmp(*availableBytes) != 0 { 71 t.Fatalf("for %s: error: expected :%v , got: %v", tc.name, *availableBytes, *(metrics.Available)) 72 } 73 if metrics.Capacity.Cmp(*totalBytes) != 0 { 74 t.Fatalf("for %s: error: expected :%v , got: %v", tc.name, *totalBytes, *(metrics.Capacity)) 75 } 76 if metrics.Used.Cmp(*usedBytes) != 0 { 77 t.Fatalf("for %s: error: expected :%v , got: %v", tc.name, *usedBytes, *(metrics.Used)) 78 } 79 } 80 81 if usage.Unit == csipbv1.VolumeUsage_INODES { 82 freeInodes := resource.NewQuantity(usage.Available, resource.BinarySI) 83 inodes := resource.NewQuantity(usage.Total, resource.BinarySI) 84 usedInodes := resource.NewQuantity(usage.Used, resource.BinarySI) 85 if metrics.InodesFree.Cmp(*freeInodes) != 0 { 86 t.Fatalf("for %s: error: expected :%v , got: %v", tc.name, *freeInodes, *(metrics.InodesFree)) 87 } 88 if metrics.Inodes.Cmp(*inodes) != 0 { 89 t.Fatalf("for %s: error: expected :%v , got: %v", tc.name, *inodes, *(metrics.Inodes)) 90 } 91 if metrics.InodesUsed.Cmp(*usedInodes) != 0 { 92 t.Fatalf("for %s: error: expected :%v , got: %v", tc.name, *usedInodes, *(metrics.InodesUsed)) 93 } 94 } 95 } 96 } 97 } 98 99 // test GetMetrics with a volume that does not support stats 100 func TestGetMetricsDriverNotSupportStats(t *testing.T) { 101 tests := []struct { 102 name string 103 volumeID string 104 targetPath string 105 expectSuccess bool 106 }{ 107 { 108 name: "volume created by simple driver", 109 expectSuccess: true, 110 volumeID: "foobar", 111 targetPath: "/mnt/foo", 112 }, 113 } 114 115 for _, tc := range tests { 116 metricsGetter := &metricsCsi{volumeID: tc.volumeID, targetPath: tc.targetPath} 117 metricsGetter.csiClient = &csiDriverClient{ 118 driverName: "com.simple.SimpleDriver", 119 nodeV1ClientCreator: func(addr csiAddr, m *MetricsManager) (csipbv1.NodeClient, io.Closer, error) { 120 nodeClient := fake.NewNodeClientWithVolumeStats(false /* VolumeStatsCapable */) 121 fakeCloser := fake.NewCloser(t) 122 nodeClient.SetNodeVolumeStatsResp(getRawVolumeInfo()) 123 return nodeClient, fakeCloser, nil 124 }, 125 } 126 metrics, err := metricsGetter.GetMetrics() 127 if err == nil { 128 t.Fatalf("for %s: expected error, but got nil error", tc.name) 129 } 130 131 if !volume.IsNotSupported(err) { 132 t.Fatalf("for %s, expected not supported error but got: %v", tc.name, err) 133 } 134 135 if metrics != nil { 136 t.Fatalf("for %s, expected nil metrics, but got: %v", tc.name, metrics) 137 } 138 } 139 140 } 141 142 // test GetMetrics with a volume that does not support stats 143 func TestGetMetricsDriverNotFound(t *testing.T) { 144 transientError := volumetypes.NewTransientOperationFailure("") 145 tests := []struct { 146 name string 147 volumeID string 148 targetPath string 149 exitError error 150 }{ 151 { 152 name: "volume with no driver", 153 volumeID: "foobar", 154 targetPath: "/mnt/foo", 155 exitError: transientError, 156 }, 157 } 158 159 for _, tc := range tests { 160 metricsGetter := &metricsCsi{volumeID: tc.volumeID, targetPath: tc.targetPath} 161 metricsGetter.driverName = "unknown-driver" 162 _, err := metricsGetter.GetMetrics() 163 if err == nil { 164 t.Errorf("test should fail, but no error occurred") 165 } else if reflect.TypeOf(tc.exitError) != reflect.TypeOf(err) { 166 t.Fatalf("expected exitError type: %v got: %v (%v)", reflect.TypeOf(transientError), reflect.TypeOf(err), err) 167 } 168 } 169 170 } 171 172 func getRawVolumeInfo() *csipbv1.NodeGetVolumeStatsResponse { 173 return &csipbv1.NodeGetVolumeStatsResponse{ 174 Usage: []*csipbv1.VolumeUsage{ 175 { 176 Available: int64(10), 177 Total: int64(10), 178 Used: int64(2), 179 Unit: csipbv1.VolumeUsage_BYTES, 180 }, 181 { 182 Available: int64(100), 183 Total: int64(100), 184 Used: int64(20), 185 Unit: csipbv1.VolumeUsage_INODES, 186 }, 187 }, 188 } 189 }