@@ -51,14 +51,34 @@ const (
51
51
serverSock = "server.sock"
52
52
)
53
53
54
+ type identityServer struct {}
55
+
56
+ func (ids * identityServer ) GetPluginInfo (ctx context.Context , req * csi.GetPluginInfoRequest ) (* csi.GetPluginInfoResponse , error ) {
57
+ return nil , status .Error (codes .Unimplemented , "Unimplemented" )
58
+ }
59
+
60
+ func (ids * identityServer ) Probe (ctx context.Context , req * csi.ProbeRequest ) (* csi.ProbeResponse , error ) {
61
+ return nil , status .Error (codes .Unimplemented , "Unimplemented" )
62
+ }
63
+
64
+ func (ids * identityServer ) GetPluginCapabilities (ctx context.Context , req * csi.GetPluginCapabilitiesRequest ) (* csi.GetPluginCapabilitiesResponse , error ) {
65
+ return nil , status .Error (codes .Unimplemented , "Unimplemented" )
66
+ }
67
+
54
68
// startServer creates a gRPC server without any registered services.
55
69
// The returned address can be used to connect to it. The cleanup
56
70
// function stops it. It can be called multiple times.
57
- func startServer (t * testing.T , tmp string , identity csi.IdentityServer , controller csi.ControllerServer ) (string , func ()) {
71
+ func startServer (t * testing.T , tmp string , identity csi.IdentityServer , controller csi.ControllerServer , cmm metrics. CSIMetricsManager ) (string , func ()) {
58
72
addr := path .Join (tmp , serverSock )
59
73
listener , err := net .Listen ("unix" , addr )
60
74
require .NoError (t , err , "listening on %s" , addr )
61
- server := grpc .NewServer ()
75
+ var opts []grpc.ServerOption
76
+ if cmm != nil {
77
+ opts = append (opts ,
78
+ grpc .UnaryInterceptor (ExtendedCSIMetricsManager {cmm }.RecordMetricsServerInterceptor ),
79
+ )
80
+ }
81
+ server := grpc .NewServer (opts ... )
62
82
if identity != nil {
63
83
csi .RegisterIdentityServer (server , identity )
64
84
}
@@ -85,7 +105,7 @@ func startServer(t *testing.T, tmp string, identity csi.IdentityServer, controll
85
105
func TestConnect (t * testing.T ) {
86
106
tmp := tmpDir (t )
87
107
defer os .RemoveAll (tmp )
88
- addr , stopServer := startServer (t , tmp , nil , nil )
108
+ addr , stopServer := startServer (t , tmp , nil , nil , nil )
89
109
defer stopServer ()
90
110
91
111
conn , err := Connect (addr , metrics .NewCSIMetricsManager ("fake.csi.driver.io" ))
@@ -100,7 +120,7 @@ func TestConnect(t *testing.T) {
100
120
func TestConnectUnix (t * testing.T ) {
101
121
tmp := tmpDir (t )
102
122
defer os .RemoveAll (tmp )
103
- addr , stopServer := startServer (t , tmp , nil , nil )
123
+ addr , stopServer := startServer (t , tmp , nil , nil , nil )
104
124
defer stopServer ()
105
125
106
126
conn , err := Connect ("unix:///" + addr , metrics .NewCSIMetricsManager ("fake.csi.driver.io" ))
@@ -141,7 +161,7 @@ func TestWaitForServer(t *testing.T) {
141
161
t .Logf ("sleeping %s before starting server" , delay )
142
162
time .Sleep (delay )
143
163
startTimeServer = time .Now ()
144
- _ , stopServer = startServer (t , tmp , nil , nil )
164
+ _ , stopServer = startServer (t , tmp , nil , nil , nil )
145
165
}()
146
166
conn , err := Connect (path .Join (tmp , serverSock ), metrics .NewCSIMetricsManager ("fake.csi.driver.io" ))
147
167
if assert .NoError (t , err , "connect via absolute path" ) {
@@ -175,7 +195,7 @@ func TestTimout(t *testing.T) {
175
195
func TestReconnect (t * testing.T ) {
176
196
tmp := tmpDir (t )
177
197
defer os .RemoveAll (tmp )
178
- addr , stopServer := startServer (t , tmp , nil , nil )
198
+ addr , stopServer := startServer (t , tmp , nil , nil , nil )
179
199
defer func () {
180
200
stopServer ()
181
201
}()
@@ -202,7 +222,7 @@ func TestReconnect(t *testing.T) {
202
222
}
203
223
204
224
// No reconnection either when the server comes back.
205
- _ , stopServer = startServer (t , tmp , nil , nil )
225
+ _ , stopServer = startServer (t , tmp , nil , nil , nil )
206
226
// We need to give gRPC some time. It does not attempt to reconnect
207
227
// immediately. If we send the method call too soon, the test passes
208
228
// even though a later method call will go through again.
@@ -220,7 +240,7 @@ func TestReconnect(t *testing.T) {
220
240
func TestDisconnect (t * testing.T ) {
221
241
tmp := tmpDir (t )
222
242
defer os .RemoveAll (tmp )
223
- addr , stopServer := startServer (t , tmp , nil , nil )
243
+ addr , stopServer := startServer (t , tmp , nil , nil , nil )
224
244
defer func () {
225
245
stopServer ()
226
246
}()
@@ -251,7 +271,7 @@ func TestDisconnect(t *testing.T) {
251
271
}
252
272
253
273
// No reconnection either when the server comes back.
254
- _ , stopServer = startServer (t , tmp , nil , nil )
274
+ _ , stopServer = startServer (t , tmp , nil , nil , nil )
255
275
// We need to give gRPC some time. It does not attempt to reconnect
256
276
// immediately. If we send the method call too soon, the test passes
257
277
// even though a later method call will go through again.
@@ -271,7 +291,7 @@ func TestDisconnect(t *testing.T) {
271
291
func TestExplicitReconnect (t * testing.T ) {
272
292
tmp := tmpDir (t )
273
293
defer os .RemoveAll (tmp )
274
- addr , stopServer := startServer (t , tmp , nil , nil )
294
+ addr , stopServer := startServer (t , tmp , nil , nil , nil )
275
295
defer func () {
276
296
stopServer ()
277
297
}()
@@ -302,7 +322,7 @@ func TestExplicitReconnect(t *testing.T) {
302
322
}
303
323
304
324
// No reconnection either when the server comes back.
305
- _ , stopServer = startServer (t , tmp , nil , nil )
325
+ _ , stopServer = startServer (t , tmp , nil , nil , nil )
306
326
// We need to give gRPC some time. It does not attempt to reconnect
307
327
// immediately. If we send the method call too soon, the test passes
308
328
// even though a later method call will go through again.
@@ -322,7 +342,12 @@ func TestExplicitReconnect(t *testing.T) {
322
342
func TestConnectMetrics (t * testing.T ) {
323
343
tmp := tmpDir (t )
324
344
defer os .RemoveAll (tmp )
325
- addr , stopServer := startServer (t , tmp , nil , nil )
345
+ cmmServer := metrics .NewCSIMetricsManager ("fake.csi.driver.io" ,
346
+ metrics .WithSubsystem (metrics .SubsystemPlugin ),
347
+ )
348
+ // We have to have a real implementation of the gRPC call, otherwise the metrics
349
+ // interceptor is not called. The CSI identity service is used because it's simple.
350
+ addr , stopServer := startServer (t , tmp , & identityServer {}, nil , cmmServer )
326
351
defer stopServer ()
327
352
328
353
cmm := metrics .NewCSIMetricsManager ("fake.csi.driver.io" )
@@ -332,38 +357,49 @@ func TestConnectMetrics(t *testing.T) {
332
357
defer conn .Close ()
333
358
assert .Equal (t , connectivity .Ready , conn .GetState (), "connection ready" )
334
359
335
- if err := conn .Invoke (context .Background (), "/csi.v1.Controller/ControllerGetCapabilities" , nil , nil ); assert .Error (t , err ) {
360
+ identityClient := csi .NewIdentityClient (conn )
361
+ if _ , err := identityClient .GetPluginInfo (context .Background (), & csi.GetPluginInfoRequest {}); assert .Error (t , err ) {
336
362
errStatus , _ := status .FromError (err )
337
363
assert .Equal (t , codes .Unimplemented , errStatus .Code (), "not implemented" )
338
364
}
339
365
}
340
366
341
367
expectedMetrics := `# HELP csi_sidecar_operations_seconds [ALPHA] Container Storage Interface operation duration with gRPC error code status total
342
368
# TYPE csi_sidecar_operations_seconds histogram
343
- csi_sidecar_operations_seconds_bucket{driver_name="fake.csi.driver.io",grpc_status_code="Unimplemented",method_name="/csi.v1.Controller/ControllerGetCapabilities ",le="0.1"} 1
344
- csi_sidecar_operations_seconds_bucket{driver_name="fake.csi.driver.io",grpc_status_code="Unimplemented",method_name="/csi.v1.Controller/ControllerGetCapabilities ",le="0.25"} 1
345
- csi_sidecar_operations_seconds_bucket{driver_name="fake.csi.driver.io",grpc_status_code="Unimplemented",method_name="/csi.v1.Controller/ControllerGetCapabilities ",le="0.5"} 1
346
- csi_sidecar_operations_seconds_bucket{driver_name="fake.csi.driver.io",grpc_status_code="Unimplemented",method_name="/csi.v1.Controller/ControllerGetCapabilities ",le="1"} 1
347
- csi_sidecar_operations_seconds_bucket{driver_name="fake.csi.driver.io",grpc_status_code="Unimplemented",method_name="/csi.v1.Controller/ControllerGetCapabilities ",le="2.5"} 1
348
- csi_sidecar_operations_seconds_bucket{driver_name="fake.csi.driver.io",grpc_status_code="Unimplemented",method_name="/csi.v1.Controller/ControllerGetCapabilities ",le="5"} 1
349
- csi_sidecar_operations_seconds_bucket{driver_name="fake.csi.driver.io",grpc_status_code="Unimplemented",method_name="/csi.v1.Controller/ControllerGetCapabilities ",le="10"} 1
350
- csi_sidecar_operations_seconds_bucket{driver_name="fake.csi.driver.io",grpc_status_code="Unimplemented",method_name="/csi.v1.Controller/ControllerGetCapabilities ",le="15"} 1
351
- csi_sidecar_operations_seconds_bucket{driver_name="fake.csi.driver.io",grpc_status_code="Unimplemented",method_name="/csi.v1.Controller/ControllerGetCapabilities ",le="25"} 1
352
- csi_sidecar_operations_seconds_bucket{driver_name="fake.csi.driver.io",grpc_status_code="Unimplemented",method_name="/csi.v1.Controller/ControllerGetCapabilities ",le="50"} 1
353
- csi_sidecar_operations_seconds_bucket{driver_name="fake.csi.driver.io",grpc_status_code="Unimplemented",method_name="/csi.v1.Controller/ControllerGetCapabilities ",le="120"} 1
354
- csi_sidecar_operations_seconds_bucket{driver_name="fake.csi.driver.io",grpc_status_code="Unimplemented",method_name="/csi.v1.Controller/ControllerGetCapabilities ",le="300"} 1
355
- csi_sidecar_operations_seconds_bucket{driver_name="fake.csi.driver.io",grpc_status_code="Unimplemented",method_name="/csi.v1.Controller/ControllerGetCapabilities ",le="600"} 1
356
- csi_sidecar_operations_seconds_bucket{driver_name="fake.csi.driver.io",grpc_status_code="Unimplemented",method_name="/csi.v1.Controller/ControllerGetCapabilities ",le="+Inf"} 1
357
- csi_sidecar_operations_seconds_sum{driver_name="fake.csi.driver.io",grpc_status_code="Unimplemented",method_name="/csi.v1.Controller/ControllerGetCapabilities "} 0
358
- csi_sidecar_operations_seconds_count{driver_name="fake.csi.driver.io",grpc_status_code="Unimplemented",method_name="/csi.v1.Controller/ControllerGetCapabilities "} 1
369
+ csi_sidecar_operations_seconds_bucket{driver_name="fake.csi.driver.io",grpc_status_code="Unimplemented",method_name="/csi.v1.Identity/GetPluginInfo ",le="0.1"} 1
370
+ csi_sidecar_operations_seconds_bucket{driver_name="fake.csi.driver.io",grpc_status_code="Unimplemented",method_name="/csi.v1.Identity/GetPluginInfo ",le="0.25"} 1
371
+ csi_sidecar_operations_seconds_bucket{driver_name="fake.csi.driver.io",grpc_status_code="Unimplemented",method_name="/csi.v1.Identity/GetPluginInfo ",le="0.5"} 1
372
+ csi_sidecar_operations_seconds_bucket{driver_name="fake.csi.driver.io",grpc_status_code="Unimplemented",method_name="/csi.v1.Identity/GetPluginInfo ",le="1"} 1
373
+ csi_sidecar_operations_seconds_bucket{driver_name="fake.csi.driver.io",grpc_status_code="Unimplemented",method_name="/csi.v1.Identity/GetPluginInfo ",le="2.5"} 1
374
+ csi_sidecar_operations_seconds_bucket{driver_name="fake.csi.driver.io",grpc_status_code="Unimplemented",method_name="/csi.v1.Identity/GetPluginInfo ",le="5"} 1
375
+ csi_sidecar_operations_seconds_bucket{driver_name="fake.csi.driver.io",grpc_status_code="Unimplemented",method_name="/csi.v1.Identity/GetPluginInfo ",le="10"} 1
376
+ csi_sidecar_operations_seconds_bucket{driver_name="fake.csi.driver.io",grpc_status_code="Unimplemented",method_name="/csi.v1.Identity/GetPluginInfo ",le="15"} 1
377
+ csi_sidecar_operations_seconds_bucket{driver_name="fake.csi.driver.io",grpc_status_code="Unimplemented",method_name="/csi.v1.Identity/GetPluginInfo ",le="25"} 1
378
+ csi_sidecar_operations_seconds_bucket{driver_name="fake.csi.driver.io",grpc_status_code="Unimplemented",method_name="/csi.v1.Identity/GetPluginInfo ",le="50"} 1
379
+ csi_sidecar_operations_seconds_bucket{driver_name="fake.csi.driver.io",grpc_status_code="Unimplemented",method_name="/csi.v1.Identity/GetPluginInfo ",le="120"} 1
380
+ csi_sidecar_operations_seconds_bucket{driver_name="fake.csi.driver.io",grpc_status_code="Unimplemented",method_name="/csi.v1.Identity/GetPluginInfo ",le="300"} 1
381
+ csi_sidecar_operations_seconds_bucket{driver_name="fake.csi.driver.io",grpc_status_code="Unimplemented",method_name="/csi.v1.Identity/GetPluginInfo ",le="600"} 1
382
+ csi_sidecar_operations_seconds_bucket{driver_name="fake.csi.driver.io",grpc_status_code="Unimplemented",method_name="/csi.v1.Identity/GetPluginInfo ",le="+Inf"} 1
383
+ csi_sidecar_operations_seconds_sum{driver_name="fake.csi.driver.io",grpc_status_code="Unimplemented",method_name="/csi.v1.Identity/GetPluginInfo "} 0
384
+ csi_sidecar_operations_seconds_count{driver_name="fake.csi.driver.io",grpc_status_code="Unimplemented",method_name="/csi.v1.Identity/GetPluginInfo "} 1
359
385
`
360
386
361
387
if err := testutil .GatherAndCompare (
362
388
cmm .GetRegistry (), strings .NewReader (expectedMetrics )); err != nil {
363
389
// Ignore mismatches on csi_sidecar_operations_seconds_sum metric because execution time will vary from test to test.
364
390
err = verifyMetricsError (t , err , "csi_sidecar_operations_seconds_sum" )
365
391
if err != nil {
366
- t .Errorf ("Expected metrics not found -- %v" , err )
392
+ t .Errorf ("Expected client metrics not found -- %v" , err )
393
+ }
394
+ }
395
+
396
+ expectedMetrics = strings .Replace (expectedMetrics , "csi_sidecar" , metrics .SubsystemPlugin , - 1 )
397
+ if err := testutil .GatherAndCompare (
398
+ cmmServer .GetRegistry (), strings .NewReader (expectedMetrics )); err != nil {
399
+ // Ignore mismatches on csi_sidecar_operations_seconds_sum metric because execution time will vary from test to test.
400
+ err = verifyMetricsError (t , err , metrics .SubsystemPlugin + "_operations_seconds_sum" )
401
+ if err != nil {
402
+ t .Errorf ("Expected server metrics not found -- %v" , err )
367
403
}
368
404
}
369
405
}
0 commit comments