Skip to content

Commit 3bc4135

Browse files
authored
Merge pull request #122 from jsafrane/configure-mock
Update mock driver for testing
2 parents 8d5ae90 + 2d2342f commit 3bc4135

File tree

6 files changed

+115
-50
lines changed

6 files changed

+115
-50
lines changed

driver/driver.go

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ package driver
2020

2121
import (
2222
"context"
23+
"encoding/json"
2324
"errors"
25+
"fmt"
2426
"net"
2527
"sync"
2628

@@ -102,7 +104,7 @@ func (c *CSIDriver) Start(l net.Listener) error {
102104

103105
// Create a new grpc server
104106
c.server = grpc.NewServer(
105-
grpc.UnaryInterceptor(c.authInterceptor),
107+
grpc.UnaryInterceptor(c.callInterceptor),
106108
)
107109

108110
// Register Mock servers
@@ -162,22 +164,49 @@ func (c *CSIDriver) SetDefaultCreds() {
162164
}
163165
}
164166

165-
func (c *CSIDriver) authInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
167+
func (c *CSIDriver) callInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
168+
err := c.authInterceptor(req)
169+
if err != nil {
170+
logGRPC(info.FullMethod, req, nil, err)
171+
return nil, err
172+
}
173+
rsp, err := handler(ctx, req)
174+
logGRPC(info.FullMethod, req, rsp, err)
175+
return rsp, err
176+
}
177+
178+
func (c *CSIDriver) authInterceptor(req interface{}) error {
166179
if c.creds != nil {
167180
authenticated, authErr := isAuthenticated(req, c.creds)
168181
if !authenticated {
169182
if authErr == ErrNoCredentials {
170-
return nil, status.Error(codes.InvalidArgument, authErr.Error())
183+
return status.Error(codes.InvalidArgument, authErr.Error())
171184
}
172185
if authErr == ErrAuthFailed {
173-
return nil, status.Error(codes.Unauthenticated, authErr.Error())
186+
return status.Error(codes.Unauthenticated, authErr.Error())
174187
}
175188
}
176189
}
190+
return nil
191+
}
177192

178-
h, err := handler(ctx, req)
179-
180-
return h, err
193+
func logGRPC(method string, request, reply interface{}, err error) {
194+
// Log JSON with the request and response for easier parsing
195+
logMessage := struct {
196+
Method string
197+
Request interface{}
198+
Response interface{}
199+
Error string
200+
}{
201+
Method: method,
202+
Request: request,
203+
Response: reply,
204+
}
205+
if err != nil {
206+
logMessage.Error = err.Error()
207+
}
208+
msg, _ := json.Marshal(logMessage)
209+
fmt.Printf("gRPCCall: %s\n", msg)
181210
}
182211

