diff --git a/.travis.yml b/.travis.yml index 8ce3dbbedf..e536ee5983 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,9 @@ services: matrix: include: - go: 1.x +install: + - go get -u github.com/golang/dep/cmd/dep + - dep ensure -vendor-only script: - go fmt $(go list ./... | grep -v vendor) | wc -l | grep 0 - go vet $(go list ./... | grep -v vendor) diff --git a/Gopkg.lock b/Gopkg.lock index 166421127d..afd6d63622 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -40,10 +40,17 @@ packages = ["lru"] revision = "66deaeb636dff1ac7d938ce666d090556056a4b0" +[[projects]] + name = "github.com/golang/mock" + packages = ["gomock"] + revision = "13f360950a79f5864a972c786a10a50e44b69541" + version = "v1.0.0" + [[projects]] name = "github.com/golang/protobuf" packages = [ "proto", + "protoc-gen-go/descriptor", "ptypes", "ptypes/any", "ptypes/duration", @@ -81,7 +88,7 @@ ".", "diskcache" ] - revision = "2bcd89a1743fd4b373f7370ce8ddc14dfbd18229" + revision = "9cad4c3443a7200dd6400aef47183728de563a38" [[projects]] branch = "master" @@ -116,6 +123,15 @@ revision = "59fac5042749a5afb9af70e813da1dd5474f0167" version = "1.0.1" +[[projects]] + branch = "master" + name = "github.com/kubernetes-csi/csi-test" + packages = [ + "driver", + "utils" + ] + revision = "d2bc8013ab3c236876f5fd7f7133335c76e6327c" + [[projects]] branch = "master" name = "github.com/kubernetes-incubator/external-storage" @@ -124,13 +140,13 @@ "lib/leaderelection", "lib/leaderelection/resourcelock" ] - revision = "1cc9d42bff12a188801f6e903d0a19bd517452a1" + revision = "06f19d7b39f17b83d3db6d52f826872c22e3273d" [[projects]] name = "github.com/modern-go/concurrent" packages = ["."] - revision = "938152ca6a933f501bb238954eebd3cbcbf489ff" - version = "1.0.2" + revision = "bacd9c7ef1dd9b15be4a9909b8ac7a4e313eec94" + version = "1.0.3" [[projects]] name = "github.com/modern-go/reflect2" @@ -166,7 +182,7 @@ branch = "master" name = "golang.org/x/crypto" packages = ["ssh/terminal"] - revision = "91a49db82a88618983a78a06c1cbd4e00ab749ab" + revision = "182114d582623c1caa54f73de9c7224e23a48487" [[projects]] branch = "master" @@ -180,7 +196,7 @@ "lex/httplex", "trace" ] - revision = "22ae77b79946ea320088417e4d50825671d82d57" + revision = "ae89d30ce0c63142b652837da33d782e2b0a9b25" [[projects]] branch = "master" @@ -189,7 +205,7 @@ "unix", "windows" ] - revision = "dd2ff4accc098aceecb86b36eaa7829b2a17b1c9" + revision = "c28acc882ebcbfbe8ce9f0f14b9ac26ee138dd51" [[projects]] name = "golang.org/x/text" @@ -216,7 +232,7 @@ branch = "master" name = "google.golang.org/genproto" packages = ["googleapis/rpc/status"] - revision = "2c5e7ac708aaa719366570dd82bda44541ca2a63" + revision = "df60624c1e9b9d2973e889c7a1cff73155da81c4" [[projects]] name = "google.golang.org/grpc" @@ -237,6 +253,8 @@ "metadata", "naming", "peer", + "reflection", + "reflection/grpc_reflection_v1alpha", "resolver", "resolver/dns", "resolver/passthrough", @@ -417,12 +435,12 @@ "pkg/util/goroutinemap/exponentialbackoff", "pkg/util/version" ] - revision = "d2835416544f298c919e2ead3be3d0864b52323b" - version = "v1.9.3" + revision = "bee2d1505c4fe820744d26d41ecd3fdd4a3d6546" + version = "v1.9.4" [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "dcef48d0f996b9ad79555efdea93b3c26dbb1b128eafa16337c677022a4ffd4c" + inputs-digest = "ca14bfaf19c3b8343f0892f1e77f6b9d856100b600186a9a3fde0f2658492aa3" solver-name = "gps-cdcl" solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml index 73f75e9e7c..8e58a18874 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -28,18 +28,10 @@ branch = "master" name = "github.com/golang/glog" -[[constraint]] - branch = "master" - name = "github.com/golang/protobuf" - [[constraint]] branch = "master" name = "github.com/kubernetes-incubator/external-storage" -[[constraint]] - branch = "master" - name = "golang.org/x/net" - [[constraint]] name = "google.golang.org/grpc" version = "1.9.2" @@ -54,4 +46,4 @@ [[constraint]] name = "k8s.io/api" - version = "kubernetes-1.10.0-beta.1" + version = "kubernetes-1.10.0-beta.1" \ No newline at end of file diff --git a/pkg/controller/controller_test.go b/pkg/controller/controller_test.go new file mode 100644 index 0000000000..5272a282db --- /dev/null +++ b/pkg/controller/controller_test.go @@ -0,0 +1,262 @@ +/* +Copyright 2018 The Kubernetes Authors. + +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. +*/ + +package controller + +import ( + "fmt" + "testing" + "time" + + csi "github.com/container-storage-interface/spec/lib/go/csi/v0" + "github.com/golang/mock/gomock" + "github.com/kubernetes-csi/csi-test/driver" + "google.golang.org/grpc" +) + +const ( + timeout = 10 * time.Second +) + +type csiConnection struct { + conn *grpc.ClientConn +} + +func New(address string, timeout time.Duration) (csiConnection, error) { + conn, err := connect(address, timeout) + if err != nil { + return csiConnection{}, err + } + return csiConnection{ + conn: conn, + }, nil +} + +func createMockServer(t *testing.T) (*gomock.Controller, + *driver.MockCSIDriver, + *driver.MockIdentityServer, + *driver.MockControllerServer, + csiConnection, error) { + // Start the mock server + mockController := gomock.NewController(t) + controllerServer := driver.NewMockControllerServer(mockController) + identityServer := driver.NewMockIdentityServer(mockController) + drv := driver.NewMockCSIDriver(&driver.MockCSIDriverServers{ + Identity: identityServer, + Controller: controllerServer, + }) + drv.Start() + + // Create a client connection to it + addr := drv.Address() + csiConn, err := New(addr, timeout) + if err != nil { + return nil, nil, nil, nil, csiConnection{}, err + } + + return mockController, drv, identityServer, controllerServer, csiConn, nil +} + +func TestSupportsControllerCreateVolume(t *testing.T) { + + tests := []struct { + name string + output *csi.ControllerGetCapabilitiesResponse + injectError bool + expectError bool + expectResult bool + }{ + { + name: "controller create", + output: &csi.ControllerGetCapabilitiesResponse{ + Capabilities: []*csi.ControllerServiceCapability{ + { + Type: &csi.ControllerServiceCapability_Rpc{ + Rpc: &csi.ControllerServiceCapability_RPC{ + Type: csi.ControllerServiceCapability_RPC_CREATE_DELETE_VOLUME, + }, + }, + }, + { + Type: &csi.ControllerServiceCapability_Rpc{ + Rpc: &csi.ControllerServiceCapability_RPC{ + Type: csi.ControllerServiceCapability_RPC_PUBLISH_UNPUBLISH_VOLUME, + }, + }, + }, + }, + }, + expectError: false, + expectResult: true, + }, + { + name: "no controller create", + output: &csi.ControllerGetCapabilitiesResponse{ + Capabilities: []*csi.ControllerServiceCapability{ + { + Type: &csi.ControllerServiceCapability_Rpc{ + Rpc: &csi.ControllerServiceCapability_RPC{ + Type: csi.ControllerServiceCapability_RPC_PUBLISH_UNPUBLISH_VOLUME, + }, + }, + }, + }, + }, + expectError: false, + expectResult: false, + }, + { + name: "gRPC error", + output: nil, + injectError: true, + expectError: true, + expectResult: false, + }, + { + name: "empty capability", + output: &csi.ControllerGetCapabilitiesResponse{ + Capabilities: []*csi.ControllerServiceCapability{ + { + Type: nil, + }, + }, + }, + expectError: false, + expectResult: false, + }, + { + name: "no capabilities", + output: &csi.ControllerGetCapabilitiesResponse{ + Capabilities: []*csi.ControllerServiceCapability{}, + }, + expectError: false, + expectResult: false, + }, + } + mockController, driver, _, controllerServer, csiConn, err := createMockServer(t) + if err != nil { + t.Fatal(err) + } + defer mockController.Finish() + defer driver.Stop() + for _, test := range tests { + + in := &csi.ControllerGetCapabilitiesRequest{} + + out := test.output + var injectedErr error + if test.injectError { + injectedErr = fmt.Errorf("mock error") + } + + controllerServer.EXPECT().ControllerGetCapabilities(gomock.Any(), in).Return(out, injectedErr).Times(1) + ok, err := supportsControllerCreateVolume(csiConn.conn, timeout) + if err != nil && !test.expectError { + t.Errorf("test fail with error: %v\n", err) + } + if err == nil && test.expectResult != ok { + t.Errorf("test fail expected result %t but got %t\n", test.expectResult, ok) + } + } +} + +func TestSupportsPluginControllerService(t *testing.T) { + + tests := []struct { + name string + output *csi.GetPluginCapabilitiesResponse + injectError bool + expectError bool + expectResult bool + }{ + { + name: "controller capability", + output: &csi.GetPluginCapabilitiesResponse{ + Capabilities: []*csi.PluginCapability{ + { + Type: &csi.PluginCapability_Service_{ + Service: &csi.PluginCapability_Service{ + Type: csi.PluginCapability_Service_CONTROLLER_SERVICE, + }, + }, + }, + }, + }, + expectError: false, + expectResult: true, + }, + { + name: "no controller capability", + output: &csi.GetPluginCapabilitiesResponse{ + Capabilities: []*csi.PluginCapability{ + { + Type: &csi.PluginCapability_Service_{ + Service: &csi.PluginCapability_Service{ + Type: csi.PluginCapability_Service_UNKNOWN, + }, + }, + }, + }, + }, + expectError: false, + expectResult: false, + }, + { + name: "gRPC error", + output: nil, + injectError: true, + expectError: true, + expectResult: false, + }, + { + name: "empty capability", + output: &csi.GetPluginCapabilitiesResponse{ + Capabilities: []*csi.PluginCapability{ + { + Type: nil, + }, + }, + }, + expectError: false, + expectResult: false, + }, + } + mockController, driver, identityServer, _, csiConn, err := createMockServer(t) + if err != nil { + t.Fatal(err) + } + defer mockController.Finish() + defer driver.Stop() + for _, test := range tests { + + in := &csi.GetPluginCapabilitiesRequest{} + + out := test.output + var injectedErr error + if test.injectError { + injectedErr = fmt.Errorf("mock error") + } + + identityServer.EXPECT().GetPluginCapabilities(gomock.Any(), in).Return(out, injectedErr).Times(1) + ok, err := supportsPluginControllerService(csiConn.conn, timeout) + if err != nil && !test.expectError { + t.Errorf("test fail with error: %v\n", err) + } + if err == nil && test.expectResult != ok { + t.Errorf("test fail expected result %t but got %t\n", test.expectResult, ok) + } + } +}