From d19316f96612804bde30dc544c1987eba0365237 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Pab=C3=B3n?= Date: Sat, 3 Mar 2018 18:48:37 -0500 Subject: [PATCH 1/2] Minimize mock driver code This includes the following changes: * `driver/driver.go` has been changed to be a generic CSI server * `driver/mock.go` used by clients has been changed to use `driver/driver.go` * `mock/main.go` has been changed to use `driver/driver.go` server * `mock/...` has been cleaned up to just what is needed --- Gopkg.lock | 2 +- driver/driver.go | 107 +++--- driver/mock.go | 85 +++++ hack/e2e.sh | 10 +- mock/.gitignore | 1 - mock/AUTHORS | 1 + mock/Makefile | 17 - mock/README.md | 48 +-- mock/context/context.go | 128 ------- mock/gocsi/envvars.go | 325 ------------------ mock/gocsi/gocsi.go | 545 ------------------------------ mock/gocsi/usage.go | 269 --------------- mock/main.go | 67 +++- mock/plugin.go | 23 -- mock/provider/provider.go | 53 --- mock/utils/utils.go | 586 --------------------------------- mock/utils/utils_middleware.go | 143 -------- mock/utils/utils_rpcs.go | 89 ----- mock/utils/utils_suite_test.go | 118 ------- mock/utils/utils_test.go | 415 ----------------------- 20 files changed, 189 insertions(+), 2843 deletions(-) create mode 100644 driver/mock.go delete mode 100644 mock/.gitignore delete mode 100644 mock/Makefile delete mode 100644 mock/context/context.go delete mode 100644 mock/gocsi/envvars.go delete mode 100644 mock/gocsi/gocsi.go delete mode 100644 mock/gocsi/usage.go delete mode 100644 mock/plugin.go delete mode 100644 mock/provider/provider.go delete mode 100644 mock/utils/utils.go delete mode 100644 mock/utils/utils_middleware.go delete mode 100644 mock/utils/utils_rpcs.go delete mode 100644 mock/utils/utils_suite_test.go delete mode 100644 mock/utils/utils_test.go diff --git a/Gopkg.lock b/Gopkg.lock index 8517fe6f..f9fb3006 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -188,6 +188,6 @@ [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "b3d02999b00cc5a342dc8b65dd941fbd0f9af728d5d42c433d82c6fcb93bb0cd" + inputs-digest = "d953393850efa90c442b607a076291db1b050e1c9523ce86fefc85fda0443b8f" solver-name = "gps-cdcl" solver-version = 1 diff --git a/driver/driver.go b/driver/driver.go index 3ed7a832..9bf13413 100644 --- a/driver/driver.go +++ b/driver/driver.go @@ -23,118 +23,95 @@ import ( "sync" csi "github.com/container-storage-interface/spec/lib/go/csi/v0" - "github.com/kubernetes-csi/csi-test/utils" "google.golang.org/grpc" "google.golang.org/grpc/reflection" ) -type MockCSIDriverServers struct { - Controller *MockControllerServer - Identity *MockIdentityServer - Node *MockNodeServer +type CSIDriverServers struct { + Controller csi.ControllerServer + Identity csi.IdentityServer + Node csi.NodeServer } -type MockCSIDriver struct { +type CSIDriver struct { listener net.Listener server *grpc.Server - conn *grpc.ClientConn - servers *MockCSIDriverServers + servers *CSIDriverServers wg sync.WaitGroup running bool lock sync.Mutex } -func NewMockCSIDriver(servers *MockCSIDriverServers) *MockCSIDriver { - return &MockCSIDriver{ +func NewCSIDriver(servers *CSIDriverServers) *CSIDriver { + return &CSIDriver{ servers: servers, } } -func (m *MockCSIDriver) goServe(started chan<- bool) { - m.wg.Add(1) +func (c *CSIDriver) goServe(started chan<- bool) { + c.wg.Add(1) go func() { - defer m.wg.Done() + defer c.wg.Done() started <- true - err := m.server.Serve(m.listener) + err := c.server.Serve(c.listener) if err != nil { panic(err.Error()) } }() } -func (m *MockCSIDriver) Address() string { - return m.listener.Addr().String() +func (c *CSIDriver) Address() string { + return c.listener.Addr().String() } -func (m *MockCSIDriver) Start() error { - m.lock.Lock() - defer m.lock.Unlock() - - // Listen on a port assigned by the net package - l, err := net.Listen("tcp", "127.0.0.1:0") - if err != nil { - return err - } - m.listener = l +func (c *CSIDriver) Start(l net.Listener) error { + c.lock.Lock() + defer c.lock.Unlock() + + // Set listener + c.listener = l // Create a new grpc server - m.server = grpc.NewServer() + c.server = grpc.NewServer() // Register Mock servers - if m.servers.Controller != nil { - csi.RegisterControllerServer(m.server, m.servers.Controller) + if c.servers.Controller != nil { + csi.RegisterControllerServer(c.server, c.servers.Controller) } - if m.servers.Identity != nil { - csi.RegisterIdentityServer(m.server, m.servers.Identity) + if c.servers.Identity != nil { + csi.RegisterIdentityServer(c.server, c.servers.Identity) } - if m.servers.Node != nil { - csi.RegisterNodeServer(m.server, m.servers.Node) + if c.servers.Node != nil { + csi.RegisterNodeServer(c.server, c.servers.Node) } - reflection.Register(m.server) + reflection.Register(c.server) // Start listening for requests waitForServer := make(chan bool) - m.goServe(waitForServer) + c.goServe(waitForServer) <-waitForServer - m.running = true + c.running = true return nil } -func (m *MockCSIDriver) Nexus() (*grpc.ClientConn, error) { - // Start server - err := m.Start() - if err != nil { - return nil, err - } - - // Create a client connection - m.conn, err = utils.Connect(m.Address()) - if err != nil { - return nil, err - } - - return m.conn, nil -} - -func (m *MockCSIDriver) Stop() { - m.lock.Lock() - defer m.lock.Unlock() +func (c *CSIDriver) Stop() { + c.lock.Lock() + defer c.lock.Unlock() - if !m.running { + if !c.running { return } - m.server.Stop() - m.wg.Wait() + c.server.Stop() + c.wg.Wait() } -func (m *MockCSIDriver) Close() { - m.conn.Close() - m.server.Stop() +func (c *CSIDriver) Close() { + c.server.Stop() } -func (m *MockCSIDriver) IsRunning() bool { - m.lock.Lock() - defer m.lock.Unlock() +func (c *CSIDriver) IsRunning() bool { + c.lock.Lock() + defer c.lock.Unlock() - return m.running + return c.running } diff --git a/driver/mock.go b/driver/mock.go new file mode 100644 index 00000000..f9ad45d5 --- /dev/null +++ b/driver/mock.go @@ -0,0 +1,85 @@ +/* +Copyright 2017 Luis Pabón luis@portworx.com + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +//go:generate mockgen -package=driver -destination=driver.mock.go github.com/container-storage-interface/spec/lib/go/csi IdentityServer,ControllerServer,NodeServer + +package driver + +import ( + "net" + + "github.com/kubernetes-csi/csi-test/utils" + "google.golang.org/grpc" +) + +type MockCSIDriverServers struct { + Controller *MockControllerServer + Identity *MockIdentityServer + Node *MockNodeServer +} + +type MockCSIDriver struct { + CSIDriver + conn *grpc.ClientConn +} + +func NewMockCSIDriver(servers *MockCSIDriverServers) *MockCSIDriver { + return &MockCSIDriver{ + CSIDriver: CSIDriver{ + servers: &CSIDriverServers{ + Controller: servers.Controller, + Node: servers.Node, + Identity: servers.Identity, + }, + }, + } +} + +func (m *MockCSIDriver) Start() error { + // Listen on a port assigned by the net package + l, err := net.Listen("tcp", "127.0.0.1:0") + if err != nil { + return err + } + + if err := m.CSIDriver.Start(l); err != nil { + l.Close() + return err + } + + return nil +} + +func (m *MockCSIDriver) Nexus() (*grpc.ClientConn, error) { + // Start server + err := m.Start() + if err != nil { + return nil, err + } + + // Create a client connection + m.conn, err = utils.Connect(m.Address()) + if err != nil { + return nil, err + } + + return m.conn, nil +} + +func (m *MockCSIDriver) Close() { + m.conn.Close() + m.server.Stop() +} diff --git a/hack/e2e.sh b/hack/e2e.sh index 43fcba84..abf2e2f5 100755 --- a/hack/e2e.sh +++ b/hack/e2e.sh @@ -2,8 +2,6 @@ TESTARGS=$@ UDS="/tmp/e2e-csi-sanity.sock" -CSI_ENDPOINTS="127.0.0.1:9998" -CSI_ENDPOINTS="$CSI_ENDPOINTS unix://${UDS}" CSI_ENDPOINTS="$CSI_ENDPOINTS ${UDS}" CSI_MOCK_VERSION="master" @@ -24,18 +22,12 @@ runTest() fi } -cd mock - make clean mock || exit 1 -cd .. +go install ./mock || exit 1 cd cmd/csi-sanity make clean install || exit 1 cd ../.. -runTest "tcp://127.0.0.1:9998" "127.0.0.1:9998" -rm -f $UDS -runTest "unix://${UDS}" "unix://${UDS}" -rm -f $UDS runTest "${UDS}" "${UDS}" rm -f $UDS diff --git a/mock/.gitignore b/mock/.gitignore deleted file mode 100644 index ce020eb6..00000000 --- a/mock/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/mock diff --git a/mock/AUTHORS b/mock/AUTHORS index 3a611857..23eabcd2 100644 --- a/mock/AUTHORS +++ b/mock/AUTHORS @@ -1 +1,2 @@ TheCodeTeam +Kubernetes Authors diff --git a/mock/Makefile b/mock/Makefile deleted file mode 100644 index 1555ead7..00000000 --- a/mock/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -all: build - -PROG := mock - -$(PROG): *.go ./provider/*.go ./service/*.go - @go install . - go build -o "$@" . - -build: $(PROG) - -clean: - go clean -i -v . - rm -f $(PROG) - -clobber: clean - -.PHONY: clean clobber diff --git a/mock/README.md b/mock/README.md index 4236b8b5..d35e2d26 100644 --- a/mock/README.md +++ b/mock/README.md @@ -1,46 +1,2 @@ -# Mock Plug-in -The mock plug-in is a stand-alone binary that implements the CSI -Controller, Identity, and Node RPCs in addition to the specification's -requirements regarding idempotency. - -The mock plug-in always starts with a deterministic state and maintains -state for the duration of the process. The state can also be modified. -For example, while the plug-in launches with three volumes, a -`CreateVolume` RPC will update the plug-in's internal data map so that a -subsequent `ListVolumes` RPC will indicate four volumes are present. - -Per the specification the Mock plug-in starts a gRPC server using the -value of the environment variable `CSI_ENDPOINT`. The plug-in process -runs in the foreground, logging activity to `STDOUT` and errors to -`STDERR`, only returning control to the user when `CTRL-C` is entered -or the process is sent a `kill` signal. - -```bash -$ CSI_ENDPOINT=/tmp/csi.sock mock/mock -INFO 2017/08/22 16:22:15 main.go:154: mock.Serve: /tmp/csi.sock -INFO 2017/08/22 16:22:18 main.go:133: /csi.Controller/CreateVolume: REQ 0001: Version=minor:1 , Name=Test Volume, CapacityRange=required_bytes:10740000000 limit_bytes:107400000000 , VolumeCapabilities=[mount: ], Parameters=map[tag:gold] -INFO 2017/08/22 16:22:18 main.go:133: /csi.Controller/CreateVolume: REP 0001: Reply=&{volume_info: values: > metadata:<> > } -INFO 2017/08/22 16:23:53 main.go:94: received signal: interrupt: shutting down -INFO 2017/08/22 16:23:53 main.go:188: mock.GracefulStop -INFO 2017/08/22 16:23:53 main.go:53: removed sock file: /tmp/csi.sock -INFO 2017/08/22 16:23:53 main.go:64: server stopped gracefully -``` - -## Configuration -The Mock CSI plug-in is created using the GoCSI CSP package. Please -see its [configuration section](../csp/README.md#configuration) for -a complete list of the environment variables that may be used to -configure the Mock SP. - -The following table is a list of the Mock SP's default configuration -values: - -| Name | Value | -|------|---------| -| `X_CSI_IDEMP` | `true` | -| `X_CSI_IDEMP_REQUIRE_VOL` | `true` | -| `X_CSI_REQUIRE_NODE_ID` | `true` | -| `X_CSI_REQUIRE_PUB_VOL_INFO` | `true` | -| `X_CSI_CREATE_VOL_ALREADY_EXISTS` | `true` | -| `X_CSI_DELETE_VOL_NOT_FOUND` | `true` | -| `X_CSI_SUPPORTED_VERSIONS` | `0.2.0 1.0.0 1.1.0` | +# Mock CSI Driver +Extremely simple mock driver used to test `csi-sanity` based on `rexray/gocsi/mock` diff --git a/mock/context/context.go b/mock/context/context.go deleted file mode 100644 index 694ed65e..00000000 --- a/mock/context/context.go +++ /dev/null @@ -1,128 +0,0 @@ -package context - -import ( - "context" - "os" - "strconv" - "strings" - - "google.golang.org/grpc/metadata" -) - -// RequestIDKey is the key used to put/get a CSI request ID -// in/fromt a Go context. -const RequestIDKey = "csi.requestid" - -var ( - // ctxRequestIDKey is an interface-wrapped key used to access the - // gRPC request ID injected into an outgoing or incoming context - // via the GoCSI request ID injection interceptor - ctxRequestIDKey = interface{}("x-csi-request-id") - - // ctxOSEnviron is an interface-wrapped key used to access a string - // slice that contains one or more environment variables stored as - // KEY=VALUE. - ctxOSEnviron = interface{}("os.Environ") - - // ctxOSLookupEnvKey is an interface-wrapped key used to access a function - // with the signature func(string) (string, bool) that returns the value of - // an environment variable. - ctxOSLookupEnvKey = interface{}("os.LookupEnv") - - // ctxOSSetenvKey is an interface-wrapped key used to access a function - // with the signature func(string, string) that can be used to set the - // value of an environment variable - ctxOSSetenvKey = interface{}("os.Setenev") -) - -type lookupEnvFunc func(string) (string, bool) -type setenvFunc func(string, string) error - -// GetRequestID inspects the context for gRPC metadata and returns -// its request ID if available. -func GetRequestID(ctx context.Context) (uint64, bool) { - var ( - szID []string - szIDOK bool - ) - - // Prefer the incoming context, but look in both types. - if md, ok := metadata.FromIncomingContext(ctx); ok { - szID, szIDOK = md[RequestIDKey] - } else if md, ok := metadata.FromOutgoingContext(ctx); ok { - szID, szIDOK = md[RequestIDKey] - } - - if szIDOK && len(szID) == 1 { - if id, err := strconv.ParseUint(szID[0], 10, 64); err == nil { - return id, true - } - } - - return 0, false -} - -// WithEnviron returns a new Context with the provided environment variable -// string slice. -func WithEnviron(ctx context.Context, v []string) context.Context { - return context.WithValue(ctx, ctxOSEnviron, v) -} - -// WithLookupEnv returns a new Context with the provided function. -func WithLookupEnv(ctx context.Context, f lookupEnvFunc) context.Context { - return context.WithValue(ctx, ctxOSLookupEnvKey, f) -} - -// WithSetenv returns a new Context with the provided function. -func WithSetenv(ctx context.Context, f setenvFunc) context.Context { - return context.WithValue(ctx, ctxOSSetenvKey, f) -} - -// LookupEnv returns the value of the provided environment variable by: -// -// 1. Inspecting the context for a key "os.Environ" with a string -// slice value. If such a key and value exist then the string slice -// is searched for the specified key and if found its value is returned. -// -// 2. Inspecting the context for a key "os.LookupEnv" with a value of -// func(string) (string, bool). If such a key and value exist then the -// function is used to attempt to discover the key's value. If the -// key and value are found they are returned. -// -// 3. Returning the result of os.LookupEnv. -func LookupEnv(ctx context.Context, key string) (string, bool) { - if s, ok := ctx.Value(ctxOSEnviron).([]string); ok { - for _, v := range s { - p := strings.SplitN(v, "=", 2) - if len(p) > 0 && strings.EqualFold(p[0], key) { - if len(p) > 1 { - return p[1], true - } - return "", true - } - } - } - if f, ok := ctx.Value(ctxOSLookupEnvKey).(lookupEnvFunc); ok { - if v, ok := f(key); ok { - return v, true - } - } - return os.LookupEnv(key) -} - -// Getenv is an alias for LookupEnv and drops the boolean return value. -func Getenv(ctx context.Context, key string) string { - val, _ := LookupEnv(ctx, key) - return val -} - -// Setenv sets the value of the provided environment variable to the -// specified value by first inspecting the context for a key "os.Setenv" -// with a value of func(string, string) error. If the context does not -// contain such a function then os.Setenv is used instead. -func Setenv(ctx context.Context, key, val string) error { - if f, ok := ctx.Value(ctxOSSetenvKey).(setenvFunc); ok { - return f(key, val) - } - return os.Setenv(key, val) -} diff --git a/mock/gocsi/envvars.go b/mock/gocsi/envvars.go deleted file mode 100644 index 28f3c376..00000000 --- a/mock/gocsi/envvars.go +++ /dev/null @@ -1,325 +0,0 @@ -package gocsi - -import ( - "context" - "strconv" - "strings" - - log "github.com/sirupsen/logrus" - - csictx "github.com/kubernetes-csi/csi-test/mock/context" - "github.com/kubernetes-csi/csi-test/mock/utils" -) - -const ( - // EnvVarEndpoint is the name of the environment variable used to - // specify the CSI endpoint. - EnvVarEndpoint = "CSI_ENDPOINT" - - // EnvVarEndpointPerms is the name of the environment variable used - // to specify the file permissions for the CSI endpoint when it is - // a UNIX socket file. This setting has no effect if CSI_ENDPOINT - // specifies a TCP socket. The default value is 0755. - EnvVarEndpointPerms = "X_CSI_ENDPOINT_PERMS" - - // EnvVarEndpointUser is the name of the environment variable used - // to specify the UID or name of the user that owns the endpoint's - // UNIX socket file. This setting has no effect if CSI_ENDPOINT - // specifies a TCP socket. The default value is the user that starts - // the process. - EnvVarEndpointUser = "X_CSI_ENDPOINT_USER" - - // EnvVarEndpointGroup is the name of the environment variable used - // to specify the GID or name of the group that owns the endpoint's - // UNIX socket file. This setting has no effect if CSI_ENDPOINT - // specifies a TCP socket. The default value is the group that starts - // the process. - EnvVarEndpointGroup = "X_CSI_ENDPOINT_GROUP" - - // EnvVarDebug is the name of the environment variable used to - // determine whether or not debug mode is enabled. - // - // Setting this environment variable to a truthy value is the - // equivalent of X_CSI_LOG_LEVEL=DEBUG, X_CSI_REQ_LOGGING=true, - // and X_CSI_REP_LOGGING=true. - EnvVarDebug = "X_CSI_DEBUG" - - // EnvVarLogLevel is the name of the environment variable used to - // specify the log level. Valid values include PANIC, FATAL, ERROR, - // WARN, INFO, and DEBUG. - EnvVarLogLevel = "X_CSI_LOG_LEVEL" - - // EnvVarSupportedVersions is the name of the environment variable used - // to specify a list of comma-separated versions supported by the SP. If - // no value is specified then the SP does not perform a version check on - // the RPC. - EnvVarSupportedVersions = "X_CSI_SUPPORTED_VERSIONS" - - // EnvVarPluginInfo is the name of the environment variable used to - // specify the plug-in info in the format: - // - // NAME, VENDOR_VERSION[, MANIFEST...] - // - // The MANIFEST value may be a series of additional comma-separated - // key/value pairs. - // - // Please see the encoding/csv package (https://goo.gl/1j1xb9) for - // information on how to quote keys and/or values to include leading - // and trailing whitespace. - // - // Setting this environment variable will cause the program to - // bypass the SP's GetPluginInfo RPC and returns the specified - // information instead. - EnvVarPluginInfo = "X_CSI_PLUGIN_INFO" - - // EnvVarMode is the name of the environment variable used to specify - // the service mode of the storage plug-in. Valie values are: - // - // * - // * controller - // * node - // - // If unset or set to an empty value the storage plug-in activates - // both controller and node services. The identity service is always - // activated. - EnvVarMode = "X_CSI_MODE" - - // EnvVarReqLogging is the name of the environment variable - // used to determine whether or not to enable request logging. - // - // Setting this environment variable to a truthy value enables - // request logging to STDOUT. - EnvVarReqLogging = "X_CSI_REQ_LOGGING" - - // EnvVarRepLogging is the name of the environment variable - // used to determine whether or not to enable response logging. - // - // Setting this environment variable to a truthy value enables - // response logging to STDOUT. - EnvVarRepLogging = "X_CSI_REP_LOGGING" - - // EnvVarReqIDInjection is the name of the environment variable - // used to determine whether or not to enable request ID injection. - EnvVarReqIDInjection = "X_CSI_REQ_ID_INJECTION" - - // EnvVarSpecValidation is the name of the environment variable - // used to determine whether or not to enable validation of CSI - // request and response messages. Setting X_CSI_SPEC_VALIDATION=true - // is the equivalent to setting X_CSI_SPEC_REQ_VALIDATION=true and - // X_CSI_SPEC_REP_VALIDATION=true. - EnvVarSpecValidation = "X_CSI_SPEC_VALIDATION" - - // EnvVarSpecReqValidation is the name of the environment variable - // used to determine whether or not to enable validation of CSI request - // messages. - EnvVarSpecReqValidation = "X_CSI_SPEC_REQ_VALIDATION" - - // EnvVarSpecRepValidation is the name of the environment variable - // used to determine whether or not to enable validation of CSI response - // messages. Invalid responses are marshalled into a gRPC error with - // a code of "Internal." - EnvVarSpecRepValidation = "X_CSI_SPEC_REP_VALIDATION" - - // EnvVarRequireNodeID is the name of the environment variable used - // to determine whether or not the node ID value is required for - // requests that accept it and responses that return it such as - // ControllerPublishVolume and GetNodeId. - EnvVarRequireNodeID = "X_CSI_REQUIRE_NODE_ID" - - // EnvVarRequirePubVolInfo is the name of the environment variable used - // to determine whether or not publish volume info is required for - // requests that accept it and responses that return it such as - // NodePublishVolume and ControllerPublishVolume. - EnvVarRequirePubVolInfo = "X_CSI_REQUIRE_PUB_VOL_INFO" - - // EnvVarRequireVolAttribs is the name of the environment variable used - // to determine whether or not volume attributes are required for - // requests that accept them and responses that return them such as - // ControllerPublishVolume and CreateVolume. - EnvVarRequireVolAttribs = "X_CSI_REQUIRE_VOL_ATTRIBS" - - // EnvVarCreds is the name of the environment variable - // used to determine whether or not user credentials are required for - // all RPCs. This value may be overridden for specific RPCs. - EnvVarCreds = "X_CSI_REQUIRE_CREDS" - - // EnvVarCredsCreateVol is the name of the environment variable - // used to determine whether or not user credentials are required for - // the eponymous RPC. - EnvVarCredsCreateVol = "X_CSI_REQUIRE_CREDS_CREATE_VOL" - - // EnvVarCredsDeleteVol is the name of the environment variable - // used to determine whether or not user credentials are required for - // the eponymous RPC. - EnvVarCredsDeleteVol = "X_CSI_REQUIRE_CREDS_DELETE_VOL" - - // EnvVarCredsCtrlrPubVol is the name of the environment - // variable used to determine whether or not user credentials are required - // for the eponymous RPC. - EnvVarCredsCtrlrPubVol = "X_CSI_REQUIRE_CREDS_CTRLR_PUB_VOL" - - // EnvVarCredsCtrlrUnpubVol is the name of the - // environment variable used to determine whether or not user credentials - // are required for the eponymous RPC. - EnvVarCredsCtrlrUnpubVol = "X_CSI_REQUIRE_CREDS_CTRLR_UNPUB_VOL" - - // EnvVarCredsNodePubVol is the name of the environment - // variable used to determine whether or not user credentials are required - // for the eponymous RPC. - EnvVarCredsNodePubVol = "X_CSI_REQUIRE_CREDS_NODE_PUB_VOL" - - // EnvVarCredsNodeUnpubVol is the name of the environment - // variable used to determine whether or not user credentials are required - // for the eponymous RPC. - EnvVarCredsNodeUnpubVol = "X_CSI_REQUIRE_CREDS_NODE_UNPUB_VOL" - - // EnvVarSerialVolAccess is the name of the environment variable - // used to determine whether or not to enable serial volume access. - EnvVarSerialVolAccess = "X_CSI_SERIAL_VOL_ACCESS" - - // EnvVarSerialVolAccessTimeout is the name of the environment variable - // used to specify the timeout for obtaining a volume lock. - EnvVarSerialVolAccessTimeout = "X_CSI_SERIAL_VOL_ACCESS_TIMEOUT" - - // EnvVarSerialVolAccessEtcdDomain is the name of the environment - // variable that defines the lock provider's concurrency domain. - EnvVarSerialVolAccessEtcdDomain = "X_CSI_SERIAL_VOL_ACCESS_ETCD_DOMAIN" - - // EnvVarSerialVolAccessEtcdTTL is the name of the environment - // variable that defines the length of time etcd will wait before - // releasing ownership of a distributed lock if the lock's session - // has not been renewed. - EnvVarSerialVolAccessEtcdTTL = "X_CSI_SERIAL_VOL_ACCESS_ETCD_TTL" - - // EnvVarSerialVolAccessEtcdEndpoints is the name of the environment - // variable that defines the lock provider's etcd endoints. - EnvVarSerialVolAccessEtcdEndpoints = "X_CSI_SERIAL_VOL_ACCESS_ETCD_ENDPOINTS" - - // EnvVarSerialVolAccessEtcdAutoSyncInterval is the name of the environment - // variable that defines the interval to update endpoints with its latest - // members. 0 disables auto-sync. By default auto-sync is disabled. - EnvVarSerialVolAccessEtcdAutoSyncInterval = "X_CSI_SERIAL_VOL_ACCESS_ETCD_AUTO_SYNC_INTERVAL" - - // EnvVarSerialVolAccessEtcdDialTimeout is the name of the environment - // variable that defines the timeout for failing to establish a connection. - EnvVarSerialVolAccessEtcdDialTimeout = "X_CSI_SERIAL_VOL_ACCESS_ETCD_DIAL_TIMEOUT" - - // EnvVarSerialVolAccessEtcdDialKeepAliveTime is the name of the environment - // variable that defines the time after which client pings the server to see - // if transport is alive. - EnvVarSerialVolAccessEtcdDialKeepAliveTime = "X_CSI_SERIAL_VOL_ACCESS_ETCD_DIAL_KEEP_ALIVE_TIME" - - // EnvVarSerialVolAccessEtcdDialKeepAliveTimeout is the name of the - // environment variable that defines the time that the client waits for a - // response for the keep-alive probe. If the response is not received in - // this time, the connection is closed. - EnvVarSerialVolAccessEtcdDialKeepAliveTimeout = "X_CSI_SERIAL_VOL_ACCESS_ETCD_DIAL_KEEP_ALIVE_TIMEOUT" - - // EnvVarSerialVolAccessEtcdMaxCallSendMsgSz is the name of the environment - // variable that defines the client-side request send limit in bytes. - // If 0, it defaults to 2.0 MiB (2 * 1024 * 1024). - // Make sure that "MaxCallSendMsgSize" < server-side default send/recv - // limit. ("--max-request-bytes" flag to etcd or - // "embed.Config.MaxRequestBytes"). - EnvVarSerialVolAccessEtcdMaxCallSendMsgSz = "X_CSI_SERIAL_VOL_ACCESS_ETCD_MAX_CALL_SEND_MSG_SZ" - - // EnvVarSerialVolAccessEtcdMaxCallRecvMsgSz is the name of the environment - // variable that defines the client-side response receive limit. - // If 0, it defaults to "math.MaxInt32", because range response can - // easily exceed request send limits. - // Make sure that "MaxCallRecvMsgSize" >= server-side default send/recv - // limit. ("--max-request-bytes" flag to etcd or - // "embed.Config.MaxRequestBytes"). - EnvVarSerialVolAccessEtcdMaxCallRecvMsgSz = "X_CSI_SERIAL_VOL_ACCESS_ETCD_MAX_CALL_RECV_MSG_SZ" - - // EnvVarSerialVolAccessEtcdUsername is the name of the environment - // variable that defines the user name used for authentication. - EnvVarSerialVolAccessEtcdUsername = "X_CSI_SERIAL_VOL_ACCESS_ETCD_USERNAME" - - // EnvVarSerialVolAccessEtcdPassword is the name of the environment - // variable that defines the password used for authentication. - EnvVarSerialVolAccessEtcdPassword = "X_CSI_SERIAL_VOL_ACCESS_ETCD_PASSWORD" - - // EnvVarSerialVolAccessEtcdRejectOldCluster is the name of the environment - // variable that defines when set will refuse to create a client against - // an outdated cluster. - EnvVarSerialVolAccessEtcdRejectOldCluster = "X_CSI_SERIAL_VOL_ACCESS_ETCD_REJECT_OLD_CLUSTER" - - // EnvVarSerialVolAccessEtcdTLS is the name of the environment - // variable that defines whether or not the client should attempt - // to use TLS when connecting to the server. - EnvVarSerialVolAccessEtcdTLS = "X_CSI_SERIAL_VOL_ACCESS_ETCD_TLS" - - // EnvVarSerialVolAccessEtcdTLSInsecure is the name of the environment - // variable that defines whether or not the TLS connection should - // verify certificates. - EnvVarSerialVolAccessEtcdTLSInsecure = "X_CSI_SERIAL_VOL_ACCESS_ETCD_TLS_INSECURE" -) - -func (sp *StoragePlugin) initEnvVars(ctx context.Context) { - - // Copy the environment variables from the public EnvVar - // string slice to the private envVars map for quick lookup. - sp.envVars = map[string]string{} - for _, v := range sp.EnvVars { - // Environment variables must adhere to one of the following - // formats: - // - // - ENV_VAR_KEY= - // - ENV_VAR_KEY=ENV_VAR_VAL - pair := strings.SplitN(v, "=", 2) - if len(pair) < 1 || len(pair) > 2 { - continue - } - - // Ensure the environment variable is stored in all upper-case - // to make subsequent map-lookups deterministic. - key := strings.ToUpper(pair[0]) - - // Check to see if the value for the key is available from the - // context's os.Environ or os.LookupEnv functions. If neither - // return a value then use the provided default value. - var val string - if v, ok := csictx.LookupEnv(ctx, key); ok { - val = v - } else if len(pair) > 1 { - val = pair[1] - } - sp.envVars[key] = val - } - - // Check for the debug value. - if v, ok := csictx.LookupEnv(ctx, EnvVarDebug); ok { - if ok, _ := strconv.ParseBool(v); ok { - csictx.Setenv(ctx, EnvVarReqLogging, "true") - csictx.Setenv(ctx, EnvVarRepLogging, "true") - } - } - - return -} - -func (sp *StoragePlugin) initPluginInfo(ctx context.Context) { - szInfo, ok := csictx.LookupEnv(ctx, EnvVarPluginInfo) - if !ok { - return - } - info := strings.SplitN(szInfo, ",", 3) - fields := map[string]interface{}{} - if len(info) > 0 { - sp.pluginInfo.Name = strings.TrimSpace(info[0]) - fields["name"] = sp.pluginInfo.Name - } - if len(info) > 1 { - sp.pluginInfo.VendorVersion = strings.TrimSpace(info[1]) - fields["vendorVersion"] = sp.pluginInfo.VendorVersion - } - if len(info) > 2 { - sp.pluginInfo.Manifest = utils.ParseMap(strings.TrimSpace(info[2])) - fields["manifest"] = sp.pluginInfo.Manifest - } - - if len(fields) > 0 { - log.WithFields(fields).Debug("init plug-in info") - } -} diff --git a/mock/gocsi/gocsi.go b/mock/gocsi/gocsi.go deleted file mode 100644 index 4b70ecc4..00000000 --- a/mock/gocsi/gocsi.go +++ /dev/null @@ -1,545 +0,0 @@ -//go:generate make - -// Package gocsi provides a Container Storage Interface (CSI) library, -// client, and other helpful utilities. -package gocsi - -import ( - "bufio" - "context" - "errors" - "flag" - "fmt" - "io" - "net" - "os" - "os/signal" - "os/user" - "regexp" - "strconv" - "strings" - "sync" - "syscall" - "text/template" - - log "github.com/sirupsen/logrus" - "google.golang.org/grpc" - - "github.com/container-storage-interface/spec/lib/go/csi/v0" - - csictx "github.com/kubernetes-csi/csi-test/mock/context" - "github.com/kubernetes-csi/csi-test/mock/utils" -) - -// Run launches a CSI storage plug-in. -func Run( - ctx context.Context, - appName, appDescription, appUsage string, - sp StoragePluginProvider) { - - // Check for the debug value. - if v, ok := csictx.LookupEnv(ctx, EnvVarDebug); ok { - if ok, _ := strconv.ParseBool(v); ok { - csictx.Setenv(ctx, EnvVarLogLevel, "debug") - csictx.Setenv(ctx, EnvVarReqLogging, "true") - csictx.Setenv(ctx, EnvVarRepLogging, "true") - } - } - - // Adjust the log level. - lvl := log.InfoLevel - if v, ok := csictx.LookupEnv(ctx, EnvVarLogLevel); ok { - var err error - if lvl, err = log.ParseLevel(v); err != nil { - lvl = log.InfoLevel - } - } - log.SetLevel(lvl) - - printUsage := func() { - // app is the information passed to the printUsage function - app := struct { - Name string - Description string - Usage string - BinPath string - }{ - appName, - appDescription, - appUsage, - os.Args[0], - } - - t, err := template.New("t").Parse(usage) - if err != nil { - log.WithError(err).Fatalln("failed to parse usage template") - } - if err := t.Execute(os.Stderr, app); err != nil { - log.WithError(err).Fatalln("failed emitting usage") - } - return - } - - // Check for a help flag. - fs := flag.NewFlagSet("csp", flag.ExitOnError) - fs.Usage = printUsage - var help bool - fs.BoolVar(&help, "?", false, "") - err := fs.Parse(os.Args) - if err == flag.ErrHelp || help { - printUsage() - os.Exit(1) - } - - // If no endpoint is set then print the usage. - if os.Getenv(EnvVarEndpoint) == "" { - printUsage() - os.Exit(1) - } - - l, err := utils.GetCSIEndpointListener() - if err != nil { - log.WithError(err).Fatalln("failed to listen") - } - - // Define a lambda that can be used in the exit handler - // to remove a potential UNIX sock file. - var rmSockFileOnce sync.Once - rmSockFile := func() { - rmSockFileOnce.Do(func() { - if l == nil || l.Addr() == nil { - return - } - if l.Addr().Network() == netUnix { - sockFile := l.Addr().String() - os.RemoveAll(sockFile) - log.WithField("path", sockFile).Info("removed sock file") - } - }) - } - - trapSignals(func() { - sp.GracefulStop(ctx) - rmSockFile() - log.Info("server stopped gracefully") - }, func() { - sp.Stop(ctx) - rmSockFile() - log.Info("server aborted") - }) - - if err := sp.Serve(ctx, l); err != nil { - rmSockFile() - log.WithError(err).Fatal("grpc failed") - } -} - -// StoragePluginProvider is able to serve a gRPC endpoint that provides -// the CSI services: Controller, Identity, Node. -type StoragePluginProvider interface { - - // Serve accepts incoming connections on the listener lis, creating - // a new ServerTransport and service goroutine for each. The service - // goroutine read gRPC requests and then call the registered handlers - // to reply to them. Serve returns when lis.Accept fails with fatal - // errors. lis will be closed when this method returns. - // Serve always returns non-nil error. - Serve(ctx context.Context, lis net.Listener) error - - // Stop stops the gRPC server. It immediately closes all open - // connections and listeners. - // It cancels all active RPCs on the server side and the corresponding - // pending RPCs on the client side will get notified by connection - // errors. - Stop(ctx context.Context) - - // GracefulStop stops the gRPC server gracefully. It stops the server - // from accepting new connections and RPCs and blocks until all the - // pending RPCs are finished. - GracefulStop(ctx context.Context) -} - -// StoragePlugin is the collection of services and data used to server -// a new gRPC endpoint that acts as a CSI storage plug-in (SP). -type StoragePlugin struct { - // Controller is the eponymous CSI service. - Controller csi.ControllerServer - - // Identity is the eponymous CSI service. - Identity csi.IdentityServer - - // Node is the eponymous CSI service. - Node csi.NodeServer - - // ServerOpts is a list of gRPC server options used when serving - // the SP. This list should not include a gRPC interceptor option - // as one is created automatically based on the interceptor configuration - // or provided list of interceptors. - ServerOpts []grpc.ServerOption - - // Interceptors is a list of gRPC server interceptors to use when - // serving the SP. This list should not include the interceptors - // defined in the GoCSI package as those are configured by default - // based on runtime configuration settings. - Interceptors []grpc.UnaryServerInterceptor - - // BeforeServe is an optional callback that is invoked after the - // StoragePlugin has been initialized, just prior to the creation - // of the gRPC server. This callback may be used to perform custom - // initialization logic, modify the interceptors and server options, - // or prevent the server from starting by returning a non-nil error. - BeforeServe func(context.Context, *StoragePlugin, net.Listener) error - - // EnvVars is a list of default environment variables and values. - EnvVars []string - - serveOnce sync.Once - stopOnce sync.Once - server *grpc.Server - - envVars map[string]string - pluginInfo csi.GetPluginInfoResponse -} - -// Serve accepts incoming connections on the listener lis, creating -// a new ServerTransport and service goroutine for each. The service -// goroutine read gRPC requests and then call the registered handlers -// to reply to them. Serve returns when lis.Accept fails with fatal -// errors. lis will be closed when this method returns. -// Serve always returns non-nil error. -func (sp *StoragePlugin) Serve(ctx context.Context, lis net.Listener) error { - var err error - sp.serveOnce.Do(func() { - // Please note that the order of the below init functions is - // important and should not be altered unless by someone aware - // of how they work. - - // Adding this function to the context allows `csictx.LookupEnv` - // to search this SP's default env vars for a value. - ctx = csictx.WithLookupEnv(ctx, sp.lookupEnv) - - // Adding this function to the context allows `csictx.Setenv` - // to set environment variables in this SP's env var store. - ctx = csictx.WithSetenv(ctx, sp.setenv) - - // Initialize the storage plug-in's environment variables map. - sp.initEnvVars(ctx) - - // Adjust the endpoint's file permissions. - if err = sp.initEndpointPerms(ctx, lis); err != nil { - return - } - - // Adjust the endpoint's file ownership. - if err = sp.initEndpointOwner(ctx, lis); err != nil { - return - } - - // Initialize the storage plug-in's info. - sp.initPluginInfo(ctx) - - // Initialize the interceptors. - // sp.initInterceptors(ctx) - - // Invoke the SP's BeforeServe function to give the SP a chance - // to perform any local initialization routines. - if f := sp.BeforeServe; f != nil { - if err = f(ctx, sp, lis); err != nil { - return - } - } - - // Add the interceptors to the server if any are configured. - if i := sp.Interceptors; len(i) > 0 { - sp.ServerOpts = append(sp.ServerOpts, - grpc.UnaryInterceptor(utils.ChainUnaryServer(i...))) - } - - // Initialize the gRPC server. - sp.server = grpc.NewServer(sp.ServerOpts...) - - // Register the CSI services. - // Always require the identity service. - if sp.Identity == nil { - err = errors.New("identity service is required") - return - } - // Either a Controller or Node service should be supplied. - if sp.Controller == nil && sp.Node == nil { - err = errors.New( - "either a controller or node service is required") - return - } - - // Always register the identity service. - csi.RegisterIdentityServer(sp.server, sp.Identity) - log.Info("identity service registered") - - // Determine which of the controller/node services to register - mode := csictx.Getenv(ctx, EnvVarMode) - if strings.EqualFold(mode, "controller") { - mode = "controller" - } else if strings.EqualFold(mode, "node") { - mode = "node" - } else { - mode = "" - } - - if mode == "" || mode == "controller" { - if sp.Controller == nil { - err = errors.New("controller service is required") - return - } - csi.RegisterControllerServer(sp.server, sp.Controller) - log.Info("controller service registered") - } - if mode == "" || mode == "node" { - if sp.Node == nil { - err = errors.New("node service is required") - return - } - csi.RegisterNodeServer(sp.server, sp.Node) - log.Info("node service registered") - } - - endpoint := fmt.Sprintf( - "%s://%s", - lis.Addr().Network(), lis.Addr().String()) - log.WithField("endpoint", endpoint).Info("serving") - - // Start the gRPC server. - err = sp.server.Serve(lis) - return - }) - return err -} - -// Stop stops the gRPC server. It immediately closes all open -// connections and listeners. -// It cancels all active RPCs on the server side and the corresponding -// pending RPCs on the client side will get notified by connection -// errors. -func (sp *StoragePlugin) Stop(ctx context.Context) { - sp.stopOnce.Do(func() { - sp.server.Stop() - log.Info("stopped") - }) -} - -// GracefulStop stops the gRPC server gracefully. It stops the server -// from accepting new connections and RPCs and blocks until all the -// pending RPCs are finished. -func (sp *StoragePlugin) GracefulStop(ctx context.Context) { - sp.stopOnce.Do(func() { - sp.server.GracefulStop() - log.Info("gracefully stopped") - }) -} - -const netUnix = "unix" - -func (sp *StoragePlugin) initEndpointPerms( - ctx context.Context, lis net.Listener) error { - - if lis.Addr().Network() != netUnix { - return nil - } - - v, ok := csictx.LookupEnv(ctx, EnvVarEndpointPerms) - if !ok || v == "0755" { - return nil - } - u, err := strconv.ParseUint(v, 8, 32) - if err != nil { - return err - } - - p := lis.Addr().String() - m := os.FileMode(u) - - log.WithFields(map[string]interface{}{ - "path": p, - "mode": m, - }).Info("chmod csi endpoint") - - if err := os.Chmod(p, m); err != nil { - return err - } - - return nil -} - -func (sp *StoragePlugin) initEndpointOwner( - ctx context.Context, lis net.Listener) error { - - if lis.Addr().Network() != netUnix { - return nil - } - - var ( - usrName string - grpName string - - uid = os.Getuid() - gid = os.Getgid() - puid = uid - pgid = gid - ) - - if v, ok := csictx.LookupEnv(ctx, EnvVarEndpointUser); ok { - m, err := regexp.MatchString(`^\d+$`, v) - if err != nil { - return err - } - usrName = v - szUID := v - if m { - u, err := user.LookupId(v) - if err != nil { - return err - } - usrName = u.Username - } else { - u, err := user.Lookup(v) - if err != nil { - return err - } - szUID = u.Uid - } - iuid, err := strconv.Atoi(szUID) - if err != nil { - return err - } - uid = iuid - } - - if v, ok := csictx.LookupEnv(ctx, EnvVarEndpointGroup); ok { - m, err := regexp.MatchString(`^\d+$`, v) - if err != nil { - return err - } - grpName = v - szGID := v - if m { - u, err := user.LookupGroupId(v) - if err != nil { - return err - } - grpName = u.Name - } else { - u, err := user.LookupGroup(v) - if err != nil { - return err - } - szGID = u.Gid - } - igid, err := strconv.Atoi(szGID) - if err != nil { - return err - } - gid = igid - } - - if uid != puid || gid != pgid { - f := lis.Addr().String() - log.WithFields(map[string]interface{}{ - "uid": usrName, - "gid": grpName, - "path": f, - }).Info("chown csi endpoint") - if err := os.Chown(f, uid, gid); err != nil { - return err - } - } - - return nil -} - -func (sp *StoragePlugin) lookupEnv(key string) (string, bool) { - val, ok := sp.envVars[key] - return val, ok -} - -func (sp *StoragePlugin) setenv(key, val string) error { - sp.envVars[key] = val - return nil -} - -func (sp *StoragePlugin) getEnvBool(ctx context.Context, key string) bool { - v, ok := csictx.LookupEnv(ctx, key) - if !ok { - return false - } - if b, err := strconv.ParseBool(v); err == nil { - return b - } - return false -} - -func trapSignals(onExit, onAbort func()) { - sigc := make(chan os.Signal, 1) - sigs := []os.Signal{ - syscall.SIGTERM, - syscall.SIGHUP, - syscall.SIGINT, - syscall.SIGQUIT, - } - signal.Notify(sigc, sigs...) - go func() { - for s := range sigc { - ok, graceful := isExitSignal(s) - if !ok { - continue - } - if !graceful { - log.WithField("signal", s).Error("received signal; aborting") - if onAbort != nil { - onAbort() - } - os.Exit(1) - } - log.WithField("signal", s).Info("received signal; shutting down") - if onExit != nil { - onExit() - } - os.Exit(0) - } - }() -} - -// isExitSignal returns a flag indicating whether a signal SIGHUP, -// SIGINT, SIGTERM, or SIGQUIT. The second return value is whether it is a -// graceful exit. This flag is true for SIGTERM, SIGHUP, SIGINT, and SIGQUIT. -func isExitSignal(s os.Signal) (bool, bool) { - switch s { - case syscall.SIGTERM, - syscall.SIGHUP, - syscall.SIGINT, - syscall.SIGQUIT: - return true, true - default: - return false, false - } -} - -type logger struct { - f func(msg string, args ...interface{}) - w io.Writer -} - -func newLogger(f func(msg string, args ...interface{})) *logger { - l := &logger{f: f} - r, w := io.Pipe() - l.w = w - go func() { - scan := bufio.NewScanner(r) - for scan.Scan() { - f(scan.Text()) - } - }() - return l -} - -func (l *logger) Write(data []byte) (int, error) { - return l.w.Write(data) -} diff --git a/mock/gocsi/usage.go b/mock/gocsi/usage.go deleted file mode 100644 index 29b05fca..00000000 --- a/mock/gocsi/usage.go +++ /dev/null @@ -1,269 +0,0 @@ -package gocsi - -const usage = `NAME - {{.Name}} -- {{.Description}} - -SYNOPSIS - {{.BinPath}} -{{if .Usage}} -STORAGE OPTIONS -{{.Usage}}{{end}} -GLOBAL OPTIONS - CSI_ENDPOINT - The CSI endpoint may also be specified by the environment variable - CSI_ENDPOINT. The endpoint should adhere to Go's network address - pattern: - - * tcp://host:port - * unix:///path/to/file.sock. - - If the network type is omitted then the value is assumed to be an - absolute or relative filesystem path to a UNIX socket file - - X_CSI_MODE - Specifies the service mode of the storage plug-in. Valid values are: - - * - * controller - * node - - If unset or set to an empty value the storage plug-in activates - both controller and node services. The identity service is always - activated. - - X_CSI_ENDPOINT_PERMS - When CSI_ENDPOINT is set to a UNIX socket file this environment - variable may be used to specify the socket's file permissions - as an octal number, ex. 0644. Please note this value has no - effect if CSI_ENDPOINT specifies a TCP socket. - - The default value is 0755. - - X_CSI_ENDPOINT_USER - When CSI_ENDPOINT is set to a UNIX socket file this environment - variable may be used to specify the UID or user name of the - user that owns the file. Please note this value has no - effect if CSI_ENDPOINT specifies a TCP socket. - - If no value is specified then the user owner of the file is the - same as the user that starts the process. - - X_CSI_ENDPOINT_GROUP - When CSI_ENDPOINT is set to a UNIX socket file this environment - variable may be used to specify the GID or group name of the - group that owns the file. Please note this value has no - effect if CSI_ENDPOINT specifies a TCP socket. - - If no value is specified then the group owner of the file is the - same as the group that starts the process. - - X_CSI_DEBUG - Enabling this option is the same as: - X_CSI_LOG_LEVEL=debug - X_CSI_REQ_LOGGING=true - X_CSI_REP_LOGGING=true - - X_CSI_LOG_LEVEL - The log level. Valid values include: - * PANIC - * FATAL - * ERROR - * WARN - * INFO - * DEBUG - - The default value is WARN. - - X_CSI_SUPPORTED_VERSIONS - A list of comma-separated versions strings: MAJOR.MINOR.PATCH. - Setting this environment variable will cause the program to - bypass the SP's GetSupportedVersions RPC and return the list of - specified versions instead. - - X_CSI_PLUGIN_INFO - The plug-in information is specified via the following - comma-separated format: - - NAME, VENDOR_VERSION[, MANIFEST...] - - The MANIFEST value may be a series of additional - comma-separated key/value pairs. - - Please see the encoding/csv package (https://goo.gl/1j1xb9) for - information on how to quote keys and/or values to include - leading and trailing whitespace. - - Setting this environment variable will cause the program to - bypass the SP's GetPluginInfo RPC and returns the specified - information instead. - - X_CSI_REQ_LOGGING - A flag that enables logging of incoming requests to STDOUT. - - Enabling this option sets X_CSI_REQ_ID_INJECTION=true. - - X_CSI_REP_LOGGING - A flag that enables logging of outgoing responses to STDOUT. - - Enabling this option sets X_CSI_REQ_ID_INJECTION=true. - - X_CSI_REQ_ID_INJECTION - A flag that enables request ID injection. The ID is parsed from - the incoming request's metadata with a key of "csi.requestid". - If no value for that key is found then a new request ID is - generated using an atomic sequence counter. - - X_CSI_SPEC_VALIDATION - Setting X_CSI_SPEC_VALIDATION=true is the same as: - X_CSI_SPEC_REQ_VALIDATION=true - X_CSI_SPEC_REP_VALIDATION=true - - X_CSI_SPEC_REQ_VALIDATION - A flag that enables the validation of CSI request messages. - - X_CSI_SPEC_REP_VALIDATION - A flag that enables the validation of CSI response messages. - Invalid responses are marshalled into a gRPC error with a code - of "Internal." - - X_CSI_REQUIRE_NODE_ID - A flag that enables treating the following fields as required: - * ControllerPublishVolumeRequest.NodeId - * NodeGetIdResponse.NodeId - - Enabling this option sets X_CSI_SPEC_REQ_VALIDATION=true. - - X_CSI_REQUIRE_PUB_VOL_INFO - A flag that enables treating the following fields as required: - * ControllerPublishVolumeResponse.PublishVolumeInfo - * NodePublishVolumeRequest.PublishVolumeInfo - - Enabling this option sets X_CSI_SPEC_REQ_VALIDATION=true. - - X_CSI_REQUIRE_VOL_ATTRIBS - A flag that enables treating the following fields as required: - * ControllerPublishVolumeRequest.VolumeAttributes - * ValidateVolumeCapabilitiesRequest.VolumeAttributes - * NodePublishVolumeRequest.VolumeAttributes - - Enabling this option sets X_CSI_SPEC_REQ_VALIDATION=true. - - X_CSI_REQUIRE_CREDS - Setting X_CSI_REQUIRE_CREDS=true is the same as: - X_CSI_REQUIRE_CREDS_CREATE_VOL=true - X_CSI_REQUIRE_CREDS_DELETE_VOL=true - X_CSI_REQUIRE_CREDS_CTRLR_PUB_VOL=true - X_CSI_REQUIRE_CREDS_CTRLR_UNPUB_VOL=true - X_CSI_REQUIRE_CREDS_NODE_PUB_VOL=true - X_CSI_REQUIRE_CREDS_NODE_UNPUB_VOL=true - - Enabling this option sets X_CSI_SPEC_REQ_VALIDATION=true. - - X_CSI_REQUIRE_CREDS_CREATE_VOL - A flag that enables treating the following fields as required: - * CreateVolumeRequest.UserCredentials - - Enabling this option sets X_CSI_SPEC_REQ_VALIDATION=true. - - X_CSI_REQUIRE_CREDS_DELETE_VOL - A flag that enables treating the following fields as required: - * DeleteVolumeRequest.UserCredentials - - Enabling this option sets X_CSI_SPEC_REQ_VALIDATION=true. - - X_CSI_REQUIRE_CREDS_CTRLR_PUB_VOL - A flag that enables treating the following fields as required: - * ControllerPublishVolumeRequest.UserCredentials - - Enabling this option sets X_CSI_SPEC_REQ_VALIDATION=true. - - X_CSI_REQUIRE_CREDS_CTRLR_UNPUB_VOL - A flag that enables treating the following fields as required: - * ControllerUnpublishVolumeRequest.UserCredentials - - Enabling this option sets X_CSI_SPEC_REQ_VALIDATION=true. - - X_CSI_REQUIRE_CREDS_NODE_PUB_VOL - A flag that enables treating the following fields as required: - * NodePublishVolumeRequest.UserCredentials - - Enabling this option sets X_CSI_SPEC_REQ_VALIDATION=true. - - X_CSI_REQUIRE_CREDS_NODE_UNPUB_VOL - A flag that enables treating the following fields as required: - * NodeUnpublishVolumeRequest.UserCredentials - - Enabling this option sets X_CSI_SPEC_REQ_VALIDATION=true. - - X_CSI_SERIAL_VOL_ACCESS - A flag that enables the serial volume access middleware. - - X_CSI_SERIAL_VOL_ACCESS_TIMEOUT - A time.Duration string that determines how long the serial volume - access middleware waits to obtain a lock for the request's volume before - returning a the gRPC error code FailedPrecondition (5) to indicate - an operation is already pending for the specified volume. - - X_CSI_SERIAL_VOL_ACCESS_ETCD_DOMAIN - The name of the environment variable that defines the etcd lock - provider's concurrency domain. - - X_CSI_SERIAL_VOL_ACCESS_ETCD_TTL - The length of time etcd will wait before releasing ownership of a - distributed lock if the lock's session has not been renewed. - - X_CSI_SERIAL_VOL_ACCESS_ETCD_ENDPOINTS - A comma-separated list of etcd endpoints. If specified then the - SP's serial volume access middleware will leverage etcd to enable - distributed locking. - - X_CSI_SERIAL_VOL_ACCESS_ETCD_AUTO_SYNC_INTERVAL - A time.Duration string that specifies the interval to update - endpoints with its latest members. A value of 0 disables - auto-sync. By default auto-sync is disabled. - - X_CSI_SERIAL_VOL_ACCESS_ETCD_DIAL_TIMEOUT - A time.Duration string that specifies the timeout for failing to - establish a connection. - - X_CSI_SERIAL_VOL_ACCESS_ETCD_DIAL_KEEP_ALIVE_TIME - A time.Duration string that defines the time after which the client - pings the server to see if the transport is alive. - - X_CSI_SERIAL_VOL_ACCESS_ETCD_DIAL_KEEP_ALIVE_TIMEOUT - A time.Duration string that defines the time that the client waits for - a response for the keep-alive probe. If the response is not received - in this time, the connection is closed. - - X_CSI_SERIAL_VOL_ACCESS_ETCD_MAX_CALL_SEND_MSG_SZ - Defines the client-side request send limit in bytes. If 0, it defaults - to 2.0 MiB (2 * 1024 * 1024). Make sure that "MaxCallSendMsgSize" < - server-side default send/recv limit. ("--max-request-bytes" flag to - etcd or "embed.Config.MaxRequestBytes"). - - X_CSI_SERIAL_VOL_ACCESS_ETCD_MAX_CALL_RECV_MSG_SZ - Defines the client-side response receive limit. If 0, it defaults to - "math.MaxInt32", because range response can easily exceed request send - limits. Make sure that "MaxCallRecvMsgSize" >= server-side default - send/recv limit. ("--max-request-bytes" flag to etcd or - "embed.Config.MaxRequestBytes"). - - X_CSI_SERIAL_VOL_ACCESS_ETCD_USERNAME - The user name used for authentication. - - X_CSI_SERIAL_VOL_ACCESS_ETCD_PASSWORD - The password used for authentication. - - X_CSI_SERIAL_VOL_ACCESS_ETCD_REJECT_OLD_CLUSTER - A flag that indicates refusal to create a client against an outdated - cluster. - - X_CSI_SERIAL_VOL_ACCESS_ETCD_TLS - A flag that indicates the client should attempt a TLS connection. - - X_CSI_SERIAL_VOL_ACCESS_ETCD_TLS_INSECURE - A flag that indicates the TLS connection should not verify peer - certificates. - -The flags -?,-h,-help may be used to print this screen. -` diff --git a/mock/main.go b/mock/main.go index 17dce66d..b42436de 100644 --- a/mock/main.go +++ b/mock/main.go @@ -1,19 +1,66 @@ package main import ( - "context" + "fmt" + "net" + "os" + "os/signal" + "strings" + "syscall" - "github.com/kubernetes-csi/csi-test/mock/gocsi" - "github.com/kubernetes-csi/csi-test/mock/provider" + "github.com/kubernetes-csi/csi-test/driver" "github.com/kubernetes-csi/csi-test/mock/service" ) -// main is ignored when this package is built as a go plug-in func main() { - gocsi.Run( - context.Background(), - service.Name, - "A Mock Container Storage Interface (CSI) Storage Plug-in (SP)", - "", - provider.New()) + endpoint := os.Getenv("CSI_ENDPOINT") + if len(endpoint) == 0 { + fmt.Println("CSI_ENDPOINT must be defined and must be a path") + return + } + if strings.Contains(endpoint, ":") { + fmt.Println("CSI_ENDPOINT must be a unix path") + return + } + + // Create mock driver + s := service.New() + servers := &driver.CSIDriverServers{ + Controller: s, + Identity: s, + Node: s, + } + d := driver.NewCSIDriver(servers) + + // Listen + os.Remove(endpoint) + l, err := net.Listen("unix", endpoint) + if err != nil { + fmt.Printf("Error: Unable to listen on %s socket: %v\n", + endpoint, + err) + return + } + defer os.Remove(endpoint) + + // Start server + if err := d.Start(l); err != nil { + fmt.Printf("Error: Unable to start mock CSI server: %v\n", + err) + } + fmt.Println("mock driver started") + + // Wait for signal + sigc := make(chan os.Signal, 1) + sigs := []os.Signal{ + syscall.SIGTERM, + syscall.SIGHUP, + syscall.SIGINT, + syscall.SIGQUIT, + } + signal.Notify(sigc, sigs...) + + <-sigc + d.Stop() + fmt.Println("mock driver stopped") } diff --git a/mock/plugin.go b/mock/plugin.go deleted file mode 100644 index c3d0aac3..00000000 --- a/mock/plugin.go +++ /dev/null @@ -1,23 +0,0 @@ -// +build linux,plugin - -package main - -import "C" - -import ( - "github.com/kubernetes-csi/csi-test/mock/provider" - "github.com/kubernetes-csi/csi-test/mock/service" -) - -//////////////////////////////////////////////////////////////////////////////// -// Go Plug-in // -//////////////////////////////////////////////////////////////////////////////// - -// SupportedVersions is a space-delimited list of supported CSI versions. -var SupportedVersions = service.SupportedVersions - -// ServiceProviders is an exported symbol that provides a host program -// with a map of the service provider names and constructors. -var ServiceProviders = map[string]func() interface{}{ - service.Name: func() interface{} { return provider.New() }, -} diff --git a/mock/provider/provider.go b/mock/provider/provider.go deleted file mode 100644 index 6b36cb4f..00000000 --- a/mock/provider/provider.go +++ /dev/null @@ -1,53 +0,0 @@ -package provider - -import ( - "context" - "net" - - log "github.com/sirupsen/logrus" - - "github.com/kubernetes-csi/csi-test/mock/gocsi" - "github.com/kubernetes-csi/csi-test/mock/service" -) - -// New returns a new Mock Storage Plug-in Provider. -func New() gocsi.StoragePluginProvider { - svc := service.New() - return &gocsi.StoragePlugin{ - Controller: svc, - Identity: svc, - Node: svc, - - // BeforeServe allows the SP to participate in the startup - // sequence. This function is invoked directly before the - // gRPC server is created, giving the callback the ability to - // modify the SP's interceptors, server options, or prevent the - // server from starting by returning a non-nil error. - BeforeServe: func( - ctx context.Context, - sp *gocsi.StoragePlugin, - lis net.Listener) error { - - log.WithField("service", service.Name).Debug("BeforeServe") - return nil - }, - - EnvVars: []string{ - // Enable serial volume access. - gocsi.EnvVarSerialVolAccess + "=true", - - // Enable request and response validation. - gocsi.EnvVarSpecValidation + "=true", - - // Treat the following fields as required: - // * ControllerPublishVolumeRequest.NodeId - // * NodeGetNodeIdResponse.NodeId - gocsi.EnvVarRequireNodeID + "=true", - - // Treat the following fields as required: - // * ControllerPublishVolumeResponse.PublishInfo - // * NodePublishVolumeRequest.PublishInfo - gocsi.EnvVarRequirePubVolInfo + "=true", - }, - } -} diff --git a/mock/utils/utils.go b/mock/utils/utils.go deleted file mode 100644 index 5e64cdce..00000000 --- a/mock/utils/utils.go +++ /dev/null @@ -1,586 +0,0 @@ -package utils - -import ( - "bytes" - "context" - "encoding/csv" - "errors" - "fmt" - "io" - "net" - "os" - "regexp" - "sort" - "strings" - "sync" - - log "github.com/sirupsen/logrus" - "google.golang.org/grpc" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" - - "github.com/container-storage-interface/spec/lib/go/csi/v0" -) - -const maxuint32 = 4294967295 - -// GetCSIEndpoint returns the network address specified by the -// environment variable CSI_ENDPOINT. -func GetCSIEndpoint() (network, addr string, err error) { - protoAddr := os.Getenv(CSIEndpoint) - if emptyRX.MatchString(protoAddr) { - return "", "", errors.New("missing CSI_ENDPOINT") - } - return ParseProtoAddr(protoAddr) -} - -// GetCSIEndpointListener returns the net.Listener for the endpoint -// specified by the environment variable CSI_ENDPOINT. -func GetCSIEndpointListener() (net.Listener, error) { - proto, addr, err := GetCSIEndpoint() - if err != nil { - return nil, err - } - return net.Listen(proto, addr) -} - -const ( - protoAddrGuessPatt = `(?i)^(?:tcp|udp|ip|unix)[^:]*://` - - protoAddrExactPatt = `(?i)^((?:(?:tcp|udp|ip)[46]?)|` + - `(?:unix(?:gram|packet)?))://(.+)$` -) - -var ( - emptyRX = regexp.MustCompile(`^\s*$`) - protoAddrGuessRX = regexp.MustCompile(protoAddrGuessPatt) - protoAddrExactRX = regexp.MustCompile(protoAddrExactPatt) -) - -// ErrParseProtoAddrRequired occurs when an empty string is provided -// to ParseProtoAddr. -var ErrParseProtoAddrRequired = errors.New( - "non-empty network address is required") - -// ParseProtoAddr parses a Golang network address. -func ParseProtoAddr(protoAddr string) (proto string, addr string, err error) { - - if emptyRX.MatchString(protoAddr) { - return "", "", ErrParseProtoAddrRequired - } - - // If the provided network address does not begin with one - // of the valid network protocols then treat the string as a - // file path. - // - // First check to see if the file exists at the specified path. - // If it does then assume it's a valid file path and return it. - // - // Otherwise attempt to create the file. If the file can be created - // without error then remove the file and return the result a UNIX - // socket file path. - if !protoAddrGuessRX.MatchString(protoAddr) { - - // If the file already exists then assume it's a valid sock - // file and return it. - if _, err := os.Stat(protoAddr); !os.IsNotExist(err) { - return "unix", protoAddr, nil - } - - f, err := os.Create(protoAddr) - if err != nil { - return "", "", fmt.Errorf( - "invalid implied sock file: %s: %v", protoAddr, err) - } - if err := f.Close(); err != nil { - return "", "", fmt.Errorf( - "failed to verify network address as sock file: %s", protoAddr) - } - if err := os.RemoveAll(protoAddr); err != nil { - return "", "", fmt.Errorf( - "failed to remove verified sock file: %s", protoAddr) - } - return "unix", protoAddr, nil - } - - // Parse the provided network address into the protocol and address parts. - m := protoAddrExactRX.FindStringSubmatch(protoAddr) - if m == nil { - return "", "", fmt.Errorf("invalid network address: %s", protoAddr) - } - return m[1], m[2], nil -} - -// ParseMap parses a string into a map. The string's expected pattern is: -// -// KEY1=VAL1, "KEY2=VAL2 ", "KEY 3= VAL3" -// -// The key/value pairs are separated by a comma and optional whitespace. -// Please see the encoding/csv package (https://goo.gl/1j1xb9) for information -// on how to quote keys and/or values to include leading and trailing -// whitespace. -func ParseMap(line string) map[string]string { - line = strings.TrimSpace(line) - if line == "" { - return nil - } - - r := csv.NewReader(strings.NewReader(line)) - r.TrimLeadingSpace = true - - record, err := r.Read() - if err == io.EOF { - return nil - } - if err != nil { - panic(err) - } - - data := map[string]string{} - for i := range record { - p := strings.SplitN(record[i], "=", 2) - if len(p) == 0 { - continue - } - k := p[0] - var v string - if len(p) > 1 { - v = p[1] - } - data[k] = v - } - - return data -} - -// ParseSlice parses a string into a slice. The string's expected pattern is: -// -// VAL1, "VAL2 ", " VAL3 " -// -// The values are separated by a comma and optional whitespace. Please see -// the encoding/csv package (https://goo.gl/1j1xb9) for information on how to -// quote values to include leading and trailing whitespace. -func ParseSlice(line string) []string { - line = strings.TrimSpace(line) - if line == "" { - return nil - } - - r := csv.NewReader(strings.NewReader(line)) - r.TrimLeadingSpace = true - - record, err := r.Read() - if err == io.EOF { - return nil - } - if err != nil { - panic(err) - } - - return record -} - -// ParseMapWS parses a string into a map. The string's expected pattern is: -// -// KEY1=VAL1 KEY2="VAL2 " "KEY 3"=' VAL3' -// -// The key/value pairs are separated by one or more whitespace characters. -// Keys and/or values with whitespace should be quoted with either single -// or double quotes. -func ParseMapWS(line string) map[string]string { - if line == "" { - return nil - } - - var ( - escp bool - quot rune - ckey string - keyb = &bytes.Buffer{} - valb = &bytes.Buffer{} - word = keyb - data = map[string]string{} - ) - - for i, c := range line { - // Check to see if the character is a quote character. - switch c { - case '\\': - // If not already escaped then activate escape. - if !escp { - escp = true - continue - } - case '\'', '"': - // If the quote or double quote is the first char or - // an unescaped char then determine if this is the - // beginning of a quote or end of one. - if i == 0 || !escp { - if quot == c { - quot = 0 - } else { - quot = c - } - continue - } - case '=': - // If the word buffer is currently the key buffer, - // quoting is not enabled, and the preceeding character - // is not the escape character then the equal sign indicates - // a transition from key to value. - if word == keyb && quot == 0 && !escp { - ckey = keyb.String() - keyb.Reset() - word = valb - continue - } - case ' ', '\t': - // If quoting is not enabled and the preceeding character is - // not the escape character then record the value into the - // map and fast-forward the cursor to the next, non-whitespace - // character. - if quot == 0 && !escp { - // Record the value into the map for the current key. - if ckey != "" { - data[ckey] = valb.String() - valb.Reset() - word = keyb - ckey = "" - } - continue - } - } - if escp { - escp = false - } - word.WriteRune(c) - } - - // If the current key string is not empty then record it with the value - // buffer's string value as a new pair. - if ckey != "" { - data[ckey] = valb.String() - } - - return data -} - -// NewMountCapability returns a new *csi.VolumeCapability for a -// volume that is to be mounted. -func NewMountCapability( - mode csi.VolumeCapability_AccessMode_Mode, - fsType string, - mountFlags ...string) *csi.VolumeCapability { - - return &csi.VolumeCapability{ - AccessMode: &csi.VolumeCapability_AccessMode{ - Mode: mode, - }, - AccessType: &csi.VolumeCapability_Mount{ - Mount: &csi.VolumeCapability_MountVolume{ - FsType: fsType, - MountFlags: mountFlags, - }, - }, - } -} - -// NewBlockCapability returns a new *csi.VolumeCapability for a -// volume that is to be accessed as a raw device. -func NewBlockCapability( - mode csi.VolumeCapability_AccessMode_Mode) *csi.VolumeCapability { - - return &csi.VolumeCapability{ - AccessMode: &csi.VolumeCapability_AccessMode{ - Mode: mode, - }, - AccessType: &csi.VolumeCapability_Block{ - Block: &csi.VolumeCapability_BlockVolume{}, - }, - } -} - -// PageVolumes issues one or more ListVolumes requests to retrieve -// all available volumes, returning them over a Go channel. -func PageVolumes( - ctx context.Context, - client csi.ControllerClient, - req csi.ListVolumesRequest, - opts ...grpc.CallOption) (<-chan csi.Volume, <-chan error) { - - var ( - cvol = make(chan csi.Volume) - cerr = make(chan error) - ) - - // Execute the RPC in a goroutine, looping until there are no - // more volumes available. - go func() { - var ( - wg sync.WaitGroup - pages int - cancel context.CancelFunc - ) - - // Get a cancellation context used to control the interaction - // between returning volumes and the possibility of an error. - ctx, cancel = context.WithCancel(ctx) - - // waitAndClose closes the volume and error channels after all - // channel-dependent goroutines have completed their work - defer func() { - wg.Wait() - close(cerr) - close(cvol) - log.WithField("pages", pages).Debug("PageAllVolumes: exit") - }() - - sendVolumes := func(res csi.ListVolumesResponse) { - // Loop over the volume entries until they're all gone - // or the context is cancelled. - var i int - for i = 0; i < len(res.Entries) && ctx.Err() == nil; i++ { - - // Send the volume over the channel. - cvol <- *res.Entries[i].Volume - - // Let the wait group know that this worker has completed - // its task. - wg.Done() - } - // If not all volumes have been sent over the channel then - // deduct the remaining number from the wait group. - if i != len(res.Entries) { - rem := len(res.Entries) - i - log.WithFields(map[string]interface{}{ - "cancel": ctx.Err(), - "remaining": rem, - }).Warn("PageAllVolumes: cancelled w unprocessed results") - wg.Add(-rem) - } - } - - // listVolumes returns true if there are more volumes to list. - listVolumes := func() bool { - - // The wait group "wg" is blocked during the execution of - // this function. - wg.Add(1) - defer wg.Done() - - res, err := client.ListVolumes(ctx, &req, opts...) - if err != nil { - cerr <- err - - // Invoke the cancellation context function to - // ensure that work wraps up as quickly as possible. - cancel() - - return false - } - - // Add to the number of workers - wg.Add(len(res.Entries)) - - // Process the retrieved volumes. - go sendVolumes(*res) - - // Set the request's starting token to the response's - // next token. - req.StartingToken = res.NextToken - return req.StartingToken != "" - } - - // List volumes until there are no more volumes or the context - // is cancelled. - for { - if ctx.Err() != nil { - break - } - if !listVolumes() { - break - } - pages++ - } - }() - - return cvol, cerr -} - -// IsSuccess returns nil if the provided error is an RPC error with an error -// code that is OK (0) or matches one of the additional, provided successful -// error codes. Otherwise the original error is returned. -func IsSuccess(err error, successCodes ...codes.Code) error { - - // Shortcut the process by first checking to see if the error is nil. - if err == nil { - return nil - } - - // Check to see if the provided error is an RPC error. - stat, ok := status.FromError(err) - if !ok { - return err - } - - if stat.Code() == codes.OK { - return nil - } - for _, c := range successCodes { - if stat.Code() == c { - return nil - } - } - - return err -} - -// IsSuccessfulResponse uses IsSuccess to determine if the response for -// a specific CSI method is successful. If successful a nil value is -// returned; otherwise the original error is returned. -func IsSuccessfulResponse(method string, err error) error { - switch method { - case CreateVolume: - return IsSuccess(err, codes.AlreadyExists) - case DeleteVolume: - return IsSuccess(err, codes.NotFound) - } - return err -} - -// AreVolumeCapabilitiesCompatible returns a flag indicating whether -// the volume capability array "a" is compatible with "b". A true value -// indicates that "a" and "b" are equivalent or "b" is a superset of "a". -func AreVolumeCapabilitiesCompatible( - a, b []*csi.VolumeCapability) (bool, error) { - - if len(a) > len(b) { - return false, status.Error( - codes.AlreadyExists, - "requested capabilities exceed existing") - } - - var i int - - for _, va := range a { - for _, vb := range b { - if EqualVolumeCapability(va, vb) { - i++ - } - } - } - - return i >= len(a), nil -} - -// IsVolumeCapabilityCompatible returns a flag indicating whether -// the volume capability "a" is compatible with the set "b". A true value -// indicates that "a" and "b" are equivalent or "b" is a superset of "a". -func IsVolumeCapabilityCompatible( - a *csi.VolumeCapability, b []*csi.VolumeCapability) (bool, error) { - - return AreVolumeCapabilitiesCompatible([]*csi.VolumeCapability{a}, b) -} - -// EqualVolumeCapability returns a flag indicating if two csi.VolumeCapability -// objects are equal. If a and b are both nil then false is returned. -func EqualVolumeCapability(a, b *csi.VolumeCapability) bool { - if a == nil || b == nil { - return false - } - - // Compare access modes. - if a.AccessMode != nil && b.AccessMode == nil { - return false - } - if a.AccessMode == nil && b.AccessMode != nil { - return false - } - if a.AccessMode != nil && b.AccessMode != nil && - a.AccessMode.Mode != b.AccessMode.Mode { - return false - } - - // If both capabilities are block then return true. - if a.GetBlock() != nil && b.GetBlock() != nil { - return true - } - - aMount := a.GetMount() - bMount := b.GetMount() - if aMount != nil && bMount != nil { - - // If the filesystem types are incompatible then return false. - if aMount.FsType != bMount.FsType { - return false - } - - // Compare the mount flags lengths. - if len(aMount.MountFlags) != len(bMount.MountFlags) { - return false - } - - // Copy the mount flags to prevent the original order - // from changing due to the sort operation below. - af := append([]string{}, aMount.MountFlags...) - bf := append([]string{}, bMount.MountFlags...) - - // Sort the mount flags prior to comparison. - sort.Strings(af) - sort.Strings(bf) - - // Compare the mount flags. - for j := range af { - if af[j] != bf[j] { - return false - } - } - - // The mount capabilities are compatible; return true. - return true - } - - return false -} - -// EqualVolume returns a flag indicating if two csi.Volume -// objects are equal. If a and b are both nil then false is returned. -func EqualVolume(a, b *csi.Volume) bool { - if a == nil || b == nil { - return false - } - return CompareVolume(*a, *b) == 0 -} - -// CompareVolume compares two csi.Volume objects and returns a -// negative number if a < b, a positive number if a > b, and zero if -// a == b. -func CompareVolume(a, b csi.Volume) int { - if a.Id < b.Id { - return -1 - } - if a.Id > b.Id { - return 1 - } - if a.CapacityBytes < b.CapacityBytes { - return -1 - } - if a.CapacityBytes > b.CapacityBytes { - return 1 - } - if len(a.Attributes) < len(b.Attributes) { - return -1 - } - if len(a.Attributes) > len(b.Attributes) { - return 1 - } - for k, v := range a.Attributes { - if v < b.Attributes[k] { - return -1 - } - if v > b.Attributes[k] { - return 1 - } - } - return 0 -} diff --git a/mock/utils/utils_middleware.go b/mock/utils/utils_middleware.go deleted file mode 100644 index f9966f05..00000000 --- a/mock/utils/utils_middleware.go +++ /dev/null @@ -1,143 +0,0 @@ -package utils - -import ( - "golang.org/x/net/context" - "google.golang.org/grpc" - - "github.com/container-storage-interface/spec/lib/go/csi/v0" -) - -// ChainUnaryClient chains one or more unary, client interceptors -// together into a left-to-right series that can be provided to a -// new gRPC client. -func ChainUnaryClient( - i ...grpc.UnaryClientInterceptor) grpc.UnaryClientInterceptor { - - switch len(i) { - case 0: - return func( - ctx context.Context, - method string, - req, rep interface{}, - cc *grpc.ClientConn, - invoker grpc.UnaryInvoker, - opts ...grpc.CallOption) error { - return invoker(ctx, method, req, rep, cc, opts...) - } - case 1: - return i[0] - } - - return func( - ctx context.Context, - method string, - req, rep interface{}, - cc *grpc.ClientConn, - invoker grpc.UnaryInvoker, - opts ...grpc.CallOption) error { - - bc := func( - cur grpc.UnaryClientInterceptor, - nxt grpc.UnaryInvoker) grpc.UnaryInvoker { - - return func( - curCtx context.Context, - curMethod string, - curReq, curRep interface{}, - curCC *grpc.ClientConn, - curOpts ...grpc.CallOption) error { - - return cur( - curCtx, - curMethod, - curReq, curRep, - curCC, nxt, - curOpts...) - } - } - - c := invoker - for j := len(i) - 1; j >= 0; j-- { - c = bc(i[j], c) - } - - return c(ctx, method, req, rep, cc, opts...) - } -} - -// ChainUnaryServer chains one or more unary, server interceptors -// together into a left-to-right series that can be provided to a -// new gRPC server. -func ChainUnaryServer( - i ...grpc.UnaryServerInterceptor) grpc.UnaryServerInterceptor { - - switch len(i) { - case 0: - return func( - ctx context.Context, - req interface{}, - _ *grpc.UnaryServerInfo, - handler grpc.UnaryHandler) (interface{}, error) { - return handler(ctx, req) - } - case 1: - return i[0] - } - - return func( - ctx context.Context, - req interface{}, - info *grpc.UnaryServerInfo, - handler grpc.UnaryHandler) (interface{}, error) { - - bc := func( - cur grpc.UnaryServerInterceptor, - nxt grpc.UnaryHandler) grpc.UnaryHandler { - return func( - curCtx context.Context, - curReq interface{}) (interface{}, error) { - return cur(curCtx, curReq, info, nxt) - } - } - c := handler - for j := len(i) - 1; j >= 0; j-- { - c = bc(i[j], c) - } - return c(ctx, req) - } -} - -// nilResponses exceeds the 80char code limit, but to modify it would render -// it less readable than leaving it as is -var nilResponses = map[string]interface{}{ - CreateVolume: (*csi.CreateVolumeResponse)(nil), - DeleteVolume: (*csi.DeleteVolumeResponse)(nil), - ControllerPublishVolume: (*csi.ControllerPublishVolumeResponse)(nil), - ControllerUnpublishVolume: (*csi.ControllerUnpublishVolumeResponse)(nil), - ValidateVolumeCapabilities: (*csi.ValidateVolumeCapabilitiesResponse)(nil), - ListVolumes: (*csi.ListVolumesResponse)(nil), - GetCapacity: (*csi.GetCapacityResponse)(nil), - ControllerGetCapabilities: (*csi.ControllerGetCapabilitiesResponse)(nil), - GetPluginInfo: (*csi.GetPluginInfoResponse)(nil), - NodeGetId: (*csi.NodeGetIdResponse)(nil), - NodePublishVolume: (*csi.NodePublishVolumeResponse)(nil), - NodeUnpublishVolume: (*csi.NodeUnpublishVolumeResponse)(nil), - NodeGetCapabilities: (*csi.NodeGetCapabilitiesResponse)(nil), -} - -// IsNilResponse returns a flag indicating whether or not the provided -// response object is a nil object wrapped inside a non-nil interface. -func IsNilResponse(method string, rep interface{}) bool { - // Determine whether or not the resposne is nil. Otherwise it - // will no longer be possible to perform a nil equality check on the - // response to the interface{} rules for nil comparison. For more info - // please see https://golang.org/doc/faq#nil_error and - // https://github.com/grpc/grpc-go/issues/532. - if rep == nil { - return true - } - if nilRep := nilResponses[method]; rep == nilRep { - return true - } - return false -} diff --git a/mock/utils/utils_rpcs.go b/mock/utils/utils_rpcs.go deleted file mode 100644 index 55c20f88..00000000 --- a/mock/utils/utils_rpcs.go +++ /dev/null @@ -1,89 +0,0 @@ -package utils - -const ( - // Namespace is the namesapce used by the protobuf. - Namespace = "csi" - - // CSIEndpoint is the name of the environment variable that - // contains the CSI endpoint. - CSIEndpoint = "CSI_ENDPOINT" - - // - // Controller Service - // - ctrlSvc = "/" + Namespace + ".Controller/" - - // CreateVolume is the full method name for the - // eponymous RPC message. - CreateVolume = ctrlSvc + "CreateVolume" - - // DeleteVolume is the full method name for the - // eponymous RPC message. - DeleteVolume = ctrlSvc + "DeleteVolume" - - // ControllerPublishVolume is the full method name for the - // eponymous RPC message. - ControllerPublishVolume = ctrlSvc + "ControllerPublishVolume" - - // ControllerUnpublishVolume is the full method name for the - // eponymous RPC message. - ControllerUnpublishVolume = ctrlSvc + "ControllerUnpublishVolume" - - // ValidateVolumeCapabilities is the full method name for the - // eponymous RPC message. - ValidateVolumeCapabilities = ctrlSvc + "ValidateVolumeCapabilities" - - // ListVolumes is the full method name for the - // eponymous RPC message. - ListVolumes = ctrlSvc + "ListVolumes" - - // GetCapacity is the full method name for the - // eponymous RPC message. - GetCapacity = ctrlSvc + "GetCapacity" - - // ControllerGetCapabilities is the full method name for the - // eponymous RPC message. - ControllerGetCapabilities = ctrlSvc + "ControllerGetCapabilities" - - // ControllerProbe is the full method name for the - // eponymous RPC message. - ControllerProbe = ctrlSvc + "ControllerProbe" - - // - // Identity Service - // - identSvc = "/" + Namespace + ".Identity/" - - // GetSupportedVersions is the full method name for the - // eponymous RPC message. - GetSupportedVersions = identSvc + "GetSupportedVersions" - - // GetPluginInfo is the full method name for the - // eponymous RPC message. - GetPluginInfo = identSvc + "GetPluginInfo" - - // - // Node Service - // - nodeSvc = "/" + Namespace + ".Node/" - - // NodeGetId is the full method name for the - // eponymous RPC message. - NodeGetId = nodeSvc + "NodeGetId" - - // NodePublishVolume is the full method name for the - // eponymous RPC message. - NodePublishVolume = nodeSvc + "NodePublishVolume" - - // NodeUnpublishVolume is the full method name for the - // eponymous RPC message. - NodeUnpublishVolume = nodeSvc + "NodeUnpublishVolume" - - // NodeProbe is the full method name for the - // eponymous RPC message. - NodeProbe = nodeSvc + "NodeProbe" - - // NodeGetCapabilities is the full method name for the - // eponymous RPC message. - NodeGetCapabilities = nodeSvc + "NodeGetCapabilities" -) diff --git a/mock/utils/utils_suite_test.go b/mock/utils/utils_suite_test.go deleted file mode 100644 index bdc90681..00000000 --- a/mock/utils/utils_suite_test.go +++ /dev/null @@ -1,118 +0,0 @@ -package utils_test - -import ( - "github.com/onsi/ginkgo" - "github.com/onsi/gomega" - log "github.com/sirupsen/logrus" - - "testing" -) - -func TestUtils(t *testing.T) { - log.SetLevel(log.DebugLevel) - log.SetOutput(GinkgoWriter) - RegisterFailHandler(Fail) - RunSpecs(t, "Utils Suite") -} - -// Declarations for Ginkgo DSL -type Done ginkgo.Done -type Benchmarker ginkgo.Benchmarker - -var GinkgoWriter = ginkgo.GinkgoWriter -var GinkgoRandomSeed = ginkgo.GinkgoRandomSeed -var GinkgoParallelNode = ginkgo.GinkgoParallelNode -var GinkgoT = ginkgo.GinkgoT -var CurrentGinkgoTestDescription = ginkgo.CurrentGinkgoTestDescription -var RunSpecs = ginkgo.RunSpecs -var RunSpecsWithDefaultAndCustomReporters = ginkgo.RunSpecsWithDefaultAndCustomReporters -var RunSpecsWithCustomReporters = ginkgo.RunSpecsWithCustomReporters -var Skip = ginkgo.Skip -var Fail = ginkgo.Fail -var GinkgoRecover = ginkgo.GinkgoRecover -var Describe = ginkgo.Describe -var FDescribe = ginkgo.FDescribe -var PDescribe = ginkgo.PDescribe -var XDescribe = ginkgo.XDescribe -var Context = ginkgo.Context -var FContext = ginkgo.FContext -var PContext = ginkgo.PContext -var XContext = ginkgo.XContext -var It = ginkgo.It -var FIt = ginkgo.FIt -var PIt = ginkgo.PIt -var XIt = ginkgo.XIt -var Specify = ginkgo.Specify -var FSpecify = ginkgo.FSpecify -var PSpecify = ginkgo.PSpecify -var XSpecify = ginkgo.XSpecify -var By = ginkgo.By -var Measure = ginkgo.Measure -var FMeasure = ginkgo.FMeasure -var PMeasure = ginkgo.PMeasure -var XMeasure = ginkgo.XMeasure -var BeforeSuite = ginkgo.BeforeSuite -var AfterSuite = ginkgo.AfterSuite -var SynchronizedBeforeSuite = ginkgo.SynchronizedBeforeSuite -var SynchronizedAfterSuite = ginkgo.SynchronizedAfterSuite -var BeforeEach = ginkgo.BeforeEach -var JustBeforeEach = ginkgo.JustBeforeEach -var AfterEach = ginkgo.AfterEach - -// Declarations for Gomega DSL -var RegisterFailHandler = gomega.RegisterFailHandler -var RegisterTestingT = gomega.RegisterTestingT -var InterceptGomegaFailures = gomega.InterceptGomegaFailures -var Ω = gomega.Ω -var Expect = gomega.Expect -var ExpectWithOffset = gomega.ExpectWithOffset -var Eventually = gomega.Eventually -var EventuallyWithOffset = gomega.EventuallyWithOffset -var Consistently = gomega.Consistently -var ConsistentlyWithOffset = gomega.ConsistentlyWithOffset -var SetDefaultEventuallyTimeout = gomega.SetDefaultEventuallyTimeout -var SetDefaultEventuallyPollingInterval = gomega.SetDefaultEventuallyPollingInterval -var SetDefaultConsistentlyDuration = gomega.SetDefaultConsistentlyDuration -var SetDefaultConsistentlyPollingInterval = gomega.SetDefaultConsistentlyPollingInterval - -// Declarations for Gomega Matchers -var Equal = gomega.Equal -var BeEquivalentTo = gomega.BeEquivalentTo -var BeIdenticalTo = gomega.BeIdenticalTo -var BeNil = gomega.BeNil -var BeTrue = gomega.BeTrue -var BeFalse = gomega.BeFalse -var HaveOccurred = gomega.HaveOccurred -var Succeed = gomega.Succeed -var MatchError = gomega.MatchError -var BeClosed = gomega.BeClosed -var Receive = gomega.Receive -var BeSent = gomega.BeSent -var MatchRegexp = gomega.MatchRegexp -var ContainSubstring = gomega.ContainSubstring -var HavePrefix = gomega.HavePrefix -var HaveSuffix = gomega.HaveSuffix -var MatchJSON = gomega.MatchJSON -var MatchXML = gomega.MatchXML -var MatchYAML = gomega.MatchYAML -var BeEmpty = gomega.BeEmpty -var HaveLen = gomega.HaveLen -var HaveCap = gomega.HaveCap -var BeZero = gomega.BeZero -var ContainElement = gomega.ContainElement -var ConsistOf = gomega.ConsistOf -var HaveKey = gomega.HaveKey -var HaveKeyWithValue = gomega.HaveKeyWithValue -var BeNumerically = gomega.BeNumerically -var BeTemporally = gomega.BeTemporally -var BeAssignableToTypeOf = gomega.BeAssignableToTypeOf -var Panic = gomega.Panic -var BeAnExistingFile = gomega.BeAnExistingFile -var BeARegularFile = gomega.BeARegularFile -var BeADirectory = gomega.BeADirectory -var And = gomega.And -var SatisfyAll = gomega.SatisfyAll -var Or = gomega.Or -var SatisfyAny = gomega.SatisfyAny -var Not = gomega.Not -var WithTransform = gomega.WithTransform diff --git a/mock/utils/utils_test.go b/mock/utils/utils_test.go deleted file mode 100644 index d6748a73..00000000 --- a/mock/utils/utils_test.go +++ /dev/null @@ -1,415 +0,0 @@ -package utils_test - -import ( - "errors" - "fmt" - "os" - - "github.com/container-storage-interface/spec/lib/go/csi/v0" - "github.com/kubernetes-csi/csi-test/mock/utils" -) - -var errMissingCSIEndpoint = errors.New("missing CSI_ENDPOINT") - -var _ = Describe("GetCSIEndpoint", func() { - var ( - err error - proto string - addr string - expEndpoint string - expProto string - expAddr string - ) - BeforeEach(func() { - expEndpoint = CurrentGinkgoTestDescription().ComponentTexts[2] - os.Setenv(utils.CSIEndpoint, expEndpoint) - }) - AfterEach(func() { - proto = "" - addr = "" - expEndpoint = "" - expProto = "" - expAddr = "" - os.Unsetenv(utils.CSIEndpoint) - }) - JustBeforeEach(func() { - proto, addr, err = utils.GetCSIEndpoint() - }) - - Context("Valid Endpoint", func() { - shouldBeValid := func() { - Ω(os.Getenv(utils.CSIEndpoint)).Should(Equal(expEndpoint)) - Ω(proto).Should(Equal(expProto)) - Ω(addr).Should(Equal(expAddr)) - } - Context("tcp://127.0.0.1", func() { - BeforeEach(func() { - expProto = "tcp" - expAddr = "127.0.0.1" - }) - It("Should Be Valid", shouldBeValid) - }) - Context("tcp://127.0.0.1:8080", func() { - BeforeEach(func() { - expProto = "tcp" - expAddr = "127.0.0.1:8080" - }) - It("Should Be Valid", shouldBeValid) - }) - Context("tcp://*:8080", func() { - BeforeEach(func() { - expProto = "tcp" - expAddr = "*:8080" - }) - It("Should Be Valid", shouldBeValid) - }) - Context("unix://path/to/sock.sock", func() { - BeforeEach(func() { - expProto = "unix" - expAddr = "path/to/sock.sock" - }) - It("Should Be Valid", shouldBeValid) - }) - Context("unix:///path/to/sock.sock", func() { - BeforeEach(func() { - expProto = "unix" - expAddr = "/path/to/sock.sock" - }) - It("Should Be Valid", shouldBeValid) - }) - Context("sock.sock", func() { - BeforeEach(func() { - expProto = "unix" - expAddr = "sock.sock" - }) - It("Should Be Valid", shouldBeValid) - }) - Context("/tmp/sock.sock", func() { - BeforeEach(func() { - expProto = "unix" - expAddr = "/tmp/sock.sock" - }) - It("Should Be Valid", shouldBeValid) - }) - }) - - Context("Missing Endpoint", func() { - Context("", func() { - It("Should Be Missing", func() { - Ω(err).Should(HaveOccurred()) - Ω(err).Should(Equal(errMissingCSIEndpoint)) - }) - }) - Context(" ", func() { - It("Should Be Missing", func() { - Ω(err).Should(HaveOccurred()) - Ω(err).Should(Equal(errMissingCSIEndpoint)) - }) - }) - }) - - Context("Invalid Network Address", func() { - shouldBeInvalid := func() { - Ω(err).Should(HaveOccurred()) - Ω(err.Error()).Should(Equal(fmt.Sprintf( - "invalid network address: %s", expEndpoint))) - } - Context("tcp5://localhost:5000", func() { - It("Should Be An Invalid Endpoint", shouldBeInvalid) - }) - Context("unixpcket://path/to/sock.sock", func() { - It("Should Be An Invalid Endpoint", shouldBeInvalid) - }) - }) - - Context("Invalid Implied Sock File", func() { - shouldBeInvalid := func() { - Ω(err).Should(HaveOccurred()) - Ω(err.Error()).Should(Equal(fmt.Sprintf( - "invalid implied sock file: %[1]s: "+ - "open %[1]s: no such file or directory", - expEndpoint))) - } - Context("Xtcp5://localhost:5000", func() { - It("Should Be An Invalid Implied Sock File", shouldBeInvalid) - }) - Context("Xunixpcket://path/to/sock.sock", func() { - It("Should Be An Invalid Implied Sock File", shouldBeInvalid) - }) - }) -}) - -var _ = Describe("ParseProtoAddr", func() { - Context("Empty Address", func() { - It("Should Be An Empty Address", func() { - _, _, err := utils.ParseProtoAddr("") - Ω(err).Should(HaveOccurred()) - Ω(err).Should(Equal(utils.ErrParseProtoAddrRequired)) - }) - It("Should Be An Empty Address", func() { - _, _, err := utils.ParseProtoAddr(" ") - Ω(err).Should(HaveOccurred()) - Ω(err).Should(Equal(utils.ErrParseProtoAddrRequired)) - }) - }) -}) - -var _ = Describe("ParseMap", func() { - Context("One Pair", func() { - It("Should Be Valid", func() { - data := utils.ParseMap("k1=v1") - Ω(data).Should(HaveLen(1)) - Ω(data["k1"]).Should(Equal("v1")) - }) - }) - Context("Empty Line", func() { - It("Should Be Valid", func() { - data := utils.ParseMap("") - Ω(data).Should(HaveLen(0)) - }) - }) - Context("Key Sans Value", func() { - It("Should Be Valid", func() { - data := utils.ParseMap("k1") - Ω(data).Should(HaveLen(1)) - }) - }) - Context("Two Pair", func() { - It("Should Be Valid", func() { - data := utils.ParseMap("k1=v1, k2=v2") - Ω(data).Should(HaveLen(2)) - Ω(data["k1"]).Should(Equal("v1")) - Ω(data["k2"]).Should(Equal("v2")) - }) - }) - Context("Two Pair with Quoting & Escaping", func() { - It("Should Be Valid", func() { - data := utils.ParseMap(`k1=v1, "k2=v2""s"`) - Ω(data).Should(HaveLen(2)) - Ω(data["k1"]).Should(Equal("v1")) - Ω(data["k2"]).Should(Equal(`v2"s`)) - }) - It("Should Be Valid", func() { - data := utils.ParseMap(`k1=v1, "k2=v2\'s"`) - Ω(data).Should(HaveLen(2)) - Ω(data["k1"]).Should(Equal("v1")) - Ω(data["k2"]).Should(Equal(`v2\'s`)) - }) - It("Should Be Valid", func() { - data := utils.ParseMap(`k1=v1, k2=v2's`) - Ω(data).Should(HaveLen(2)) - Ω(data["k1"]).Should(Equal("v1")) - Ω(data["k2"]).Should(Equal(`v2's`)) - }) - }) - Context("Two Pair with Three Spaces Between Them", func() { - It("Should Be Valid", func() { - data := utils.ParseMap("k1=v1, k2=v2") - Ω(data).Should(HaveLen(2)) - Ω(data["k1"]).Should(Equal("v1")) - Ω(data["k2"]).Should(Equal("v2")) - }) - }) - Context("Two Pair with One Sans Value", func() { - It("Should Be Valid", func() { - data := utils.ParseMap("k1=, k2=v2") - Ω(data).Should(HaveLen(2)) - Ω(data["k1"]).Should(Equal("")) - Ω(data["k2"]).Should(Equal("v2")) - }) - }) - Context("Two Pair with One Sans Value & Three Spaces Between Them", func() { - It("Should Be Valid", func() { - data := utils.ParseMap("k1=, k2=v2") - Ω(data).Should(HaveLen(2)) - Ω(data["k1"]).Should(Equal("")) - Ω(data["k2"]).Should(Equal("v2")) - }) - }) - Context("One Pair with Quoted Value", func() { - It("Should Be Valid", func() { - data := utils.ParseMap("k1=v 1") - Ω(data).Should(HaveLen(1)) - Ω(data["k1"]).Should(Equal("v 1")) - }) - }) - Context("Three Pair with Mixed Values", func() { - It("Should Be Valid", func() { - data := utils.ParseMap(`"k1=v 1", "k2=v 2 ", "k3 =v3" `) - Ω(data).Should(HaveLen(3)) - Ω(data["k1"]).Should(Equal("v 1")) - Ω(data["k2"]).Should(Equal("v 2 ")) - Ω(data["k3 "]).Should(Equal("v3")) - }) - }) -}) - -var _ = Describe("CompareVolume", func() { - It("a == b", func() { - a := csi.Volume{Id: "0"} - b := csi.Volume{Id: "0"} - Ω(utils.CompareVolume(a, b)).Should(Equal(0)) - a.CapacityBytes = 1 - b.CapacityBytes = 1 - Ω(utils.CompareVolume(a, b)).Should(Equal(0)) - a.Attributes = map[string]string{"key": "val"} - b.Attributes = map[string]string{"key": "val"} - Ω(utils.CompareVolume(a, b)).Should(Equal(0)) - }) - It("a > b", func() { - a := csi.Volume{Id: "0"} - b := csi.Volume{} - Ω(utils.CompareVolume(a, b)).Should(Equal(1)) - b.Id = "0" - Ω(utils.CompareVolume(a, b)).Should(Equal(0)) - a.CapacityBytes = 1 - Ω(utils.CompareVolume(a, b)).Should(Equal(1)) - b.CapacityBytes = 1 - Ω(utils.CompareVolume(a, b)).Should(Equal(0)) - a.Attributes = map[string]string{"key": "val"} - Ω(utils.CompareVolume(a, b)).Should(Equal(1)) - b.Attributes = map[string]string{"key": "val"} - Ω(utils.CompareVolume(a, b)).Should(Equal(0)) - }) - It("a < b", func() { - b := csi.Volume{Id: "0"} - a := csi.Volume{} - Ω(utils.CompareVolume(a, b)).Should(Equal(-1)) - a.Id = "0" - Ω(utils.CompareVolume(a, b)).Should(Equal(0)) - b.CapacityBytes = 1 - Ω(utils.CompareVolume(a, b)).Should(Equal(-1)) - a.CapacityBytes = 1 - Ω(utils.CompareVolume(a, b)).Should(Equal(0)) - b.Attributes = map[string]string{"key": "val"} - Ω(utils.CompareVolume(a, b)).Should(Equal(-1)) - a.Attributes = map[string]string{"key": "val"} - Ω(utils.CompareVolume(a, b)).Should(Equal(0)) - }) -}) - -var _ = Describe("EqualVolumeCapability", func() { - It("a == b", func() { - a := &csi.VolumeCapability{ - AccessMode: &csi.VolumeCapability_AccessMode{ - Mode: csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER, - }, - AccessType: &csi.VolumeCapability_Block{ - Block: &csi.VolumeCapability_BlockVolume{}, - }, - } - b := &csi.VolumeCapability{ - AccessMode: &csi.VolumeCapability_AccessMode{ - Mode: csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER, - }, - AccessType: &csi.VolumeCapability_Block{ - Block: &csi.VolumeCapability_BlockVolume{}, - }, - } - Ω(utils.EqualVolumeCapability(a, b)).Should(BeTrue()) - a.AccessMode.Mode = csi.VolumeCapability_AccessMode_MULTI_NODE_READER_ONLY - Ω(utils.EqualVolumeCapability(a, b)).Should(BeFalse()) - b.AccessMode.Mode = csi.VolumeCapability_AccessMode_MULTI_NODE_READER_ONLY - Ω(utils.EqualVolumeCapability(a, b)).Should(BeTrue()) - a.AccessMode = nil - Ω(utils.EqualVolumeCapability(a, b)).Should(BeFalse()) - b.AccessMode = nil - Ω(utils.EqualVolumeCapability(a, b)).Should(BeTrue()) - a = nil - Ω(utils.EqualVolumeCapability(nil, b)).Should(BeFalse()) - b = nil - Ω(utils.EqualVolumeCapability(a, b)).Should(BeFalse()) - - aAT := &csi.VolumeCapability_Mount{ - Mount: &csi.VolumeCapability_MountVolume{ - FsType: "ext4", - MountFlags: []string{"rw"}, - }, - } - bAT := &csi.VolumeCapability_Mount{ - Mount: &csi.VolumeCapability_MountVolume{ - FsType: "ext4", - MountFlags: []string{"rw"}, - }, - } - - a = &csi.VolumeCapability{ - AccessMode: &csi.VolumeCapability_AccessMode{ - Mode: csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER, - }, - AccessType: aAT, - } - b = &csi.VolumeCapability{ - AccessMode: &csi.VolumeCapability_AccessMode{ - Mode: csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER, - }, - AccessType: bAT, - } - Ω(utils.EqualVolumeCapability(a, b)).Should(BeTrue()) - aAT.Mount.FsType = "xfs" - Ω(utils.EqualVolumeCapability(a, b)).Should(BeFalse()) - bAT.Mount.FsType = "xfs" - Ω(utils.EqualVolumeCapability(a, b)).Should(BeTrue()) - aAT.Mount.MountFlags = append(aAT.Mount.MountFlags, "nosuid") - Ω(utils.EqualVolumeCapability(a, b)).Should(BeFalse()) - bAT.Mount.MountFlags = append(bAT.Mount.MountFlags, "nosuid") - Ω(utils.EqualVolumeCapability(a, b)).Should(BeTrue()) - aAT.Mount.MountFlags[0] = "ro" - Ω(utils.EqualVolumeCapability(a, b)).Should(BeFalse()) - bAT.Mount.MountFlags[0] = "ro" - Ω(utils.EqualVolumeCapability(a, b)).Should(BeTrue()) - aAT.Mount.MountFlags = nil - Ω(utils.EqualVolumeCapability(a, b)).Should(BeFalse()) - bAT.Mount.MountFlags = nil - Ω(utils.EqualVolumeCapability(a, b)).Should(BeTrue()) - }) -}) - -var _ = Describe("AreVolumeCapabilitiesCompatible", func() { - It("compatible", func() { - aMountAT := &csi.VolumeCapability_Mount{ - Mount: &csi.VolumeCapability_MountVolume{ - FsType: "ext4", - MountFlags: []string{"rw"}, - }, - } - a := []*csi.VolumeCapability{ - { - AccessMode: &csi.VolumeCapability_AccessMode{ - Mode: csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER, - }, - AccessType: aMountAT, - }, - } - - b := []*csi.VolumeCapability{ - { - AccessMode: &csi.VolumeCapability_AccessMode{ - Mode: csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER, - }, - AccessType: &csi.VolumeCapability_Block{ - Block: &csi.VolumeCapability_BlockVolume{}, - }, - }, - { - AccessMode: &csi.VolumeCapability_AccessMode{ - Mode: csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER, - }, - AccessType: &csi.VolumeCapability_Mount{ - Mount: &csi.VolumeCapability_MountVolume{ - FsType: "ext4", - MountFlags: []string{"rw"}, - }, - }, - }, - } - - Ω(utils.AreVolumeCapabilitiesCompatible(a, b)).Should(BeTrue()) - aMountAT.Mount.MountFlags[0] = "ro" - Ω(utils.AreVolumeCapabilitiesCompatible(a, b)).Should(BeFalse()) - a[0].AccessType = &csi.VolumeCapability_Block{ - Block: &csi.VolumeCapability_BlockVolume{}, - } - Ω(utils.AreVolumeCapabilitiesCompatible(a, b)).Should(BeTrue()) - }) -}) From 351c1583c469c96b475708267b52b3dfdb6ecdc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Pab=C3=B3n?= Date: Sun, 4 Mar 2018 00:33:59 -0500 Subject: [PATCH 2/2] Update golang mock driver Depends on #54 --- driver/driver.mock.go | 272 +++++++++++++++++++++++------------------- 1 file changed, 150 insertions(+), 122 deletions(-) diff --git a/driver/driver.mock.go b/driver/driver.mock.go index e9e14061..ed14e019 100644 --- a/driver/driver.mock.go +++ b/driver/driver.mock.go @@ -1,261 +1,289 @@ -// Automatically generated by MockGen. DO NOT EDIT! -// Source: github.com/container-storage-interface/spec/lib/go/csi/v0 (interfaces: IdentityServer,ControllerServer,NodeServer) +// Code generated by MockGen. DO NOT EDIT. +// Source: github.com/container-storage-interface/spec/lib/go/csi (interfaces: IdentityServer,ControllerServer,NodeServer) +// Package driver is a generated GoMock package. package driver import ( context "context" - - v0 "github.com/container-storage-interface/spec/lib/go/csi/v0" + csi "github.com/container-storage-interface/spec/lib/go/csi" gomock "github.com/golang/mock/gomock" + reflect "reflect" ) -// Mock of IdentityServer interface +// MockIdentityServer is a mock of IdentityServer interface type MockIdentityServer struct { ctrl *gomock.Controller - recorder *_MockIdentityServerRecorder + recorder *MockIdentityServerMockRecorder } -// Recorder for MockIdentityServer (not exported) -type _MockIdentityServerRecorder struct { +// MockIdentityServerMockRecorder is the mock recorder for MockIdentityServer +type MockIdentityServerMockRecorder struct { mock *MockIdentityServer } +// NewMockIdentityServer creates a new mock instance func NewMockIdentityServer(ctrl *gomock.Controller) *MockIdentityServer { mock := &MockIdentityServer{ctrl: ctrl} - mock.recorder = &_MockIdentityServerRecorder{mock} + mock.recorder = &MockIdentityServerMockRecorder{mock} return mock } -func (_m *MockIdentityServer) EXPECT() *_MockIdentityServerRecorder { - return _m.recorder -} - -func (_m *MockIdentityServer) GetPluginCapabilities(_param0 context.Context, _param1 *v0.GetPluginCapabilitiesRequest) (*v0.GetPluginCapabilitiesResponse, error) { - ret := _m.ctrl.Call(_m, "GetPluginCapabilities", _param0, _param1) - ret0, _ := ret[0].(*v0.GetPluginCapabilitiesResponse) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -func (_mr *_MockIdentityServerRecorder) GetPluginCapabilities(arg0, arg1 interface{}) *gomock.Call { - return _mr.mock.ctrl.RecordCall(_mr.mock, "GetPluginCapabilities", arg0, arg1) +// EXPECT returns an object that allows the caller to indicate expected use +func (m *MockIdentityServer) EXPECT() *MockIdentityServerMockRecorder { + return m.recorder } -func (_m *MockIdentityServer) GetPluginInfo(_param0 context.Context, _param1 *v0.GetPluginInfoRequest) (*v0.GetPluginInfoResponse, error) { - ret := _m.ctrl.Call(_m, "GetPluginInfo", _param0, _param1) - ret0, _ := ret[0].(*v0.GetPluginInfoResponse) +// GetPluginInfo mocks base method +func (m *MockIdentityServer) GetPluginInfo(arg0 context.Context, arg1 *csi.GetPluginInfoRequest) (*csi.GetPluginInfoResponse, error) { + ret := m.ctrl.Call(m, "GetPluginInfo", arg0, arg1) + ret0, _ := ret[0].(*csi.GetPluginInfoResponse) ret1, _ := ret[1].(error) return ret0, ret1 } -func (_mr *_MockIdentityServerRecorder) GetPluginInfo(arg0, arg1 interface{}) *gomock.Call { - return _mr.mock.ctrl.RecordCall(_mr.mock, "GetPluginInfo", arg0, arg1) +// GetPluginInfo indicates an expected call of GetPluginInfo +func (mr *MockIdentityServerMockRecorder) GetPluginInfo(arg0, arg1 interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPluginInfo", reflect.TypeOf((*MockIdentityServer)(nil).GetPluginInfo), arg0, arg1) } -func (_m *MockIdentityServer) Probe(_param0 context.Context, _param1 *v0.ProbeRequest) (*v0.ProbeResponse, error) { - ret := _m.ctrl.Call(_m, "Probe", _param0, _param1) - ret0, _ := ret[0].(*v0.ProbeResponse) +// GetSupportedVersions mocks base method +func (m *MockIdentityServer) GetSupportedVersions(arg0 context.Context, arg1 *csi.GetSupportedVersionsRequest) (*csi.GetSupportedVersionsResponse, error) { + ret := m.ctrl.Call(m, "GetSupportedVersions", arg0, arg1) + ret0, _ := ret[0].(*csi.GetSupportedVersionsResponse) ret1, _ := ret[1].(error) return ret0, ret1 } -func (_mr *_MockIdentityServerRecorder) Probe(arg0, arg1 interface{}) *gomock.Call { - return _mr.mock.ctrl.RecordCall(_mr.mock, "Probe", arg0, arg1) +// GetSupportedVersions indicates an expected call of GetSupportedVersions +func (mr *MockIdentityServerMockRecorder) GetSupportedVersions(arg0, arg1 interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSupportedVersions", reflect.TypeOf((*MockIdentityServer)(nil).GetSupportedVersions), arg0, arg1) } -// Mock of ControllerServer interface +// MockControllerServer is a mock of ControllerServer interface type MockControllerServer struct { ctrl *gomock.Controller - recorder *_MockControllerServerRecorder + recorder *MockControllerServerMockRecorder } -// Recorder for MockControllerServer (not exported) -type _MockControllerServerRecorder struct { +// MockControllerServerMockRecorder is the mock recorder for MockControllerServer +type MockControllerServerMockRecorder struct { mock *MockControllerServer } +// NewMockControllerServer creates a new mock instance func NewMockControllerServer(ctrl *gomock.Controller) *MockControllerServer { mock := &MockControllerServer{ctrl: ctrl} - mock.recorder = &_MockControllerServerRecorder{mock} + mock.recorder = &MockControllerServerMockRecorder{mock} return mock } -func (_m *MockControllerServer) EXPECT() *_MockControllerServerRecorder { - return _m.recorder +// EXPECT returns an object that allows the caller to indicate expected use +func (m *MockControllerServer) EXPECT() *MockControllerServerMockRecorder { + return m.recorder } -func (_m *MockControllerServer) ControllerGetCapabilities(_param0 context.Context, _param1 *v0.ControllerGetCapabilitiesRequest) (*v0.ControllerGetCapabilitiesResponse, error) { - ret := _m.ctrl.Call(_m, "ControllerGetCapabilities", _param0, _param1) - ret0, _ := ret[0].(*v0.ControllerGetCapabilitiesResponse) +// ControllerGetCapabilities mocks base method +func (m *MockControllerServer) ControllerGetCapabilities(arg0 context.Context, arg1 *csi.ControllerGetCapabilitiesRequest) (*csi.ControllerGetCapabilitiesResponse, error) { + ret := m.ctrl.Call(m, "ControllerGetCapabilities", arg0, arg1) + ret0, _ := ret[0].(*csi.ControllerGetCapabilitiesResponse) ret1, _ := ret[1].(error) return ret0, ret1 } -func (_mr *_MockControllerServerRecorder) ControllerGetCapabilities(arg0, arg1 interface{}) *gomock.Call { - return _mr.mock.ctrl.RecordCall(_mr.mock, "ControllerGetCapabilities", arg0, arg1) +// ControllerGetCapabilities indicates an expected call of ControllerGetCapabilities +func (mr *MockControllerServerMockRecorder) ControllerGetCapabilities(arg0, arg1 interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ControllerGetCapabilities", reflect.TypeOf((*MockControllerServer)(nil).ControllerGetCapabilities), arg0, arg1) } -func (_m *MockControllerServer) ControllerPublishVolume(_param0 context.Context, _param1 *v0.ControllerPublishVolumeRequest) (*v0.ControllerPublishVolumeResponse, error) { - ret := _m.ctrl.Call(_m, "ControllerPublishVolume", _param0, _param1) - ret0, _ := ret[0].(*v0.ControllerPublishVolumeResponse) +// ControllerProbe mocks base method +func (m *MockControllerServer) ControllerProbe(arg0 context.Context, arg1 *csi.ControllerProbeRequest) (*csi.ControllerProbeResponse, error) { + ret := m.ctrl.Call(m, "ControllerProbe", arg0, arg1) + ret0, _ := ret[0].(*csi.ControllerProbeResponse) ret1, _ := ret[1].(error) return ret0, ret1 } -func (_mr *_MockControllerServerRecorder) ControllerPublishVolume(arg0, arg1 interface{}) *gomock.Call { - return _mr.mock.ctrl.RecordCall(_mr.mock, "ControllerPublishVolume", arg0, arg1) +// ControllerProbe indicates an expected call of ControllerProbe +func (mr *MockControllerServerMockRecorder) ControllerProbe(arg0, arg1 interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ControllerProbe", reflect.TypeOf((*MockControllerServer)(nil).ControllerProbe), arg0, arg1) } -func (_m *MockControllerServer) ControllerUnpublishVolume(_param0 context.Context, _param1 *v0.ControllerUnpublishVolumeRequest) (*v0.ControllerUnpublishVolumeResponse, error) { - ret := _m.ctrl.Call(_m, "ControllerUnpublishVolume", _param0, _param1) - ret0, _ := ret[0].(*v0.ControllerUnpublishVolumeResponse) +// ControllerPublishVolume mocks base method +func (m *MockControllerServer) ControllerPublishVolume(arg0 context.Context, arg1 *csi.ControllerPublishVolumeRequest) (*csi.ControllerPublishVolumeResponse, error) { + ret := m.ctrl.Call(m, "ControllerPublishVolume", arg0, arg1) + ret0, _ := ret[0].(*csi.ControllerPublishVolumeResponse) ret1, _ := ret[1].(error) return ret0, ret1 } -func (_mr *_MockControllerServerRecorder) ControllerUnpublishVolume(arg0, arg1 interface{}) *gomock.Call { - return _mr.mock.ctrl.RecordCall(_mr.mock, "ControllerUnpublishVolume", arg0, arg1) +// ControllerPublishVolume indicates an expected call of ControllerPublishVolume +func (mr *MockControllerServerMockRecorder) ControllerPublishVolume(arg0, arg1 interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ControllerPublishVolume", reflect.TypeOf((*MockControllerServer)(nil).ControllerPublishVolume), arg0, arg1) } -func (_m *MockControllerServer) CreateVolume(_param0 context.Context, _param1 *v0.CreateVolumeRequest) (*v0.CreateVolumeResponse, error) { - ret := _m.ctrl.Call(_m, "CreateVolume", _param0, _param1) - ret0, _ := ret[0].(*v0.CreateVolumeResponse) +// ControllerUnpublishVolume mocks base method +func (m *MockControllerServer) ControllerUnpublishVolume(arg0 context.Context, arg1 *csi.ControllerUnpublishVolumeRequest) (*csi.ControllerUnpublishVolumeResponse, error) { + ret := m.ctrl.Call(m, "ControllerUnpublishVolume", arg0, arg1) + ret0, _ := ret[0].(*csi.ControllerUnpublishVolumeResponse) ret1, _ := ret[1].(error) return ret0, ret1 } -func (_mr *_MockControllerServerRecorder) CreateVolume(arg0, arg1 interface{}) *gomock.Call { - return _mr.mock.ctrl.RecordCall(_mr.mock, "CreateVolume", arg0, arg1) +// ControllerUnpublishVolume indicates an expected call of ControllerUnpublishVolume +func (mr *MockControllerServerMockRecorder) ControllerUnpublishVolume(arg0, arg1 interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ControllerUnpublishVolume", reflect.TypeOf((*MockControllerServer)(nil).ControllerUnpublishVolume), arg0, arg1) } -func (_m *MockControllerServer) DeleteVolume(_param0 context.Context, _param1 *v0.DeleteVolumeRequest) (*v0.DeleteVolumeResponse, error) { - ret := _m.ctrl.Call(_m, "DeleteVolume", _param0, _param1) - ret0, _ := ret[0].(*v0.DeleteVolumeResponse) +// CreateVolume mocks base method +func (m *MockControllerServer) CreateVolume(arg0 context.Context, arg1 *csi.CreateVolumeRequest) (*csi.CreateVolumeResponse, error) { + ret := m.ctrl.Call(m, "CreateVolume", arg0, arg1) + ret0, _ := ret[0].(*csi.CreateVolumeResponse) ret1, _ := ret[1].(error) return ret0, ret1 } -func (_mr *_MockControllerServerRecorder) DeleteVolume(arg0, arg1 interface{}) *gomock.Call { - return _mr.mock.ctrl.RecordCall(_mr.mock, "DeleteVolume", arg0, arg1) +// CreateVolume indicates an expected call of CreateVolume +func (mr *MockControllerServerMockRecorder) CreateVolume(arg0, arg1 interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateVolume", reflect.TypeOf((*MockControllerServer)(nil).CreateVolume), arg0, arg1) } -func (_m *MockControllerServer) GetCapacity(_param0 context.Context, _param1 *v0.GetCapacityRequest) (*v0.GetCapacityResponse, error) { - ret := _m.ctrl.Call(_m, "GetCapacity", _param0, _param1) - ret0, _ := ret[0].(*v0.GetCapacityResponse) +// DeleteVolume mocks base method +func (m *MockControllerServer) DeleteVolume(arg0 context.Context, arg1 *csi.DeleteVolumeRequest) (*csi.DeleteVolumeResponse, error) { + ret := m.ctrl.Call(m, "DeleteVolume", arg0, arg1) + ret0, _ := ret[0].(*csi.DeleteVolumeResponse) ret1, _ := ret[1].(error) return ret0, ret1 } -func (_mr *_MockControllerServerRecorder) GetCapacity(arg0, arg1 interface{}) *gomock.Call { - return _mr.mock.ctrl.RecordCall(_mr.mock, "GetCapacity", arg0, arg1) +// DeleteVolume indicates an expected call of DeleteVolume +func (mr *MockControllerServerMockRecorder) DeleteVolume(arg0, arg1 interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteVolume", reflect.TypeOf((*MockControllerServer)(nil).DeleteVolume), arg0, arg1) } -func (_m *MockControllerServer) ListVolumes(_param0 context.Context, _param1 *v0.ListVolumesRequest) (*v0.ListVolumesResponse, error) { - ret := _m.ctrl.Call(_m, "ListVolumes", _param0, _param1) - ret0, _ := ret[0].(*v0.ListVolumesResponse) +// GetCapacity mocks base method +func (m *MockControllerServer) GetCapacity(arg0 context.Context, arg1 *csi.GetCapacityRequest) (*csi.GetCapacityResponse, error) { + ret := m.ctrl.Call(m, "GetCapacity", arg0, arg1) + ret0, _ := ret[0].(*csi.GetCapacityResponse) ret1, _ := ret[1].(error) return ret0, ret1 } -func (_mr *_MockControllerServerRecorder) ListVolumes(arg0, arg1 interface{}) *gomock.Call { - return _mr.mock.ctrl.RecordCall(_mr.mock, "ListVolumes", arg0, arg1) +// GetCapacity indicates an expected call of GetCapacity +func (mr *MockControllerServerMockRecorder) GetCapacity(arg0, arg1 interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCapacity", reflect.TypeOf((*MockControllerServer)(nil).GetCapacity), arg0, arg1) } -func (_m *MockControllerServer) ValidateVolumeCapabilities(_param0 context.Context, _param1 *v0.ValidateVolumeCapabilitiesRequest) (*v0.ValidateVolumeCapabilitiesResponse, error) { - ret := _m.ctrl.Call(_m, "ValidateVolumeCapabilities", _param0, _param1) - ret0, _ := ret[0].(*v0.ValidateVolumeCapabilitiesResponse) +// ListVolumes mocks base method +func (m *MockControllerServer) ListVolumes(arg0 context.Context, arg1 *csi.ListVolumesRequest) (*csi.ListVolumesResponse, error) { + ret := m.ctrl.Call(m, "ListVolumes", arg0, arg1) + ret0, _ := ret[0].(*csi.ListVolumesResponse) ret1, _ := ret[1].(error) return ret0, ret1 } -func (_mr *_MockControllerServerRecorder) ValidateVolumeCapabilities(arg0, arg1 interface{}) *gomock.Call { - return _mr.mock.ctrl.RecordCall(_mr.mock, "ValidateVolumeCapabilities", arg0, arg1) +// ListVolumes indicates an expected call of ListVolumes +func (mr *MockControllerServerMockRecorder) ListVolumes(arg0, arg1 interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListVolumes", reflect.TypeOf((*MockControllerServer)(nil).ListVolumes), arg0, arg1) } -// Mock of NodeServer interface +// ValidateVolumeCapabilities mocks base method +func (m *MockControllerServer) ValidateVolumeCapabilities(arg0 context.Context, arg1 *csi.ValidateVolumeCapabilitiesRequest) (*csi.ValidateVolumeCapabilitiesResponse, error) { + ret := m.ctrl.Call(m, "ValidateVolumeCapabilities", arg0, arg1) + ret0, _ := ret[0].(*csi.ValidateVolumeCapabilitiesResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ValidateVolumeCapabilities indicates an expected call of ValidateVolumeCapabilities +func (mr *MockControllerServerMockRecorder) ValidateVolumeCapabilities(arg0, arg1 interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ValidateVolumeCapabilities", reflect.TypeOf((*MockControllerServer)(nil).ValidateVolumeCapabilities), arg0, arg1) +} + +// MockNodeServer is a mock of NodeServer interface type MockNodeServer struct { ctrl *gomock.Controller - recorder *_MockNodeServerRecorder + recorder *MockNodeServerMockRecorder } -// Recorder for MockNodeServer (not exported) -type _MockNodeServerRecorder struct { +// MockNodeServerMockRecorder is the mock recorder for MockNodeServer +type MockNodeServerMockRecorder struct { mock *MockNodeServer } +// NewMockNodeServer creates a new mock instance func NewMockNodeServer(ctrl *gomock.Controller) *MockNodeServer { mock := &MockNodeServer{ctrl: ctrl} - mock.recorder = &_MockNodeServerRecorder{mock} + mock.recorder = &MockNodeServerMockRecorder{mock} return mock } -func (_m *MockNodeServer) EXPECT() *_MockNodeServerRecorder { - return _m.recorder -} - -func (_m *MockNodeServer) NodeGetCapabilities(_param0 context.Context, _param1 *v0.NodeGetCapabilitiesRequest) (*v0.NodeGetCapabilitiesResponse, error) { - ret := _m.ctrl.Call(_m, "NodeGetCapabilities", _param0, _param1) - ret0, _ := ret[0].(*v0.NodeGetCapabilitiesResponse) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -func (_mr *_MockNodeServerRecorder) NodeGetCapabilities(arg0, arg1 interface{}) *gomock.Call { - return _mr.mock.ctrl.RecordCall(_mr.mock, "NodeGetCapabilities", arg0, arg1) +// EXPECT returns an object that allows the caller to indicate expected use +func (m *MockNodeServer) EXPECT() *MockNodeServerMockRecorder { + return m.recorder } -func (_m *MockNodeServer) NodeGetId(_param0 context.Context, _param1 *v0.NodeGetIdRequest) (*v0.NodeGetIdResponse, error) { - ret := _m.ctrl.Call(_m, "NodeGetId", _param0, _param1) - ret0, _ := ret[0].(*v0.NodeGetIdResponse) +// GetNodeID mocks base method +func (m *MockNodeServer) GetNodeID(arg0 context.Context, arg1 *csi.GetNodeIDRequest) (*csi.GetNodeIDResponse, error) { + ret := m.ctrl.Call(m, "GetNodeID", arg0, arg1) + ret0, _ := ret[0].(*csi.GetNodeIDResponse) ret1, _ := ret[1].(error) return ret0, ret1 } -func (_mr *_MockNodeServerRecorder) NodeGetId(arg0, arg1 interface{}) *gomock.Call { - return _mr.mock.ctrl.RecordCall(_mr.mock, "NodeGetId", arg0, arg1) +// GetNodeID indicates an expected call of GetNodeID +func (mr *MockNodeServerMockRecorder) GetNodeID(arg0, arg1 interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetNodeID", reflect.TypeOf((*MockNodeServer)(nil).GetNodeID), arg0, arg1) } -func (_m *MockNodeServer) NodePublishVolume(_param0 context.Context, _param1 *v0.NodePublishVolumeRequest) (*v0.NodePublishVolumeResponse, error) { - ret := _m.ctrl.Call(_m, "NodePublishVolume", _param0, _param1) - ret0, _ := ret[0].(*v0.NodePublishVolumeResponse) +// NodeGetCapabilities mocks base method +func (m *MockNodeServer) NodeGetCapabilities(arg0 context.Context, arg1 *csi.NodeGetCapabilitiesRequest) (*csi.NodeGetCapabilitiesResponse, error) { + ret := m.ctrl.Call(m, "NodeGetCapabilities", arg0, arg1) + ret0, _ := ret[0].(*csi.NodeGetCapabilitiesResponse) ret1, _ := ret[1].(error) return ret0, ret1 } -func (_mr *_MockNodeServerRecorder) NodePublishVolume(arg0, arg1 interface{}) *gomock.Call { - return _mr.mock.ctrl.RecordCall(_mr.mock, "NodePublishVolume", arg0, arg1) +// NodeGetCapabilities indicates an expected call of NodeGetCapabilities +func (mr *MockNodeServerMockRecorder) NodeGetCapabilities(arg0, arg1 interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NodeGetCapabilities", reflect.TypeOf((*MockNodeServer)(nil).NodeGetCapabilities), arg0, arg1) } -func (_m *MockNodeServer) NodeStageVolume(_param0 context.Context, _param1 *v0.NodeStageVolumeRequest) (*v0.NodeStageVolumeResponse, error) { - ret := _m.ctrl.Call(_m, "NodeStageVolume", _param0, _param1) - ret0, _ := ret[0].(*v0.NodeStageVolumeResponse) +// NodeProbe mocks base method +func (m *MockNodeServer) NodeProbe(arg0 context.Context, arg1 *csi.NodeProbeRequest) (*csi.NodeProbeResponse, error) { + ret := m.ctrl.Call(m, "NodeProbe", arg0, arg1) + ret0, _ := ret[0].(*csi.NodeProbeResponse) ret1, _ := ret[1].(error) return ret0, ret1 } -func (_mr *_MockNodeServerRecorder) NodeStageVolume(arg0, arg1 interface{}) *gomock.Call { - return _mr.mock.ctrl.RecordCall(_mr.mock, "NodeStageVolume", arg0, arg1) +// NodeProbe indicates an expected call of NodeProbe +func (mr *MockNodeServerMockRecorder) NodeProbe(arg0, arg1 interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NodeProbe", reflect.TypeOf((*MockNodeServer)(nil).NodeProbe), arg0, arg1) } -func (_m *MockNodeServer) NodeUnpublishVolume(_param0 context.Context, _param1 *v0.NodeUnpublishVolumeRequest) (*v0.NodeUnpublishVolumeResponse, error) { - ret := _m.ctrl.Call(_m, "NodeUnpublishVolume", _param0, _param1) - ret0, _ := ret[0].(*v0.NodeUnpublishVolumeResponse) +// NodePublishVolume mocks base method +func (m *MockNodeServer) NodePublishVolume(arg0 context.Context, arg1 *csi.NodePublishVolumeRequest) (*csi.NodePublishVolumeResponse, error) { + ret := m.ctrl.Call(m, "NodePublishVolume", arg0, arg1) + ret0, _ := ret[0].(*csi.NodePublishVolumeResponse) ret1, _ := ret[1].(error) return ret0, ret1 } -func (_mr *_MockNodeServerRecorder) NodeUnpublishVolume(arg0, arg1 interface{}) *gomock.Call { - return _mr.mock.ctrl.RecordCall(_mr.mock, "NodeUnpublishVolume", arg0, arg1) +// NodePublishVolume indicates an expected call of NodePublishVolume +func (mr *MockNodeServerMockRecorder) NodePublishVolume(arg0, arg1 interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NodePublishVolume", reflect.TypeOf((*MockNodeServer)(nil).NodePublishVolume), arg0, arg1) } -func (_m *MockNodeServer) NodeUnstageVolume(_param0 context.Context, _param1 *v0.NodeUnstageVolumeRequest) (*v0.NodeUnstageVolumeResponse, error) { - ret := _m.ctrl.Call(_m, "NodeUnstageVolume", _param0, _param1) - ret0, _ := ret[0].(*v0.NodeUnstageVolumeResponse) +// NodeUnpublishVolume mocks base method +func (m *MockNodeServer) NodeUnpublishVolume(arg0 context.Context, arg1 *csi.NodeUnpublishVolumeRequest) (*csi.NodeUnpublishVolumeResponse, error) { + ret := m.ctrl.Call(m, "NodeUnpublishVolume", arg0, arg1) + ret0, _ := ret[0].(*csi.NodeUnpublishVolumeResponse) ret1, _ := ret[1].(error) return ret0, ret1 } -func (_mr *_MockNodeServerRecorder) NodeUnstageVolume(arg0, arg1 interface{}) *gomock.Call { - return _mr.mock.ctrl.RecordCall(_mr.mock, "NodeUnstageVolume", arg0, arg1) +// NodeUnpublishVolume indicates an expected call of NodeUnpublishVolume +func (mr *MockNodeServerMockRecorder) NodeUnpublishVolume(arg0, arg1 interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NodeUnpublishVolume", reflect.TypeOf((*MockNodeServer)(nil).NodeUnpublishVolume), arg0, arg1) }