183212
func isAuthenticated(req interface{}, creds *CSICreds) (bool, error) {

mock/main.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ limitations under the License.
1616
package main
1717

1818
import (
19+
"flag"
1920
"fmt"
2021
"net"
2122
"os"
@@ -28,6 +29,11 @@ import (
2829
)
2930

3031
func main() {
32+
var config service.Config
33+
flag.BoolVar(&config.DisableAttach, "disable-attach", false, "Disables RPC_PUBLISH_UNPUBLISH_VOLUME capability.")
34+
flag.StringVar(&config.DriverName, "name", service.Name, "CSI driver name.")
35+
flag.Parse()
36+
3137
endpoint := os.Getenv("CSI_ENDPOINT")
3238
if len(endpoint) == 0 {
3339
fmt.Println("CSI_ENDPOINT must be defined and must be a path")
@@ -39,7 +45,7 @@ func main() {
3945
}
4046

4147
// Create mock driver
42-
s := service.New()
48+
s := service.New(config)
4349
servers := &driver.CSIDriverServers{
4450
Controller: s,
4551
Identity: s,

mock/service/controller.go

Lines changed: 46 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,10 @@ func (s *service) ControllerPublishVolume(
108108
req *csi.ControllerPublishVolumeRequest) (
109109
*csi.ControllerPublishVolumeResponse, error) {
110110

111+
if s.config.DisableAttach {
112+
return nil, status.Error(codes.Unimplemented, "ControllerPublish is not supported")
113+
}
114+
111115
if len(req.VolumeId) == 0 {
112116
return nil, status.Error(codes.InvalidArgument, "Volume ID cannot be empty")
113117
}
@@ -188,6 +192,10 @@ func (s *service) ControllerUnpublishVolume(
188192
req *csi.ControllerUnpublishVolumeRequest) (
189193
*csi.ControllerUnpublishVolumeResponse, error) {
190194

195+
if s.config.DisableAttach {
196+
return nil, status.Error(codes.Unimplemented, "ControllerPublish is not supported")
197+
}
198+
191199
if len(req.VolumeId) == 0 {
192200
return nil, status.Error(codes.InvalidArgument, "Volume ID cannot be empty")
193201
}
@@ -338,51 +346,56 @@ func (s *service) ControllerGetCapabilities(
338346
req *csi.ControllerGetCapabilitiesRequest) (
339347
*csi.ControllerGetCapabilitiesResponse, error) {
340348

341-
return &csi.ControllerGetCapabilitiesResponse{
342-
Capabilities: []*csi.ControllerServiceCapability{
343-
{
344-
Type: &csi.ControllerServiceCapability_Rpc{
345-
Rpc: &csi.ControllerServiceCapability_RPC{
346-
Type: csi.ControllerServiceCapability_RPC_CREATE_DELETE_VOLUME,
347-
},
349+
caps := []*csi.ControllerServiceCapability{
350+
{
351+
Type: &csi.ControllerServiceCapability_Rpc{
352+
Rpc: &csi.ControllerServiceCapability_RPC{
353+
Type: csi.ControllerServiceCapability_RPC_CREATE_DELETE_VOLUME,
348354
},
349355
},
350-
{
351-
Type: &csi.ControllerServiceCapability_Rpc{
352-
Rpc: &csi.ControllerServiceCapability_RPC{
353-
Type: csi.ControllerServiceCapability_RPC_PUBLISH_UNPUBLISH_VOLUME,
354-
},
356+
},
357+
{
358+
Type: &csi.ControllerServiceCapability_Rpc{
359+
Rpc: &csi.ControllerServiceCapability_RPC{
360+
Type: csi.ControllerServiceCapability_RPC_LIST_VOLUMES,
355361
},
356362
},
357-
{
358-
Type: &csi.ControllerServiceCapability_Rpc{
359-
Rpc: &csi.ControllerServiceCapability_RPC{
360-
Type: csi.ControllerServiceCapability_RPC_LIST_VOLUMES,
361-
},
363+
},
364+
{
365+
Type: &csi.ControllerServiceCapability_Rpc{
366+
Rpc: &csi.ControllerServiceCapability_RPC{
367+
Type: csi.ControllerServiceCapability_RPC_GET_CAPACITY,
362368
},
363369
},
364-
{
365-
Type: &csi.ControllerServiceCapability_Rpc{
366-
Rpc: &csi.ControllerServiceCapability_RPC{
367-
Type: csi.ControllerServiceCapability_RPC_GET_CAPACITY,
368-
},
370+
},
371+
{
372+
Type: &csi.ControllerServiceCapability_Rpc{
373+
Rpc: &csi.ControllerServiceCapability_RPC{
374+
Type: csi.ControllerServiceCapability_RPC_LIST_SNAPSHOTS,
369375
},
370376
},
371-
{
372-
Type: &csi.ControllerServiceCapability_Rpc{
373-
Rpc: &csi.ControllerServiceCapability_RPC{
374-
Type: csi.ControllerServiceCapability_RPC_LIST_SNAPSHOTS,
375-
},
377+
},
378+
{
379+
Type: &csi.ControllerServiceCapability_Rpc{
380+
Rpc: &csi.ControllerServiceCapability_RPC{
381+
Type: csi.ControllerServiceCapability_RPC_CREATE_DELETE_SNAPSHOT,
376382
},
377383
},
378-
{
379-
Type: &csi.ControllerServiceCapability_Rpc{
380-
Rpc: &csi.ControllerServiceCapability_RPC{
381-
Type: csi.ControllerServiceCapability_RPC_CREATE_DELETE_SNAPSHOT,
382-
},
384+
},
385+
}
386+
387+
if !s.config.DisableAttach {
388+
caps = append(caps, &csi.ControllerServiceCapability{
389+
Type: &csi.ControllerServiceCapability_Rpc{
390+
Rpc: &csi.ControllerServiceCapability_RPC{
391+
Type: csi.ControllerServiceCapability_RPC_PUBLISH_UNPUBLISH_VOLUME,
383392
},
384393
},
385-
},
394+
})
395+
}
396+
397+
return &csi.ControllerGetCapabilitiesResponse{
398+
Capabilities: caps,
386399
}, nil
387400
}
388401

mock/service/identity.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ func (s *service) GetPluginInfo(
1313
*csi.GetPluginInfoResponse, error) {
1414

1515
return &csi.GetPluginInfoResponse{
16-
Name: Name,
16+
Name: s.config.DriverName,
1717
VendorVersion: VendorVersion,
1818
Manifest: Manifest,
1919
}, nil

mock/service/node.go

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,13 @@ func (s *service) NodeStageVolume(
1818

1919
device, ok := req.PublishInfo["device"]
2020
if !ok {
21-
return nil, status.Error(
22-
codes.InvalidArgument,
23-
"stage volume info 'device' key required")
21+
if s.config.DisableAttach {
22+
device = "mock device"
23+
} else {
24+
return nil, status.Error(
25+
codes.InvalidArgument,
26+
"stage volume info 'device' key required")
27+
}
2428
}
2529

2630
if len(req.GetVolumeId()) == 0 {
@@ -105,9 +109,13 @@ func (s *service) NodePublishVolume(
105109

106110
device, ok := req.PublishInfo["device"]
107111
if !ok {
108-
return nil, status.Error(
109-
codes.InvalidArgument,
110-
"publish volume info 'device' key required")
112+
if s.config.DisableAttach {
113+
device = "mock device"
114+
} else {
115+
return nil, status.Error(
116+
codes.InvalidArgument,
117+
"stage volume info 'device' key required")
118+
}
111119
}
112120

113121
if len(req.GetVolumeId()) == 0 {

mock/service/service.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ var Manifest = map[string]string{
2525
"url": "https://github.com/kubernetes-csi/csi-test/mock",
2626
}
2727

28+
type Config struct {
29+
DisableAttach bool
30+
DriverName string
31+
}
32+
2833
// Service is the CSI Mock service provider.
2934
type Service interface {
3035
csi.ControllerServer
@@ -40,6 +45,7 @@ type service struct {
4045
volsNID uint64
4146
snapshots cache.SnapshotCache
4247
snapshotsNID uint64
48+
config Config
4349
}
4450

4551
type Volume struct {
@@ -55,8 +61,11 @@ type Volume struct {
5561
var MockVolumes map[string]Volume
5662

5763
// New returns a new Service.
58-
func New() Service {
59-
s := &service{nodeID: Name}
64+
func New(config Config) Service {
65+
s := &service{
66+
nodeID: config.DriverName,
67+
config: config,
68+
}
6069
s.snapshots = cache.NewSnapshotCache()
6170
s.vols = []csi.Volume{
6271
s.newVolume("Mock Volume 1", gib100),

0 commit comments

Comments
 (0)