From bf9b84233eb595ee23ee0300eba8d3bc60e3a015 Mon Sep 17 00:00:00 2001 From: Serguei Bezverkhi Date: Wed, 15 Aug 2018 08:30:26 -0400 Subject: [PATCH] Code changes Signed-off-by: Serguei Bezverkhi --- .travis.yml | 8 ++- Gopkg.lock | 103 +++++++++++++++++++++++++++++++------- Gopkg.toml | 10 ++-- cmd/livenessprobe_test.go | 95 +++++++++++++++++++++++++++++++++++ cmd/main.go | 29 +++++++---- hack/e2e-livenessprobe.sh | 58 +++++++++++++++++++++ 6 files changed, 270 insertions(+), 33 deletions(-) create mode 100644 cmd/livenessprobe_test.go create mode 100755 hack/e2e-livenessprobe.sh diff --git a/.travis.yml b/.travis.yml index ee934fec..2fe3721f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,12 @@ language: go +services: + - docker + +# Needed for e2e tests sudo: true -go: 1.9.x + +go: 1.10.x go_import_path: github.com/kubernetes-csi/livenessprobe install: - go get -u github.com/golang/dep/cmd/dep @@ -11,6 +16,7 @@ script: - go fmt $(go list ./... | grep -v vendor) | wc -l | grep 0 - go vet $(go list ./... | grep -v vendor) - go test $(go list ./... | grep -v vendor) +- ./hack/e2e-livenessprobe.sh after_success: - if [ "${TRAVIS_BRANCH}" == "master" ] && [ "${TRAVIS_PULL_REQUEST}" == "false" ]; then sudo make livenessprobe-container; diff --git a/Gopkg.lock b/Gopkg.lock index 6ab30844..de9a2c79 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -4,8 +4,8 @@ [[projects]] name = "github.com/container-storage-interface/spec" packages = ["lib/go/csi/v0"] - revision = "35d9f9d77954980e449e52c3f3e43c21bd8171f5" - version = "v0.2.0-rc1" + revision = "2178fdeea87f1150a17a63252eee28d4d8141f72" + version = "v0.3.0" [[projects]] branch = "master" @@ -16,30 +16,70 @@ [[projects]] name = "github.com/golang/mock" packages = ["gomock"] - revision = "13f360950a79f5864a972c786a10a50e44b69541" - version = "v1.0.0" + revision = "c34cdb4725f4c3844d095133c6e40e448b86589b" + version = "v1.1.1" [[projects]] name = "github.com/golang/protobuf" - packages = ["proto","protoc-gen-go/descriptor","ptypes","ptypes/any","ptypes/duration","ptypes/timestamp"] - revision = "925541529c1fa6821df4e44ce2723319eb2be768" - version = "v1.0.0" + packages = [ + "proto", + "protoc-gen-go/descriptor", + "ptypes", + "ptypes/any", + "ptypes/duration", + "ptypes/timestamp", + "ptypes/wrappers" + ] + revision = "b4deda0973fb4c70b50d226b1af49f3da59f5265" + version = "v1.1.0" [[projects]] branch = "master" name = "github.com/kubernetes-csi/csi-test" - packages = ["driver","utils"] - revision = "3e4586c0abfbc869329d01510c663c6c540efb77" + packages = [ + "driver", + "utils" + ] + revision = "e11d328ecca7fe91939284a8e878ebe77df8756d" [[projects]] branch = "master" name = "golang.org/x/net" - packages = ["context","http2","http2/hpack","idna","internal/timeseries","lex/httplex","trace"] - revision = "cbe0f9307d0156177f9dd5dc85da1a31abc5f2fb" + packages = [ + "context", + "http/httpguts", + "http2", + "http2/hpack", + "idna", + "internal/timeseries", + "trace" + ] + revision = "c39426892332e1bb5ec0a434a079bf82f5d30c54" + +[[projects]] + branch = "master" + name = "golang.org/x/sys" + packages = ["unix"] + revision = "4e1fef5609515ec7a2cee7b5de30ba6d9b438cbf" [[projects]] name = "golang.org/x/text" - packages = ["collate","collate/build","internal/colltab","internal/gen","internal/tag","internal/triegen","internal/ucd","language","secure/bidirule","transform","unicode/bidi","unicode/cldr","unicode/norm","unicode/rangetable"] + packages = [ + "collate", + "collate/build", + "internal/colltab", + "internal/gen", + "internal/tag", + "internal/triegen", + "internal/ucd", + "language", + "secure/bidirule", + "transform", + "unicode/bidi", + "unicode/cldr", + "unicode/norm", + "unicode/rangetable" + ] revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0" version = "v0.3.0" @@ -47,17 +87,46 @@ branch = "master" name = "google.golang.org/genproto" packages = ["googleapis/rpc/status"] - revision = "2d9486acae19cf9bd0c093d7dc236a323726a9e4" + revision = "383e8b2c3b9e36c4076b235b32537292176bae20" [[projects]] name = "google.golang.org/grpc" - packages = [".","balancer","balancer/base","balancer/roundrobin","codes","connectivity","credentials","encoding","encoding/proto","grpclb/grpc_lb_v1/messages","grpclog","internal","keepalive","metadata","naming","peer","reflection","reflection/grpc_reflection_v1alpha","resolver","resolver/dns","resolver/passthrough","stats","status","tap","transport"] - revision = "8e4536a86ab602859c20df5ebfd0bd4228d08655" - version = "v1.10.0" + packages = [ + ".", + "balancer", + "balancer/base", + "balancer/roundrobin", + "codes", + "connectivity", + "credentials", + "encoding", + "encoding/proto", + "grpclog", + "internal", + "internal/backoff", + "internal/channelz", + "internal/envconfig", + "internal/grpcrand", + "internal/transport", + "keepalive", + "metadata", + "naming", + "peer", + "reflection", + "reflection/grpc_reflection_v1alpha", + "resolver", + "resolver/dns", + "resolver/passthrough", + "stats", + "status", + "tap" + ] + revision = "32fb0ac620c32ba40a4626ddf94d90d12cce3455" + version = "v1.14.0" [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "45f3b35a6ac9c977722fe0c14094733e288ce4648bb219612d65dc1bc3c1d7e3" + inputs-digest = "2f6e76998bb9d9f92c42332508edd9511082dc4b2a5bac1f3eba207120dd1b25" solver-name = "gps-cdcl" solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml index 0619d492..182d704c 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -23,16 +23,12 @@ [[constraint]] name = "github.com/container-storage-interface/spec" - version = "0.2.0-rc1" + version = "~0.3.0" [[constraint]] branch = "master" name = "github.com/golang/glog" -[[constraint]] - name = "github.com/golang/mock" - version = "1.0.0" - [[constraint]] branch = "master" name = "github.com/kubernetes-csi/csi-test" @@ -40,3 +36,7 @@ [[constraint]] name = "google.golang.org/grpc" version = "1.10.0" + +[[constraint]] + name = "github.com/golang/mock" + version = "1.1.1" diff --git a/cmd/livenessprobe_test.go b/cmd/livenessprobe_test.go new file mode 100644 index 00000000..0153137e --- /dev/null +++ b/cmd/livenessprobe_test.go @@ -0,0 +1,95 @@ +/* +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 main + +import ( + "context" + "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" + "github.com/kubernetes-csi/livenessprobe/pkg/connection" +) + +const ( + driverName = "foo/bar" +) + +func createMockServer(t *testing.T) ( + *gomock.Controller, + *driver.MockCSIDriver, + *driver.MockIdentityServer, + *driver.MockControllerServer, + *driver.MockNodeServer, + connection.CSIConnection, + error) { + // Start the mock server + mockController := gomock.NewController(t) + identityServer := driver.NewMockIdentityServer(mockController) + controllerServer := driver.NewMockControllerServer(mockController) + nodeServer := driver.NewMockNodeServer(mockController) + drv := driver.NewMockCSIDriver(&driver.MockCSIDriverServers{ + Identity: identityServer, + Controller: controllerServer, + Node: nodeServer, + }) + drv.Start() + + // Create a client connection to it + addr := drv.Address() + csiConn, err := connection.NewConnection(addr, 10) + if err != nil { + return nil, nil, nil, nil, nil, nil, err + } + + return mockController, drv, identityServer, controllerServer, nodeServer, csiConn, nil +} + +func TestProbe(t *testing.T) { + mockController, driver, idServer, _, nodeServer, csiConn, err := createMockServer(t) + if err != nil { + t.Fatal(err) + } + defer mockController.Finish() + defer driver.Stop() + defer csiConn.Close() + + // Setting up expected calls' responses + inPlugin := &csi.GetPluginInfoRequest{} + outPlugin := &csi.GetPluginInfoResponse{ + Name: "foo/bar", + } + var injectedErr error + idServer.EXPECT().GetPluginInfo(gomock.Any(), inPlugin).Return(outPlugin, injectedErr).Times(1) + + inNode := &csi.NodeGetIdRequest{} + outNode := &csi.NodeGetIdResponse{ + NodeId: "test_node_id", + } + nodeServer.EXPECT().NodeGetId(gomock.Any(), inNode).Return(outNode, injectedErr).Times(1) + inProbe := &csi.ProbeRequest{} + outProbe := &csi.ProbeResponse{} + idServer.EXPECT().Probe(gomock.Any(), inProbe).Return(outProbe, injectedErr).Times(1) + // Calling Probing function + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + if err := runProbe(ctx, csiConn); err != nil { + t.Fatalf("failed to run probe with error: %+v", err) + } +} diff --git a/cmd/main.go b/cmd/main.go index 4acf0d9f..cc5eb319 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -41,14 +41,7 @@ var ( healthzPort = flag.String("health-port", "9808", "TCP ports for listening healthz requests") ) -func runProbe(ctx context.Context) error { - - // Connect to CSI. - glog.Infof("Attempting to open a gRPC connection with: %s", *csiAddress) - csiConn, err := connection.NewConnection(*csiAddress, *connectionTimeout) - if err != nil { - return err - } +func runProbe(ctx context.Context, csiConn connection.CSIConnection) error { // Get CSI driver name. glog.Infof("Calling CSI driver to discover driver name.") @@ -74,13 +67,29 @@ func runProbe(ctx context.Context) error { return nil } +func getCSIConnection() (connection.CSIConnection, error) { + // Connect to CSI. + glog.Infof("Attempting to open a gRPC connection with: %s", *csiAddress) + csiConn, err := connection.NewConnection(*csiAddress, *connectionTimeout) + if err != nil { + return nil, err + } + return csiConn, nil +} + func chekcHealth(w http.ResponseWriter, req *http.Request) { glog.Infof("Request: %s from: %s\n", req.URL.Path, req.RemoteAddr) + csiConn, err := getCSIConnection() + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte(err.Error())) + glog.Infof("Failed to get connection to CSI with error: %v.", err) + return + } ctx, cancel := context.WithTimeout(context.Background(), *connectionTimeout) defer cancel() - err := runProbe(ctx) - if err != nil { + if err := runProbe(ctx, csiConn); err != nil { w.WriteHeader(http.StatusInternalServerError) w.Write([]byte(err.Error())) glog.Infof("Health check failed with: %v.", err) diff --git a/hack/e2e-livenessprobe.sh b/hack/e2e-livenessprobe.sh new file mode 100755 index 00000000..5768df26 --- /dev/null +++ b/hack/e2e-livenessprobe.sh @@ -0,0 +1,58 @@ +#!/bin/bash +set -x + +## This file is for livenessprove which runs in a pair with csi +## hostpath + +## Must be run from the root of the repo +UDS="/tmp/e2e-csi-sanity.sock" +CSI_ENDPOINT="unix://${UDS}" +CSI_MOUNTPOINT="/mnt" +APP=hostpathplugin + +SKIP="WithCapacity" +if [ x${TRAVIS} = x"true" ] ; then + SKIP="WithCapacity|NodeUnpublishVolume|NodePublishVolume" +fi + +git clone https://github.com/kubernetes-csi/drivers $GOPATH/src/github.com/kubernetes-csi/drivers +pushd $GOPATH/src/github.com/kubernetes-csi/drivers +# Build +make hostpath; ret=$? +if [ $ret -ne 0 ]; then + echo "Failed to build hostpath plugin, file a bug against drivers repo" + exit 1 +fi +popd + +sudo rm -rf "$UDS" || true + +# Start hostpathplugin in the background +sudo $GOPATH/src/github.com/kubernetes-csi/drivers/_output/$APP --endpoint=$CSI_ENDPOINT --nodeid=1 --v=5 & + +# Start liveness probe in the background +sudo ./bin/livenessprobe --csi-address=$CSI_ENDPOINT & + +# Give time to CSI hostpathplugin and livenessprobe to initialize +sleep 3 + +# Requesting health +health=$(curl -I http://localhost:9808/healthz | grep HTTP | awk '{print $2}') +if [[ "x$health" != "x200" ]]; then + echo "Health check failed, but it was not supposed to, exiting..." + exit 1 +fi + +# Killing hostpathplugin +sudo kill -9 $(pidof hostpathplugin) +sleep 3 + +# Requesting health, should fail since hostpathplugin is gone +health=$(curl -I http://localhost:9808/healthz| grep HTTP | awk '{print $2}') +if [[ "x$health" != "x500" ]]; then + echo "Health check did not detect driver failure, returned code: $health, exiting..." + exit 1 +fi + +sudo rm -f $UDS +exit 0