1
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 )
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
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 )
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
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 }
190
View as plain text