add prune and remove unused packages
This commit is contained in:
19
vendor/github.com/kubernetes-csi/csi-test/.gitignore
generated
vendored
19
vendor/github.com/kubernetes-csi/csi-test/.gitignore
generated
vendored
@@ -1,19 +0,0 @@
|
||||
# Binaries for programs and plugins
|
||||
*.exe
|
||||
*.dll
|
||||
*.so
|
||||
*.dylib
|
||||
|
||||
# Test binary, build with `go test -c`
|
||||
*.test
|
||||
|
||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||
*.out
|
||||
bin/mock
|
||||
cmd/csi-sanity/csi-sanity
|
||||
|
||||
# JetBrains GoLand
|
||||
.idea
|
||||
|
||||
# Vim
|
||||
*.swp
|
15
vendor/github.com/kubernetes-csi/csi-test/.travis.yml
generated
vendored
15
vendor/github.com/kubernetes-csi/csi-test/.travis.yml
generated
vendored
@@ -1,15 +0,0 @@
|
||||
language: go
|
||||
sudo: required
|
||||
services:
|
||||
- docker
|
||||
matrix:
|
||||
include:
|
||||
- go: 1.10.3
|
||||
script:
|
||||
- make test
|
||||
after_success:
|
||||
- if [ "${TRAVIS_BRANCH}" == "master" ] && [ "${TRAVIS_PULL_REQUEST}" == "false" ]; then
|
||||
make container
|
||||
docker login -u "${DOCKER_USERNAME}" -p "${DOCKER_PASSWORD}" quay.io;
|
||||
make push;
|
||||
fi
|
22
vendor/github.com/kubernetes-csi/csi-test/CONTRIBUTING.md
generated
vendored
22
vendor/github.com/kubernetes-csi/csi-test/CONTRIBUTING.md
generated
vendored
@@ -1,22 +0,0 @@
|
||||
# Contributing Guidelines
|
||||
|
||||
Welcome to Kubernetes. We are excited about the prospect of you joining our [community](https://github.com/kubernetes/community)! The Kubernetes community abides by the CNCF [code of conduct](https://github.com/cncf/foundation/blob/master/code-of-conduct.md). Here is an excerpt:
|
||||
|
||||
_As contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities._
|
||||
|
||||
## Getting Started
|
||||
|
||||
We have full documentation on how to get started contributing here:
|
||||
|
||||
- [Contributor License Agreement](https://git.k8s.io/community/CLA.md) Kubernetes projects require that you sign a Contributor License Agreement (CLA) before we can accept your pull requests
|
||||
- [Kubernetes Contributor Guide](http://git.k8s.io/community/contributors/guide) - Main contributor documentation, or you can just jump directly to the [contributing section](http://git.k8s.io/community/contributors/guide#contributing)
|
||||
- [Contributor Cheat Sheet](https://git.k8s.io/community/contributors/guide/contributor-cheatsheet.md) - Common resources for existing developers
|
||||
|
||||
## Mentorship
|
||||
|
||||
- [Mentoring Initiatives](https://git.k8s.io/community/mentoring) - We have a diverse set of mentorship programs available that are always looking for volunteers!
|
||||
|
||||
## Contact Information
|
||||
|
||||
- [Slack channel](https://kubernetes.slack.com/messages/sig-storage)
|
||||
- [Mailing list](https://groups.google.com/forum/#!forum/kubernetes-sig-storage)
|
6
vendor/github.com/kubernetes-csi/csi-test/Dockerfile.mock
generated
vendored
6
vendor/github.com/kubernetes-csi/csi-test/Dockerfile.mock
generated
vendored
@@ -1,6 +0,0 @@
|
||||
FROM alpine
|
||||
LABEL maintainers="Kubernetes Authors"
|
||||
LABEL description="CSI Mock Driver"
|
||||
|
||||
COPY ./bin/mock mock
|
||||
ENTRYPOINT ["/mock"]
|
237
vendor/github.com/kubernetes-csi/csi-test/Gopkg.lock
generated
vendored
237
vendor/github.com/kubernetes-csi/csi-test/Gopkg.lock
generated
vendored
@@ -1,237 +0,0 @@
|
||||
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
|
||||
|
||||
|
||||
[[projects]]
|
||||
digest = "1:26ee2356254e58b9872ba736f66aff1c54a26f08c7d16afbf49695131a87d454"
|
||||
name = "github.com/container-storage-interface/spec"
|
||||
packages = ["lib/go/csi"]
|
||||
pruneopts = "UT"
|
||||
revision = "8efcc85c45550571fba8134182013ed7dc34038a"
|
||||
version = "v1.0.0-rc2"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:bc38c7c481812e178d85160472e231c5e1c9a7f5845d67e23ee4e706933c10d8"
|
||||
name = "github.com/golang/mock"
|
||||
packages = ["gomock"]
|
||||
pruneopts = "UT"
|
||||
revision = "c34cdb4725f4c3844d095133c6e40e448b86589b"
|
||||
version = "v1.1.1"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:588beb9f80d2b0afddf05663b32d01c867da419458b560471d81cca0286e76b8"
|
||||
name = "github.com/golang/protobuf"
|
||||
packages = [
|
||||
"proto",
|
||||
"protoc-gen-go/descriptor",
|
||||
"ptypes",
|
||||
"ptypes/any",
|
||||
"ptypes/duration",
|
||||
"ptypes/timestamp",
|
||||
"ptypes/wrappers",
|
||||
]
|
||||
pruneopts = "UT"
|
||||
revision = "aa810b61a9c79d51363740d207bb46cf8e620ed5"
|
||||
version = "v1.2.0"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:72f35d3e412bc67b121e15ea4c88a3b3da8bcbc2264339e7ffa4a1865799840c"
|
||||
name = "github.com/onsi/ginkgo"
|
||||
packages = [
|
||||
".",
|
||||
"config",
|
||||
"internal/codelocation",
|
||||
"internal/containernode",
|
||||
"internal/failer",
|
||||
"internal/leafnodes",
|
||||
"internal/remote",
|
||||
"internal/spec",
|
||||
"internal/spec_iterator",
|
||||
"internal/specrunner",
|
||||
"internal/suite",
|
||||
"internal/testingtproxy",
|
||||
"internal/writer",
|
||||
"reporters",
|
||||
"reporters/stenographer",
|
||||
"reporters/stenographer/support/go-colorable",
|
||||
"reporters/stenographer/support/go-isatty",
|
||||
"types",
|
||||
]
|
||||
pruneopts = "UT"
|
||||
revision = "fa5fabab2a1bfbd924faf4c067d07ae414e2aedf"
|
||||
version = "v1.5.0"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:d0c2c4e2d0006cd28c220a549cda1de8e67abc65ed4c572421492bbf0492ceaf"
|
||||
name = "github.com/onsi/gomega"
|
||||
packages = [
|
||||
".",
|
||||
"format",
|
||||
"internal/assertion",
|
||||
"internal/asyncassertion",
|
||||
"internal/oraclematcher",
|
||||
"internal/testingtsupport",
|
||||
"matchers",
|
||||
"matchers/support/goraph/bipartitegraph",
|
||||
"matchers/support/goraph/edge",
|
||||
"matchers/support/goraph/node",
|
||||
"matchers/support/goraph/util",
|
||||
"types",
|
||||
]
|
||||
pruneopts = "UT"
|
||||
revision = "62bff4df71bdbc266561a0caee19f0594b17c240"
|
||||
version = "v1.4.0"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:9e9193aa51197513b3abcb108970d831fbcf40ef96aa845c4f03276e1fa316d2"
|
||||
name = "github.com/sirupsen/logrus"
|
||||
packages = ["."]
|
||||
pruneopts = "UT"
|
||||
revision = "c155da19408a8799da419ed3eeb0cb5db0ad5dbc"
|
||||
version = "v1.0.5"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:3f3a05ae0b95893d90b9b3b5afdb79a9b3d96e4e36e099d841ae602e4aca0da8"
|
||||
name = "golang.org/x/crypto"
|
||||
packages = ["ssh/terminal"]
|
||||
pruneopts = "UT"
|
||||
revision = "8ac0e0d97ce45cd83d1d7243c060cb8461dda5e9"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:0bb2e6ef036484991ed446a6c698698b8901766981d4d22cc8e53fedb09709ac"
|
||||
name = "golang.org/x/net"
|
||||
packages = [
|
||||
"context",
|
||||
"html",
|
||||
"html/atom",
|
||||
"html/charset",
|
||||
"http/httpguts",
|
||||
"http2",
|
||||
"http2/hpack",
|
||||
"idna",
|
||||
"internal/timeseries",
|
||||
"trace",
|
||||
]
|
||||
pruneopts = "UT"
|
||||
revision = "1e491301e022f8f977054da4c2d852decd59571f"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:8fbfc6ea1a8a078697633be97f07dd83a83d32a96959d42195464c13c25be374"
|
||||
name = "golang.org/x/sys"
|
||||
packages = [
|
||||
"unix",
|
||||
"windows",
|
||||
]
|
||||
pruneopts = "UT"
|
||||
revision = "9527bec2660bd847c050fda93a0f0c6dee0800bb"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:436b24586f8fee329e0dd65fd67c817681420cda1d7f934345c13fe78c212a73"
|
||||
name = "golang.org/x/text"
|
||||
packages = [
|
||||
"collate",
|
||||
"collate/build",
|
||||
"encoding",
|
||||
"encoding/charmap",
|
||||
"encoding/htmlindex",
|
||||
"encoding/internal",
|
||||
"encoding/internal/identifier",
|
||||
"encoding/japanese",
|
||||
"encoding/korean",
|
||||
"encoding/simplifiedchinese",
|
||||
"encoding/traditionalchinese",
|
||||
"encoding/unicode",
|
||||
"internal/colltab",
|
||||
"internal/gen",
|
||||
"internal/tag",
|
||||
"internal/triegen",
|
||||
"internal/ucd",
|
||||
"internal/utf8internal",
|
||||
"language",
|
||||
"runes",
|
||||
"secure/bidirule",
|
||||
"transform",
|
||||
"unicode/bidi",
|
||||
"unicode/cldr",
|
||||
"unicode/norm",
|
||||
"unicode/rangetable",
|
||||
]
|
||||
pruneopts = "UT"
|
||||
revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0"
|
||||
version = "v0.3.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:601e63e7d4577f907118bec825902505291918859d223bce015539e79f1160e3"
|
||||
name = "google.golang.org/genproto"
|
||||
packages = ["googleapis/rpc/status"]
|
||||
pruneopts = "UT"
|
||||
revision = "32ee49c4dd805befd833990acba36cb75042378c"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:7a977fdcd5abff03e94f92e7b374ef37e91c7c389581e5c4348fa98616e6c6be"
|
||||
name = "google.golang.org/grpc"
|
||||
packages = [
|
||||
".",
|
||||
"balancer",
|
||||
"balancer/base",
|
||||
"balancer/roundrobin",
|
||||
"channelz",
|
||||
"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",
|
||||
]
|
||||
pruneopts = "UT"
|
||||
revision = "7a6a684ca69eb4cae85ad0a484f2e531598c047b"
|
||||
version = "v1.12.2"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:342378ac4dcb378a5448dd723f0784ae519383532f5e70ade24132c4c8693202"
|
||||
name = "gopkg.in/yaml.v2"
|
||||
packages = ["."]
|
||||
pruneopts = "UT"
|
||||
revision = "5420a8b6744d3b0345ab293f6fcba19c978f1183"
|
||||
version = "v2.2.1"
|
||||
|
||||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
input-imports = [
|
||||
"github.com/container-storage-interface/spec/lib/go/csi",
|
||||
"github.com/golang/mock/gomock",
|
||||
"github.com/golang/protobuf/proto",
|
||||
"github.com/golang/protobuf/ptypes",
|
||||
"github.com/golang/protobuf/ptypes/wrappers",
|
||||
"github.com/onsi/ginkgo",
|
||||
"github.com/onsi/gomega",
|
||||
"github.com/sirupsen/logrus",
|
||||
"golang.org/x/net/context",
|
||||
"google.golang.org/grpc",
|
||||
"google.golang.org/grpc/codes",
|
||||
"google.golang.org/grpc/connectivity",
|
||||
"google.golang.org/grpc/reflection",
|
||||
"google.golang.org/grpc/status",
|
||||
"gopkg.in/yaml.v2",
|
||||
]
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
62
vendor/github.com/kubernetes-csi/csi-test/Gopkg.toml
generated
vendored
62
vendor/github.com/kubernetes-csi/csi-test/Gopkg.toml
generated
vendored
@@ -1,62 +0,0 @@
|
||||
# Gopkg.toml example
|
||||
#
|
||||
# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
|
||||
# for detailed Gopkg.toml documentation.
|
||||
#
|
||||
# required = ["github.com/user/thing/cmd/thing"]
|
||||
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
|
||||
#
|
||||
# [[constraint]]
|
||||
# name = "github.com/user/project"
|
||||
# version = "1.0.0"
|
||||
#
|
||||
# [[constraint]]
|
||||
# name = "github.com/user/project2"
|
||||
# branch = "dev"
|
||||
# source = "github.com/myfork/project2"
|
||||
#
|
||||
# [[override]]
|
||||
# name = "github.com/x/y"
|
||||
# version = "2.4.0"
|
||||
#
|
||||
# [prune]
|
||||
# non-go = false
|
||||
# go-tests = true
|
||||
# unused-packages = true
|
||||
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/container-storage-interface/spec"
|
||||
version = "v1.0.0-rc2"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/golang/mock"
|
||||
version = "1.0.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/golang/protobuf"
|
||||
version = "v1.2.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/onsi/ginkgo"
|
||||
version = "1.4.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/onsi/gomega"
|
||||
version = "1.3.0"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/net"
|
||||
|
||||
[[constraint]]
|
||||
name = "google.golang.org/grpc"
|
||||
version = "1.9.2"
|
||||
|
||||
[[constraint]]
|
||||
name = "gopkg.in/yaml.v2"
|
||||
version = "v2.1.1"
|
||||
|
||||
[prune]
|
||||
go-tests = true
|
||||
unused-packages = true
|
52
vendor/github.com/kubernetes-csi/csi-test/Makefile
generated
vendored
52
vendor/github.com/kubernetes-csi/csi-test/Makefile
generated
vendored
@@ -1,52 +0,0 @@
|
||||
# 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.
|
||||
|
||||
IMAGE_NAME = quay.io/k8scsi/mock-driver
|
||||
IMAGE_VERSION = canary
|
||||
APP := ./bin/mock
|
||||
|
||||
|
||||
ifdef V
|
||||
TESTARGS = -v -args -alsologtostderr -v 5
|
||||
else
|
||||
TESTARGS =
|
||||
endif
|
||||
|
||||
all: $(APP)
|
||||
|
||||
$(APP):
|
||||
mkdir -p bin
|
||||
CGO_ENABLED=0 GOOS=linux go build -a -ldflags '-extldflags "-static"' -o $(APP) ./mock/main.go
|
||||
|
||||
clean:
|
||||
rm -rf bin
|
||||
|
||||
container: $(APP)
|
||||
docker build -f Dockerfile.mock -t $(IMAGE_NAME):$(IMAGE_VERSION) .
|
||||
|
||||
push: container
|
||||
docker push $(IMAGE_NAME):$(IMAGE_VERSION)
|
||||
|
||||
test: $(APP)
|
||||
files=$$(find ./ -name '*.go' | grep -v '^./vendor' ); \
|
||||
if [ $$(gofmt -d $$files | wc -l) -ne 0 ]; then \
|
||||
echo "formatting errors:"; \
|
||||
gofmt -d $$files; \
|
||||
false; \
|
||||
fi
|
||||
go vet $$(go list ./... | grep -v vendor)
|
||||
go test $$(go list ./... | grep -v vendor | grep -v "cmd/csi-sanity")
|
||||
./hack/e2e.sh
|
||||
|
||||
.PHONY: all clean container push test
|
4
vendor/github.com/kubernetes-csi/csi-test/OWNERS
generated
vendored
4
vendor/github.com/kubernetes-csi/csi-test/OWNERS
generated
vendored
@@ -1,4 +0,0 @@
|
||||
approvers:
|
||||
- saad-ali
|
||||
- lpabon
|
||||
- pohly
|
42
vendor/github.com/kubernetes-csi/csi-test/README.md
generated
vendored
42
vendor/github.com/kubernetes-csi/csi-test/README.md
generated
vendored
@@ -1,42 +0,0 @@
|
||||
[](https://travis-ci.org/kubernetes-csi/csi-test)
|
||||
[](https://quay.io/repository/k8scsi/mock-driver)
|
||||
|
||||
# csi-test
|
||||
csi-test houses packages and libraries to help test CSI client and plugins.
|
||||
|
||||
## For Container Orchestration Tests
|
||||
CO developers can use this framework to create drivers based on the
|
||||
[Golang mock](https://github.com/golang/mock) framework. Please see
|
||||
[co_test.go](test/co_test.go) for an example.
|
||||
|
||||
### Mock driver for testing
|
||||
We also provide a container called `quay.io/k8scsi/mock-driver:canary` which can be used as an in-memory mock driver.
|
||||
It follows the same release cycle as other containers, so the latest release is `quay.io/k8scsi/mock-driver:v0.3.0`.
|
||||
|
||||
You will need to setup the environment variable `CSI_ENDPOINT` for the mock driver to know where to create the unix
|
||||
domain socket.
|
||||
|
||||
## For CSI Driver Tests
|
||||
To test drivers please take a look at [pkg/sanity](https://github.com/kubernetes-csi/csi-test/tree/master/pkg/sanity).
|
||||
This package and [csi-sanity](https://github.com/kubernetes-csi/csi-test/tree/master/cmd/csi-sanity) are meant to test
|
||||
the CSI API capability of a driver. They are meant to be an additional test to the unit, functional, and e2e tests of a
|
||||
CSI driver.
|
||||
|
||||
### Note
|
||||
|
||||
* Master is for CSI v0.4.0. Please see the branches for other CSI releases.
|
||||
* Only Golang 1.9+ supported. See [gRPC issue](https://github.com/grpc/grpc-go/issues/711#issuecomment-326626790)
|
||||
|
||||
## Community, discussion, contribution, and support
|
||||
|
||||
Learn how to engage with the Kubernetes community on the [community page](http://kubernetes.io/community/).
|
||||
|
||||
You can reach the maintainers of this project at:
|
||||
|
||||
- [Slack channel](https://kubernetes.slack.com/messages/sig-storage)
|
||||
- [Mailing list](https://groups.google.com/forum/#!forum/kubernetes-sig-storage)
|
||||
|
||||
### Code of conduct
|
||||
|
||||
Participation in the Kubernetes community is governed by the [Kubernetes Code of Conduct](code-of-conduct.md).
|
14
vendor/github.com/kubernetes-csi/csi-test/SECURITY_CONTACTS
generated
vendored
14
vendor/github.com/kubernetes-csi/csi-test/SECURITY_CONTACTS
generated
vendored
@@ -1,14 +0,0 @@
|
||||
# Defined below are the security contacts for this repo.
|
||||
#
|
||||
# They are the contact point for the Product Security Team to reach out
|
||||
# to for triaging and handling of incoming issues.
|
||||
#
|
||||
# The below names agree to abide by the
|
||||
# [Embargo Policy](https://github.com/kubernetes/sig-release/blob/master/security-release-process-documentation/security-release-process.md#embargo-policy)
|
||||
# and will be removed and replaced if they violate that agreement.
|
||||
#
|
||||
# DO NOT REPORT SECURITY VULNERABILITIES DIRECTLY TO THESE NAMES, FOLLOW THE
|
||||
# INSTRUCTIONS AT https://kubernetes.io/security/
|
||||
|
||||
saad-ali
|
||||
lpabon
|
61
vendor/github.com/kubernetes-csi/csi-test/cmd/csi-sanity/Makefile
generated
vendored
61
vendor/github.com/kubernetes-csi/csi-test/cmd/csi-sanity/Makefile
generated
vendored
@@ -1,61 +0,0 @@
|
||||
APP_NAME := csi-sanity
|
||||
VER :=$(shell git describe)
|
||||
RELEASEVER := $(shell git describe --abbrev=0)
|
||||
BRANCH := $(subst /,-,$(shell git rev-parse --abbrev-ref HEAD))
|
||||
SHA := $(shell git rev-parse --short HEAD)
|
||||
ARCH := $(shell go env GOARCH)
|
||||
GOOS := $(shell go env GOOS)
|
||||
DIR=.
|
||||
|
||||
ifdef APP_SUFFIX
|
||||
VERSION = $(VER)-$(subst /,-,$(APP_SUFFIX))
|
||||
else
|
||||
ifeq (master,$(BRANCH))
|
||||
VERSION = $(VER)
|
||||
else
|
||||
VERSION = $(VER)-$(BRANCH)
|
||||
endif
|
||||
endif
|
||||
|
||||
LDFLAGS :=-ldflags "-w -X github.com/kubernetes-csi/csi-test/cmd/csi-sanity.VERSION=$(VERSION) -extldflags '-z relro -z now'"
|
||||
PACKAGE :=$(DIR)/dist/$(APP_NAME)-$(RELEASEVER).$(GOOS).$(ARCH).tar.gz
|
||||
|
||||
all: $(APP_NAME)
|
||||
|
||||
$(APP_NAME): Makefile sanity_test.go
|
||||
go test $(LDFLAGS) -c -o $(APP_NAME)
|
||||
|
||||
install: $(APP_NAME)
|
||||
cp $(APP_NAME) $(GOPATH)/bin
|
||||
|
||||
clean:
|
||||
rm -f csi-sanity
|
||||
|
||||
dist-clean:
|
||||
rm -rf $(DIR)/dist
|
||||
|
||||
dist: clean $(PACKAGE)
|
||||
|
||||
$(PACKAGE): $(APP_NAME)
|
||||
@echo Packaging Binaries...
|
||||
@mkdir -p tmp/$(APP_NAME)
|
||||
@cp $(APP_NAME) tmp/$(APP_NAME)/
|
||||
@mkdir -p $(DIR)/dist/
|
||||
tar -czf $@ -C tmp $(APP_NAME);
|
||||
@rm -rf tmp
|
||||
@echo
|
||||
@echo Package $@ saved in dist directory
|
||||
|
||||
linux_amd64_dist:
|
||||
GOOS=linux GOARCH=amd64 $(MAKE) dist
|
||||
|
||||
linux_arm64_dist:
|
||||
GOOS=linux GOARCH=arm64 $(MAKE) dist
|
||||
|
||||
darwin_amd64_dist:
|
||||
GOOS=darwin GOARCH=amd64 $(MAKE) dist
|
||||
|
||||
release: dist-clean darwin_amd64_dist linux_amd64_dist linux_arm64_dist
|
||||
|
||||
.PHONY: release darwin_amd64_dist linux_arm64_dist linux_amd64_dist \
|
||||
linux_arm_dist linux_amd64_dist clean dist-clean
|
58
vendor/github.com/kubernetes-csi/csi-test/cmd/csi-sanity/README.md
generated
vendored
58
vendor/github.com/kubernetes-csi/csi-test/cmd/csi-sanity/README.md
generated
vendored
@@ -1,58 +0,0 @@
|
||||
# Sanity Test Command Line Program
|
||||
This is the command line program that tests a CSI driver using the [`sanity`](https://github.com/kubernetes-csi/csi-test/tree/master/pkg/sanity) package test suite.
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
$ csi-sanity --csi.endpoint=<your csi driver endpoint>
|
||||
```
|
||||
|
||||
If you want to specify a mount point:
|
||||
|
||||
```
|
||||
$ csi-sanity --csi.endpoint=<your csi driver endpoint> --csi.mountpoint=/mnt
|
||||
```
|
||||
|
||||
For verbose type:
|
||||
|
||||
```
|
||||
$ csi-sanity --ginkgo.v --csi.endpoint=<your csi driver endpoint>
|
||||
```
|
||||
|
||||
For csi-credentials, create a secrets file with all the secrets in it:
|
||||
```yaml
|
||||
CreateVolumeSecret:
|
||||
secretKey: secretval1
|
||||
DeleteVolumeSecret:
|
||||
secretKey: secretval2
|
||||
ControllerPublishVolumeSecret:
|
||||
secretKey: secretval3
|
||||
ControllerUnpublishVolumeSecret:
|
||||
secretKey: secretval4
|
||||
NodeStageVolumeSecret:
|
||||
secretKey: secretval5
|
||||
NodePublishVolumeSecret:
|
||||
secretKey: secretval6
|
||||
```
|
||||
|
||||
Pass the file path to csi-sanity as:
|
||||
```
|
||||
$ csi-sanity --csi.endpoint=<your csi driver endpoint> --csi.secrets=<path to secrets file>
|
||||
```
|
||||
|
||||
Replace the keys and values of the credentials appropriately. Since the whole
|
||||
secret is passed in the request, multiple key-val pairs can be used.
|
||||
|
||||
### Help
|
||||
The full Ginkgo and golang unit test parameters are available. Type
|
||||
|
||||
```
|
||||
$ csi-sanity -h
|
||||
```
|
||||
|
||||
to get more information
|
||||
|
||||
### Download
|
||||
|
||||
Please see the [Releases](https://github.com/kubernetes-csi/csi-test/releases) page
|
||||
to download the latest version of `csi-sanity`
|
57
vendor/github.com/kubernetes-csi/csi-test/cmd/csi-sanity/sanity_test.go
generated
vendored
57
vendor/github.com/kubernetes-csi/csi-test/cmd/csi-sanity/sanity_test.go
generated
vendored
@@ -1,57 +0,0 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
package sanity
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/kubernetes-csi/csi-test/pkg/sanity"
|
||||
)
|
||||
|
||||
const (
|
||||
prefix string = "csi."
|
||||
)
|
||||
|
||||
var (
|
||||
VERSION = "(dev)"
|
||||
version bool
|
||||
config sanity.Config
|
||||
)
|
||||
|
||||
func init() {
|
||||
flag.StringVar(&config.Address, prefix+"endpoint", "", "CSI endpoint")
|
||||
flag.BoolVar(&version, prefix+"version", false, "Version of this program")
|
||||
flag.StringVar(&config.TargetPath, prefix+"mountdir", os.TempDir()+"/csi", "Mount point for NodePublish")
|
||||
flag.StringVar(&config.StagingPath, prefix+"stagingdir", os.TempDir()+"/csi", "Mount point for NodeStage if staging is supported")
|
||||
flag.StringVar(&config.SecretsFile, prefix+"secrets", "", "CSI secrets file")
|
||||
flag.Int64Var(&config.TestVolumeSize, prefix+"testvolumesize", sanity.DefTestVolumeSize, "Base volume size used for provisioned volumes")
|
||||
flag.StringVar(&config.TestVolumeParametersFile, prefix+"testvolumeparameters", "", "YAML file of volume parameters for provisioned volumes")
|
||||
flag.Parse()
|
||||
}
|
||||
|
||||
func TestSanity(t *testing.T) {
|
||||
if version {
|
||||
fmt.Printf("Version = %s\n", VERSION)
|
||||
return
|
||||
}
|
||||
if len(config.Address) == 0 {
|
||||
t.Fatalf("--%sendpoint must be provided with an CSI endpoint", prefix)
|
||||
}
|
||||
sanity.Test(t, &config)
|
||||
}
|
3
vendor/github.com/kubernetes-csi/csi-test/code-of-conduct.md
generated
vendored
3
vendor/github.com/kubernetes-csi/csi-test/code-of-conduct.md
generated
vendored
@@ -1,3 +0,0 @@
|
||||
# Kubernetes Community Code of Conduct
|
||||
|
||||
Please refer to our [Kubernetes Community Code of Conduct](https://git.k8s.io/community/code-of-conduct.md)
|
18
vendor/github.com/kubernetes-csi/csi-test/hack/_apitest/api_test.go
generated
vendored
18
vendor/github.com/kubernetes-csi/csi-test/hack/_apitest/api_test.go
generated
vendored
@@ -1,18 +0,0 @@
|
||||
package apitest
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/kubernetes-csi/csi-test/pkg/sanity"
|
||||
)
|
||||
|
||||
func TestMyDriver(t *testing.T) {
|
||||
config := &sanity.Config{
|
||||
TargetPath: os.TempDir() + "/csi",
|
||||
StagingPath: os.TempDir() + "/csi",
|
||||
Address: "/tmp/e2e-csi-sanity.sock",
|
||||
}
|
||||
|
||||
sanity.Test(t, config)
|
||||
}
|
42
vendor/github.com/kubernetes-csi/csi-test/hack/_embedded/embedded_test.go
generated
vendored
42
vendor/github.com/kubernetes-csi/csi-test/hack/_embedded/embedded_test.go
generated
vendored
@@ -1,42 +0,0 @@
|
||||
package embedded
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/kubernetes-csi/csi-test/pkg/sanity"
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
func TestMyDriverGinkgo(t *testing.T) {
|
||||
RegisterFailHandler(Fail)
|
||||
RunSpecs(t, "CSI Sanity Test Suite")
|
||||
}
|
||||
|
||||
// The test suite into which the sanity tests get embedded may already
|
||||
// have before/after suite functions. There can only be one such
|
||||
// function. Here we define empty ones because then Ginkgo
|
||||
// will start complaining at runtime when invoking the embedded case
|
||||
// in hack/e2e.sh if a PR adds back such functions in the sanity test
|
||||
// code.
|
||||
var _ = BeforeSuite(func() {})
|
||||
var _ = AfterSuite(func() {})
|
||||
|
||||
var _ = Describe("MyCSIDriver", func() {
|
||||
Context("Config A", func() {
|
||||
config := &sanity.Config{
|
||||
TargetPath: os.TempDir() + "/csi",
|
||||
StagingPath: os.TempDir() + "/csi",
|
||||
Address: "/tmp/e2e-csi-sanity.sock",
|
||||
}
|
||||
|
||||
BeforeEach(func() {})
|
||||
|
||||
AfterEach(func() {})
|
||||
|
||||
Describe("CSI Driver Test Suite", func() {
|
||||
sanity.GinkgoTest(config)
|
||||
})
|
||||
})
|
||||
})
|
72
vendor/github.com/kubernetes-csi/csi-test/hack/e2e.sh
generated
vendored
72
vendor/github.com/kubernetes-csi/csi-test/hack/e2e.sh
generated
vendored
@@ -1,72 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
TESTARGS=$@
|
||||
UDS="/tmp/e2e-csi-sanity.sock"
|
||||
CSI_ENDPOINTS="$CSI_ENDPOINTS ${UDS}"
|
||||
CSI_MOCK_VERSION="master"
|
||||
|
||||
#
|
||||
# $1 - endpoint for mock.
|
||||
# $2 - endpoint for csi-sanity in Grpc format.
|
||||
# See https://github.com/grpc/grpc/blob/master/doc/naming.md
|
||||
runTest()
|
||||
{
|
||||
CSI_ENDPOINT=$1 ./bin/mock &
|
||||
local pid=$!
|
||||
|
||||
./cmd/csi-sanity/csi-sanity $TESTARGS --csi.endpoint=$2; ret=$?
|
||||
kill -9 $pid
|
||||
|
||||
if [ $ret -ne 0 ] ; then
|
||||
exit $ret
|
||||
fi
|
||||
}
|
||||
|
||||
runTestWithCreds()
|
||||
{
|
||||
CSI_ENDPOINT=$1 CSI_ENABLE_CREDS=true ./bin/mock &
|
||||
local pid=$!
|
||||
|
||||
./cmd/csi-sanity/csi-sanity $TESTARGS --csi.endpoint=$2 --csi.secrets=mock/mocksecret.yaml; ret=$?
|
||||
kill -9 $pid
|
||||
|
||||
if [ $ret -ne 0 ] ; then
|
||||
exit $ret
|
||||
fi
|
||||
}
|
||||
|
||||
runTestAPI()
|
||||
{
|
||||
CSI_ENDPOINT=$1 ./bin/mock &
|
||||
local pid=$!
|
||||
|
||||
GOCACHE=off go test -v ./hack/_apitest/api_test.go; ret=$?
|
||||
|
||||
if [ $ret -ne 0 ] ; then
|
||||
exit $ret
|
||||
fi
|
||||
|
||||
GOCACHE=off go test -v ./hack/_embedded/embedded_test.go; ret=$?
|
||||
kill -9 $pid
|
||||
|
||||
if [ $ret -ne 0 ] ; then
|
||||
exit $ret
|
||||
fi
|
||||
}
|
||||
|
||||
make
|
||||
|
||||
cd cmd/csi-sanity
|
||||
make clean install || exit 1
|
||||
cd ../..
|
||||
|
||||
runTest "${UDS}" "${UDS}"
|
||||
rm -f $UDS
|
||||
|
||||
runTestWithCreds "${UDS}" "${UDS}"
|
||||
rm -f $UDS
|
||||
|
||||
runTestAPI "${UDS}"
|
||||
rm -f $UDS
|
||||
|
||||
exit 0
|
22
vendor/github.com/kubernetes-csi/csi-test/mock/README.md
generated
vendored
22
vendor/github.com/kubernetes-csi/csi-test/mock/README.md
generated
vendored
@@ -1,22 +0,0 @@
|
||||
# Mock CSI Driver
|
||||
Extremely simple mock driver used to test `csi-sanity` based on `rexray/gocsi/mock`.
|
||||
It can be used for testing of Container Orchestrators that implement client side
|
||||
of CSI interface.
|
||||
|
||||
```
|
||||
Usage of mock:
|
||||
-disable-attach
|
||||
Disables RPC_PUBLISH_UNPUBLISH_VOLUME capability.
|
||||
-name string
|
||||
CSI driver name. (default "io.kubernetes.storage.mock")
|
||||
```
|
||||
|
||||
It prints all received CSI messages to stdout encoded as json, so a test can check that
|
||||
CO sent the right CSI message.
|
||||
|
||||
Example of such output:
|
||||
|
||||
```
|
||||
gRPCCall: {"Method":"/csi.v0.Controller/ControllerGetCapabilities","Request":{},"Response":{"capabilities":[{"Type":{"Rpc":{"type":1}}},{"Type":{"Rpc":{"type":3}}},{"Type":{"Rpc":{"type":4}}},{"Type":{"Rpc":{"type":6}}},{"Type":{"Rpc":{"type":5}}},{"Type":{"Rpc":{"type":2}}}]},"Error":""}
|
||||
gRPCCall: {"Method":"/csi.v0.Controller/ControllerPublishVolume","Request":{"volume_id":"12","node_id":"some-fake-node-id","volume_capability":{"AccessType":{"Mount":{}},"access_mode":{"mode":1}}},"Response":null,"Error":"rpc error: code = NotFound desc = Not matching Node ID some-fake-node-id to Mock Node ID io.kubernetes.storage.mock"}
|
||||
```
|
89
vendor/github.com/kubernetes-csi/csi-test/mock/cache/SnapshotCache.go
generated
vendored
89
vendor/github.com/kubernetes-csi/csi-test/mock/cache/SnapshotCache.go
generated
vendored
@@ -1,89 +0,0 @@
|
||||
package cache
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/container-storage-interface/spec/lib/go/csi"
|
||||
)
|
||||
|
||||
type SnapshotCache interface {
|
||||
Add(snapshot Snapshot)
|
||||
|
||||
Delete(i int)
|
||||
|
||||
List(ready bool) []csi.Snapshot
|
||||
|
||||
FindSnapshot(k, v string) (int, Snapshot)
|
||||
}
|
||||
|
||||
type Snapshot struct {
|
||||
Name string
|
||||
Parameters map[string]string
|
||||
SnapshotCSI csi.Snapshot
|
||||
}
|
||||
|
||||
type snapshotCache struct {
|
||||
snapshotsRWL sync.RWMutex
|
||||
snapshots []Snapshot
|
||||
}
|
||||
|
||||
func NewSnapshotCache() SnapshotCache {
|
||||
return &snapshotCache{
|
||||
snapshots: make([]Snapshot, 0),
|
||||
}
|
||||
}
|
||||
|
||||
func (snap *snapshotCache) Add(snapshot Snapshot) {
|
||||
snap.snapshotsRWL.Lock()
|
||||
defer snap.snapshotsRWL.Unlock()
|
||||
|
||||
snap.snapshots = append(snap.snapshots, snapshot)
|
||||
}
|
||||
|
||||
func (snap *snapshotCache) Delete(i int) {
|
||||
snap.snapshotsRWL.Lock()
|
||||
defer snap.snapshotsRWL.Unlock()
|
||||
|
||||
copy(snap.snapshots[i:], snap.snapshots[i+1:])
|
||||
snap.snapshots = snap.snapshots[:len(snap.snapshots)-1]
|
||||
}
|
||||
|
||||
func (snap *snapshotCache) List(ready bool) []csi.Snapshot {
|
||||
snap.snapshotsRWL.RLock()
|
||||
defer snap.snapshotsRWL.RUnlock()
|
||||
|
||||
snapshots := make([]csi.Snapshot, 0)
|
||||
for _, v := range snap.snapshots {
|
||||
if v.SnapshotCSI.GetReadyToUse() {
|
||||
snapshots = append(snapshots, v.SnapshotCSI)
|
||||
}
|
||||
}
|
||||
|
||||
return snapshots
|
||||
}
|
||||
|
||||
func (snap *snapshotCache) FindSnapshot(k, v string) (int, Snapshot) {
|
||||
snap.snapshotsRWL.RLock()
|
||||
defer snap.snapshotsRWL.RUnlock()
|
||||
|
||||
snapshotIdx := -1
|
||||
for i, vi := range snap.snapshots {
|
||||
switch k {
|
||||
case "id":
|
||||
if strings.EqualFold(v, vi.SnapshotCSI.GetSnapshotId()) {
|
||||
return i, vi
|
||||
}
|
||||
case "sourceVolumeId":
|
||||
if strings.EqualFold(v, vi.SnapshotCSI.SourceVolumeId) {
|
||||
return i, vi
|
||||
}
|
||||
case "name":
|
||||
if vi.Name == v {
|
||||
return i, vi
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return snapshotIdx, Snapshot{}
|
||||
}
|
95
vendor/github.com/kubernetes-csi/csi-test/mock/main.go
generated
vendored
95
vendor/github.com/kubernetes-csi/csi-test/mock/main.go
generated
vendored
@@ -1,95 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 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 (
|
||||
"flag"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/kubernetes-csi/csi-test/driver"
|
||||
"github.com/kubernetes-csi/csi-test/mock/service"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var config service.Config
|
||||
flag.BoolVar(&config.DisableAttach, "disable-attach", false, "Disables RPC_PUBLISH_UNPUBLISH_VOLUME capability.")
|
||||
flag.StringVar(&config.DriverName, "name", service.Name, "CSI driver name.")
|
||||
flag.Int64Var(&config.AttachLimit, "attach-limit", 0, "number of attachable volumes on a node")
|
||||
flag.Parse()
|
||||
|
||||
endpoint := os.Getenv("CSI_ENDPOINT")
|
||||
if len(endpoint) == 0 {
|
||||
fmt.Println("CSI_ENDPOINT must be defined and must be a path")
|
||||
os.Exit(1)
|
||||
}
|
||||
if strings.Contains(endpoint, ":") {
|
||||
fmt.Println("CSI_ENDPOINT must be a unix path")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Create mock driver
|
||||
s := service.New(config)
|
||||
servers := &driver.CSIDriverServers{
|
||||
Controller: s,
|
||||
Identity: s,
|
||||
Node: s,
|
||||
}
|
||||
d := driver.NewCSIDriver(servers)
|
||||
|
||||
// If creds is enabled, set the default creds.
|
||||
setCreds := os.Getenv("CSI_ENABLE_CREDS")
|
||||
if len(setCreds) > 0 && setCreds == "true" {
|
||||
d.SetDefaultCreds()
|
||||
}
|
||||
|
||||
// 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)
|
||||
os.Exit(1)
|
||||
}
|
||||
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)
|
||||
os.Exit(1)
|
||||
}
|
||||
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")
|
||||
}
|
16
vendor/github.com/kubernetes-csi/csi-test/mock/mocksecret.yaml
generated
vendored
16
vendor/github.com/kubernetes-csi/csi-test/mock/mocksecret.yaml
generated
vendored
@@ -1,16 +0,0 @@
|
||||
CreateVolumeSecret:
|
||||
secretKey: secretval1
|
||||
DeleteVolumeSecret:
|
||||
secretKey: secretval2
|
||||
ControllerPublishVolumeSecret:
|
||||
secretKey: secretval3
|
||||
ControllerUnpublishVolumeSecret:
|
||||
secretKey: secretval4
|
||||
NodeStageVolumeSecret:
|
||||
secretKey: secretval5
|
||||
NodePublishVolumeSecret:
|
||||
secretKey: secretval6
|
||||
CreateSnapshotSecret:
|
||||
secretKey: secretval7
|
||||
DeleteSnapshotSecret:
|
||||
secretKey: secretval8
|
577
vendor/github.com/kubernetes-csi/csi-test/mock/service/controller.go
generated
vendored
577
vendor/github.com/kubernetes-csi/csi-test/mock/service/controller.go
generated
vendored
@@ -1,577 +0,0 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"path"
|
||||
"reflect"
|
||||
"strconv"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
|
||||
"github.com/container-storage-interface/spec/lib/go/csi"
|
||||
)
|
||||
|
||||
const (
|
||||
MaxStorageCapacity = tib
|
||||
ReadOnlyKey = "readonly"
|
||||
)
|
||||
|
||||
func (s *service) CreateVolume(
|
||||
ctx context.Context,
|
||||
req *csi.CreateVolumeRequest) (
|
||||
*csi.CreateVolumeResponse, error) {
|
||||
|
||||
if len(req.Name) == 0 {
|
||||
return nil, status.Error(codes.InvalidArgument, "Volume Name cannot be empty")
|
||||
}
|
||||
if req.VolumeCapabilities == nil {
|
||||
return nil, status.Error(codes.InvalidArgument, "Volume Capabilities cannot be empty")
|
||||
}
|
||||
|
||||
// Check to see if the volume already exists.
|
||||
if i, v := s.findVolByName(ctx, req.Name); i >= 0 {
|
||||
// Requested volume name already exists, need to check if the existing volume's
|
||||
// capacity is more or equal to new request's capacity.
|
||||
if v.GetCapacityBytes() < req.GetCapacityRange().GetRequiredBytes() {
|
||||
return nil, status.Error(codes.AlreadyExists,
|
||||
fmt.Sprintf("Volume with name %s already exists", req.GetName()))
|
||||
}
|
||||
return &csi.CreateVolumeResponse{Volume: &v}, nil
|
||||
}
|
||||
|
||||
// If no capacity is specified then use 100GiB
|
||||
capacity := gib100
|
||||
if cr := req.CapacityRange; cr != nil {
|
||||
if rb := cr.RequiredBytes; rb > 0 {
|
||||
capacity = rb
|
||||
}
|
||||
if lb := cr.LimitBytes; lb > 0 {
|
||||
capacity = lb
|
||||
}
|
||||
}
|
||||
// Check for maximum available capacity
|
||||
if capacity >= MaxStorageCapacity {
|
||||
return nil, status.Errorf(codes.OutOfRange, "Requested capacity %d exceeds maximum allowed %d", capacity, MaxStorageCapacity)
|
||||
}
|
||||
// Create the volume and add it to the service's in-mem volume slice.
|
||||
v := s.newVolume(req.Name, capacity)
|
||||
s.volsRWL.Lock()
|
||||
defer s.volsRWL.Unlock()
|
||||
s.vols = append(s.vols, v)
|
||||
MockVolumes[v.GetVolumeId()] = Volume{
|
||||
VolumeCSI: v,
|
||||
NodeID: "",
|
||||
ISStaged: false,
|
||||
ISPublished: false,
|
||||
StageTargetPath: "",
|
||||
TargetPath: "",
|
||||
}
|
||||
|
||||
return &csi.CreateVolumeResponse{Volume: &v}, nil
|
||||
}
|
||||
|
||||
func (s *service) DeleteVolume(
|
||||
ctx context.Context,
|
||||
req *csi.DeleteVolumeRequest) (
|
||||
*csi.DeleteVolumeResponse, error) {
|
||||
|
||||
s.volsRWL.Lock()
|
||||
defer s.volsRWL.Unlock()
|
||||
|
||||
// If the volume is not specified, return error
|
||||
if len(req.VolumeId) == 0 {
|
||||
return nil, status.Error(codes.InvalidArgument, "Volume ID cannot be empty")
|
||||
}
|
||||
|
||||
// If the volume does not exist then return an idempotent response.
|
||||
i, _ := s.findVolNoLock("id", req.VolumeId)
|
||||
if i < 0 {
|
||||
return &csi.DeleteVolumeResponse{}, nil
|
||||
}
|
||||
|
||||
// This delete logic preserves order and prevents potential memory
|
||||
// leaks. The slice's elements may not be pointers, but the structs
|
||||
// themselves have fields that are.
|
||||
copy(s.vols[i:], s.vols[i+1:])
|
||||
s.vols[len(s.vols)-1] = csi.Volume{}
|
||||
s.vols = s.vols[:len(s.vols)-1]
|
||||
log.WithField("volumeID", req.VolumeId).Debug("mock delete volume")
|
||||
return &csi.DeleteVolumeResponse{}, nil
|
||||
}
|
||||
|
||||
func (s *service) ControllerPublishVolume(
|
||||
ctx context.Context,
|
||||
req *csi.ControllerPublishVolumeRequest) (
|
||||
*csi.ControllerPublishVolumeResponse, error) {
|
||||
|
||||
if s.config.DisableAttach {
|
||||
return nil, status.Error(codes.Unimplemented, "ControllerPublish is not supported")
|
||||
}
|
||||
|
||||
if len(req.VolumeId) == 0 {
|
||||
return nil, status.Error(codes.InvalidArgument, "Volume ID cannot be empty")
|
||||
}
|
||||
if len(req.NodeId) == 0 {
|
||||
return nil, status.Error(codes.InvalidArgument, "Node ID cannot be empty")
|
||||
}
|
||||
if req.VolumeCapability == nil {
|
||||
return nil, status.Error(codes.InvalidArgument, "Volume Capabilities cannot be empty")
|
||||
}
|
||||
|
||||
if req.NodeId != s.nodeID {
|
||||
return nil, status.Errorf(codes.NotFound, "Not matching Node ID %s to Mock Node ID %s", req.NodeId, s.nodeID)
|
||||
}
|
||||
|
||||
s.volsRWL.Lock()
|
||||
defer s.volsRWL.Unlock()
|
||||
|
||||
i, v := s.findVolNoLock("id", req.VolumeId)
|
||||
if i < 0 {
|
||||
return nil, status.Error(codes.NotFound, req.VolumeId)
|
||||
}
|
||||
|
||||
// devPathKey is the key in the volume's attributes that is set to a
|
||||
// mock device path if the volume has been published by the controller
|
||||
// to the specified node.
|
||||
devPathKey := path.Join(req.NodeId, "dev")
|
||||
|
||||
// Check to see if the volume is already published.
|
||||
if device := v.VolumeContext[devPathKey]; device != "" {
|
||||
var volRo bool
|
||||
var roVal string
|
||||
if ro, ok := v.VolumeContext[ReadOnlyKey]; ok {
|
||||
roVal = ro
|
||||
}
|
||||
|
||||
if roVal == "true" {
|
||||
volRo = true
|
||||
} else {
|
||||
volRo = false
|
||||
}
|
||||
|
||||
// Check if readonly flag is compatible with the publish request.
|
||||
if req.GetReadonly() != volRo {
|
||||
return nil, status.Error(codes.AlreadyExists, "Volume published but has incompatible readonly flag")
|
||||
}
|
||||
|
||||
return &csi.ControllerPublishVolumeResponse{
|
||||
PublishContext: map[string]string{
|
||||
"device": device,
|
||||
"readonly": roVal,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
var roVal string
|
||||
if req.GetReadonly() {
|
||||
roVal = "true"
|
||||
} else {
|
||||
roVal = "false"
|
||||
}
|
||||
|
||||
// Publish the volume.
|
||||
device := "/dev/mock"
|
||||
v.VolumeContext[devPathKey] = device
|
||||
v.VolumeContext[ReadOnlyKey] = roVal
|
||||
s.vols[i] = v
|
||||
|
||||
return &csi.ControllerPublishVolumeResponse{
|
||||
PublishContext: map[string]string{
|
||||
"device": device,
|
||||
"readonly": roVal,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *service) ControllerUnpublishVolume(
|
||||
ctx context.Context,
|
||||
req *csi.ControllerUnpublishVolumeRequest) (
|
||||
*csi.ControllerUnpublishVolumeResponse, error) {
|
||||
|
||||
if s.config.DisableAttach {
|
||||
return nil, status.Error(codes.Unimplemented, "ControllerPublish is not supported")
|
||||
}
|
||||
|
||||
if len(req.VolumeId) == 0 {
|
||||
return nil, status.Error(codes.InvalidArgument, "Volume ID cannot be empty")
|
||||
}
|
||||
nodeID := req.NodeId
|
||||
if len(nodeID) == 0 {
|
||||
// If node id is empty, no failure as per Spec
|
||||
nodeID = s.nodeID
|
||||
}
|
||||
|
||||
if req.NodeId != s.nodeID {
|
||||
return nil, status.Errorf(codes.NotFound, "Node ID %s does not match to expected Node ID %s", req.NodeId, s.nodeID)
|
||||
}
|
||||
|
||||
s.volsRWL.Lock()
|
||||
defer s.volsRWL.Unlock()
|
||||
|
||||
i, v := s.findVolNoLock("id", req.VolumeId)
|
||||
if i < 0 {
|
||||
return nil, status.Error(codes.NotFound, req.VolumeId)
|
||||
}
|
||||
|
||||
// devPathKey is the key in the volume's attributes that is set to a
|
||||
// mock device path if the volume has been published by the controller
|
||||
// to the specified node.
|
||||
devPathKey := path.Join(nodeID, "dev")
|
||||
|
||||
// Check to see if the volume is already unpublished.
|
||||
if v.VolumeContext[devPathKey] == "" {
|
||||
return &csi.ControllerUnpublishVolumeResponse{}, nil
|
||||
}
|
||||
|
||||
// Unpublish the volume.
|
||||
delete(v.VolumeContext, devPathKey)
|
||||
delete(v.VolumeContext, ReadOnlyKey)
|
||||
s.vols[i] = v
|
||||
|
||||
return &csi.ControllerUnpublishVolumeResponse{}, nil
|
||||
}
|
||||
|
||||
func (s *service) ValidateVolumeCapabilities(
|
||||
ctx context.Context,
|
||||
req *csi.ValidateVolumeCapabilitiesRequest) (
|
||||
*csi.ValidateVolumeCapabilitiesResponse, error) {
|
||||
|
||||
if len(req.GetVolumeId()) == 0 {
|
||||
return nil, status.Error(codes.InvalidArgument, "Volume ID cannot be empty")
|
||||
}
|
||||
if len(req.VolumeCapabilities) == 0 {
|
||||
return nil, status.Error(codes.InvalidArgument, req.VolumeId)
|
||||
}
|
||||
i, _ := s.findVolNoLock("id", req.VolumeId)
|
||||
if i < 0 {
|
||||
return nil, status.Error(codes.NotFound, req.VolumeId)
|
||||
}
|
||||
|
||||
return &csi.ValidateVolumeCapabilitiesResponse{
|
||||
Confirmed: &csi.ValidateVolumeCapabilitiesResponse_Confirmed{
|
||||
VolumeContext: req.GetVolumeContext(),
|
||||
VolumeCapabilities: req.GetVolumeCapabilities(),
|
||||
Parameters: req.GetParameters(),
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *service) ListVolumes(
|
||||
ctx context.Context,
|
||||
req *csi.ListVolumesRequest) (
|
||||
*csi.ListVolumesResponse, error) {
|
||||
|
||||
// Copy the mock volumes into a new slice in order to avoid
|
||||
// locking the service's volume slice for the duration of the
|
||||
// ListVolumes RPC.
|
||||
var vols []csi.Volume
|
||||
func() {
|
||||
s.volsRWL.RLock()
|
||||
defer s.volsRWL.RUnlock()
|
||||
vols = make([]csi.Volume, len(s.vols))
|
||||
copy(vols, s.vols)
|
||||
}()
|
||||
|
||||
var (
|
||||
ulenVols = int32(len(vols))
|
||||
maxEntries = req.MaxEntries
|
||||
startingToken int32
|
||||
)
|
||||
|
||||
if v := req.StartingToken; v != "" {
|
||||
i, err := strconv.ParseUint(v, 10, 32)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(
|
||||
codes.InvalidArgument,
|
||||
"startingToken=%d !< int32=%d",
|
||||
startingToken, math.MaxUint32)
|
||||
}
|
||||
startingToken = int32(i)
|
||||
}
|
||||
|
||||
if startingToken > ulenVols {
|
||||
return nil, status.Errorf(
|
||||
codes.InvalidArgument,
|
||||
"startingToken=%d > len(vols)=%d",
|
||||
startingToken, ulenVols)
|
||||
}
|
||||
|
||||
// Discern the number of remaining entries.
|
||||
rem := ulenVols - startingToken
|
||||
|
||||
// If maxEntries is 0 or greater than the number of remaining entries then
|
||||
// set maxEntries to the number of remaining entries.
|
||||
if maxEntries == 0 || maxEntries > rem {
|
||||
maxEntries = rem
|
||||
}
|
||||
|
||||
var (
|
||||
i int
|
||||
j = startingToken
|
||||
entries = make(
|
||||
[]*csi.ListVolumesResponse_Entry,
|
||||
maxEntries)
|
||||
)
|
||||
|
||||
for i = 0; i < len(entries); i++ {
|
||||
entries[i] = &csi.ListVolumesResponse_Entry{
|
||||
Volume: &vols[j],
|
||||
}
|
||||
j++
|
||||
}
|
||||
|
||||
var nextToken string
|
||||
if n := startingToken + int32(i); n < ulenVols {
|
||||
nextToken = fmt.Sprintf("%d", n)
|
||||
}
|
||||
|
||||
return &csi.ListVolumesResponse{
|
||||
Entries: entries,
|
||||
NextToken: nextToken,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *service) GetCapacity(
|
||||
ctx context.Context,
|
||||
req *csi.GetCapacityRequest) (
|
||||
*csi.GetCapacityResponse, error) {
|
||||
|
||||
return &csi.GetCapacityResponse{
|
||||
AvailableCapacity: MaxStorageCapacity,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *service) ControllerGetCapabilities(
|
||||
ctx context.Context,
|
||||
req *csi.ControllerGetCapabilitiesRequest) (
|
||||
*csi.ControllerGetCapabilitiesResponse, error) {
|
||||
|
||||
caps := []*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_LIST_VOLUMES,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: &csi.ControllerServiceCapability_Rpc{
|
||||
Rpc: &csi.ControllerServiceCapability_RPC{
|
||||
Type: csi.ControllerServiceCapability_RPC_GET_CAPACITY,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: &csi.ControllerServiceCapability_Rpc{
|
||||
Rpc: &csi.ControllerServiceCapability_RPC{
|
||||
Type: csi.ControllerServiceCapability_RPC_LIST_SNAPSHOTS,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: &csi.ControllerServiceCapability_Rpc{
|
||||
Rpc: &csi.ControllerServiceCapability_RPC{
|
||||
Type: csi.ControllerServiceCapability_RPC_CREATE_DELETE_SNAPSHOT,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
if !s.config.DisableAttach {
|
||||
caps = append(caps, &csi.ControllerServiceCapability{
|
||||
Type: &csi.ControllerServiceCapability_Rpc{
|
||||
Rpc: &csi.ControllerServiceCapability_RPC{
|
||||
Type: csi.ControllerServiceCapability_RPC_PUBLISH_UNPUBLISH_VOLUME,
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
return &csi.ControllerGetCapabilitiesResponse{
|
||||
Capabilities: caps,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *service) CreateSnapshot(ctx context.Context,
|
||||
req *csi.CreateSnapshotRequest) (*csi.CreateSnapshotResponse, error) {
|
||||
// Check arguments
|
||||
if len(req.GetName()) == 0 {
|
||||
return nil, status.Error(codes.InvalidArgument, "Snapshot Name cannot be empty")
|
||||
}
|
||||
if len(req.GetSourceVolumeId()) == 0 {
|
||||
return nil, status.Error(codes.InvalidArgument, "Snapshot SourceVolumeId cannot be empty")
|
||||
}
|
||||
|
||||
// Check to see if the snapshot already exists.
|
||||
if i, v := s.snapshots.FindSnapshot("name", req.GetName()); i >= 0 {
|
||||
// Requested snapshot name already exists
|
||||
if v.SnapshotCSI.GetSourceVolumeId() != req.GetSourceVolumeId() || !reflect.DeepEqual(v.Parameters, req.GetParameters()) {
|
||||
return nil, status.Error(codes.AlreadyExists,
|
||||
fmt.Sprintf("Snapshot with name %s already exists", req.GetName()))
|
||||
}
|
||||
return &csi.CreateSnapshotResponse{Snapshot: &v.SnapshotCSI}, nil
|
||||
}
|
||||
|
||||
// Create the snapshot and add it to the service's in-mem snapshot slice.
|
||||
snapshot := s.newSnapshot(req.GetName(), req.GetSourceVolumeId(), req.GetParameters())
|
||||
s.snapshots.Add(snapshot)
|
||||
|
||||
return &csi.CreateSnapshotResponse{Snapshot: &snapshot.SnapshotCSI}, nil
|
||||
}
|
||||
|
||||
func (s *service) DeleteSnapshot(ctx context.Context,
|
||||
req *csi.DeleteSnapshotRequest) (*csi.DeleteSnapshotResponse, error) {
|
||||
|
||||
// If the snapshot is not specified, return error
|
||||
if len(req.SnapshotId) == 0 {
|
||||
return nil, status.Error(codes.InvalidArgument, "Snapshot ID cannot be empty")
|
||||
}
|
||||
|
||||
// If the snapshot does not exist then return an idempotent response.
|
||||
i, _ := s.snapshots.FindSnapshot("id", req.SnapshotId)
|
||||
if i < 0 {
|
||||
return &csi.DeleteSnapshotResponse{}, nil
|
||||
}
|
||||
|
||||
// This delete logic preserves order and prevents potential memory
|
||||
// leaks. The slice's elements may not be pointers, but the structs
|
||||
// themselves have fields that are.
|
||||
s.snapshots.Delete(i)
|
||||
log.WithField("SnapshotId", req.SnapshotId).Debug("mock delete snapshot")
|
||||
return &csi.DeleteSnapshotResponse{}, nil
|
||||
}
|
||||
|
||||
func (s *service) ListSnapshots(ctx context.Context,
|
||||
req *csi.ListSnapshotsRequest) (*csi.ListSnapshotsResponse, error) {
|
||||
|
||||
// case 1: SnapshotId is not empty, return snapshots that match the snapshot id.
|
||||
if len(req.GetSnapshotId()) != 0 {
|
||||
return getSnapshotById(s, req)
|
||||
}
|
||||
|
||||
// case 2: SourceVolumeId is not empty, return snapshots that match the source volume id.
|
||||
if len(req.GetSourceVolumeId()) != 0 {
|
||||
return getSnapshotByVolumeId(s, req)
|
||||
}
|
||||
|
||||
// case 3: no parameter is set, so we return all the snapshots.
|
||||
return getAllSnapshots(s, req)
|
||||
}
|
||||
|
||||
func getSnapshotById(s *service, req *csi.ListSnapshotsRequest) (*csi.ListSnapshotsResponse, error) {
|
||||
if len(req.GetSnapshotId()) != 0 {
|
||||
i, snapshot := s.snapshots.FindSnapshot("id", req.GetSnapshotId())
|
||||
if i < 0 {
|
||||
return &csi.ListSnapshotsResponse{}, nil
|
||||
}
|
||||
|
||||
if len(req.GetSourceVolumeId()) != 0 {
|
||||
if snapshot.SnapshotCSI.GetSourceVolumeId() != req.GetSourceVolumeId() {
|
||||
return &csi.ListSnapshotsResponse{}, nil
|
||||
}
|
||||
}
|
||||
|
||||
return &csi.ListSnapshotsResponse{
|
||||
Entries: []*csi.ListSnapshotsResponse_Entry{
|
||||
{
|
||||
Snapshot: &snapshot.SnapshotCSI,
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func getSnapshotByVolumeId(s *service, req *csi.ListSnapshotsRequest) (*csi.ListSnapshotsResponse, error) {
|
||||
if len(req.GetSourceVolumeId()) != 0 {
|
||||
i, snapshot := s.snapshots.FindSnapshot("sourceVolumeId", req.SourceVolumeId)
|
||||
if i < 0 {
|
||||
return &csi.ListSnapshotsResponse{}, nil
|
||||
}
|
||||
return &csi.ListSnapshotsResponse{
|
||||
Entries: []*csi.ListSnapshotsResponse_Entry{
|
||||
{
|
||||
Snapshot: &snapshot.SnapshotCSI,
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func getAllSnapshots(s *service, req *csi.ListSnapshotsRequest) (*csi.ListSnapshotsResponse, error) {
|
||||
// Copy the mock snapshots into a new slice in order to avoid
|
||||
// locking the service's snapshot slice for the duration of the
|
||||
// ListSnapshots RPC.
|
||||
readyToUse := true
|
||||
snapshots := s.snapshots.List(readyToUse)
|
||||
|
||||
var (
|
||||
ulenSnapshots = int32(len(snapshots))
|
||||
maxEntries = req.MaxEntries
|
||||
startingToken int32
|
||||
)
|
||||
|
||||
if v := req.StartingToken; v != "" {
|
||||
i, err := strconv.ParseUint(v, 10, 32)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(
|
||||
codes.Aborted,
|
||||
"startingToken=%d !< int32=%d",
|
||||
startingToken, math.MaxUint32)
|
||||
}
|
||||
startingToken = int32(i)
|
||||
}
|
||||
|
||||
if startingToken > ulenSnapshots {
|
||||
return nil, status.Errorf(
|
||||
codes.Aborted,
|
||||
"startingToken=%d > len(snapshots)=%d",
|
||||
startingToken, ulenSnapshots)
|
||||
}
|
||||
|
||||
// Discern the number of remaining entries.
|
||||
rem := ulenSnapshots - startingToken
|
||||
|
||||
// If maxEntries is 0 or greater than the number of remaining entries then
|
||||
// set maxEntries to the number of remaining entries.
|
||||
if maxEntries == 0 || maxEntries > rem {
|
||||
maxEntries = rem
|
||||
}
|
||||
|
||||
var (
|
||||
i int
|
||||
j = startingToken
|
||||
entries = make(
|
||||
[]*csi.ListSnapshotsResponse_Entry,
|
||||
maxEntries)
|
||||
)
|
||||
|
||||
for i = 0; i < len(entries); i++ {
|
||||
entries[i] = &csi.ListSnapshotsResponse_Entry{
|
||||
Snapshot: &snapshots[j],
|
||||
}
|
||||
j++
|
||||
}
|
||||
|
||||
var nextToken string
|
||||
if n := startingToken + int32(i); n < ulenSnapshots {
|
||||
nextToken = fmt.Sprintf("%d", n)
|
||||
}
|
||||
|
||||
return &csi.ListSnapshotsResponse{
|
||||
Entries: entries,
|
||||
NextToken: nextToken,
|
||||
}, nil
|
||||
}
|
48
vendor/github.com/kubernetes-csi/csi-test/mock/service/identity.go
generated
vendored
48
vendor/github.com/kubernetes-csi/csi-test/mock/service/identity.go
generated
vendored
@@ -1,48 +0,0 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"github.com/container-storage-interface/spec/lib/go/csi"
|
||||
"github.com/golang/protobuf/ptypes/wrappers"
|
||||
)
|
||||
|
||||
func (s *service) GetPluginInfo(
|
||||
ctx context.Context,
|
||||
req *csi.GetPluginInfoRequest) (
|
||||
*csi.GetPluginInfoResponse, error) {
|
||||
|
||||
return &csi.GetPluginInfoResponse{
|
||||
Name: s.config.DriverName,
|
||||
VendorVersion: VendorVersion,
|
||||
Manifest: Manifest,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *service) Probe(
|
||||
ctx context.Context,
|
||||
req *csi.ProbeRequest) (
|
||||
*csi.ProbeResponse, error) {
|
||||
|
||||
return &csi.ProbeResponse{
|
||||
Ready: &wrappers.BoolValue{Value: true},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *service) GetPluginCapabilities(
|
||||
ctx context.Context,
|
||||
req *csi.GetPluginCapabilitiesRequest) (
|
||||
*csi.GetPluginCapabilitiesResponse, error) {
|
||||
|
||||
return &csi.GetPluginCapabilitiesResponse{
|
||||
Capabilities: []*csi.PluginCapability{
|
||||
{
|
||||
Type: &csi.PluginCapability_Service_{
|
||||
Service: &csi.PluginCapability_Service{
|
||||
Type: csi.PluginCapability_Service_CONTROLLER_SERVICE,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
}
|
244
vendor/github.com/kubernetes-csi/csi-test/mock/service/node.go
generated
vendored
244
vendor/github.com/kubernetes-csi/csi-test/mock/service/node.go
generated
vendored
@@ -1,244 +0,0 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"path"
|
||||
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"github.com/container-storage-interface/spec/lib/go/csi"
|
||||
)
|
||||
|
||||
func (s *service) NodeStageVolume(
|
||||
ctx context.Context,
|
||||
req *csi.NodeStageVolumeRequest) (
|
||||
*csi.NodeStageVolumeResponse, error) {
|
||||
|
||||
device, ok := req.PublishContext["device"]
|
||||
if !ok {
|
||||
if s.config.DisableAttach {
|
||||
device = "mock device"
|
||||
} else {
|
||||
return nil, status.Error(
|
||||
codes.InvalidArgument,
|
||||
"stage volume info 'device' key required")
|
||||
}
|
||||
}
|
||||
|
||||
if len(req.GetVolumeId()) == 0 {
|
||||
return nil, status.Error(codes.InvalidArgument, "Volume ID cannot be empty")
|
||||
}
|
||||
|
||||
if len(req.GetStagingTargetPath()) == 0 {
|
||||
return nil, status.Error(codes.InvalidArgument, "Staging Target Path cannot be empty")
|
||||
}
|
||||
|
||||
if req.GetVolumeCapability() == nil {
|
||||
return nil, status.Error(codes.InvalidArgument, "Volume Capability cannot be empty")
|
||||
}
|
||||
|
||||
s.volsRWL.Lock()
|
||||
defer s.volsRWL.Unlock()
|
||||
|
||||
i, v := s.findVolNoLock("id", req.VolumeId)
|
||||
if i < 0 {
|
||||
return nil, status.Error(codes.NotFound, req.VolumeId)
|
||||
}
|
||||
|
||||
// nodeStgPathKey is the key in the volume's attributes that is set to a
|
||||
// mock stage path if the volume has been published by the node
|
||||
nodeStgPathKey := path.Join(s.nodeID, req.StagingTargetPath)
|
||||
|
||||
// Check to see if the volume has already been staged.
|
||||
if v.VolumeContext[nodeStgPathKey] != "" {
|
||||
// TODO: Check for the capabilities to be equal. Return "ALREADY_EXISTS"
|
||||
// if the capabilities don't match.
|
||||
return &csi.NodeStageVolumeResponse{}, nil
|
||||
}
|
||||
|
||||
// Stage the volume.
|
||||
v.VolumeContext[nodeStgPathKey] = device
|
||||
s.vols[i] = v
|
||||
|
||||
return &csi.NodeStageVolumeResponse{}, nil
|
||||
}
|
||||
|
||||
func (s *service) NodeUnstageVolume(
|
||||
ctx context.Context,
|
||||
req *csi.NodeUnstageVolumeRequest) (
|
||||
*csi.NodeUnstageVolumeResponse, error) {
|
||||
|
||||
if len(req.GetVolumeId()) == 0 {
|
||||
return nil, status.Error(codes.InvalidArgument, "Volume ID cannot be empty")
|
||||
}
|
||||
|
||||
if len(req.GetStagingTargetPath()) == 0 {
|
||||
return nil, status.Error(codes.InvalidArgument, "Staging Target Path cannot be empty")
|
||||
}
|
||||
|
||||
s.volsRWL.Lock()
|
||||
defer s.volsRWL.Unlock()
|
||||
|
||||
i, v := s.findVolNoLock("id", req.VolumeId)
|
||||
if i < 0 {
|
||||
return nil, status.Error(codes.NotFound, req.VolumeId)
|
||||
}
|
||||
|
||||
// nodeStgPathKey is the key in the volume's attributes that is set to a
|
||||
// mock stage path if the volume has been published by the node
|
||||
nodeStgPathKey := path.Join(s.nodeID, req.StagingTargetPath)
|
||||
|
||||
// Check to see if the volume has already been unstaged.
|
||||
if v.VolumeContext[nodeStgPathKey] == "" {
|
||||
return &csi.NodeUnstageVolumeResponse{}, nil
|
||||
}
|
||||
|
||||
// Unpublish the volume.
|
||||
delete(v.VolumeContext, nodeStgPathKey)
|
||||
s.vols[i] = v
|
||||
|
||||
return &csi.NodeUnstageVolumeResponse{}, nil
|
||||
}
|
||||
|
||||
func (s *service) NodePublishVolume(
|
||||
ctx context.Context,
|
||||
req *csi.NodePublishVolumeRequest) (
|
||||
*csi.NodePublishVolumeResponse, error) {
|
||||
|
||||
device, ok := req.PublishContext["device"]
|
||||
if !ok {
|
||||
if s.config.DisableAttach {
|
||||
device = "mock device"
|
||||
} else {
|
||||
return nil, status.Error(
|
||||
codes.InvalidArgument,
|
||||
"stage volume info 'device' key required")
|
||||
}
|
||||
}
|
||||
|
||||
if len(req.GetVolumeId()) == 0 {
|
||||
return nil, status.Error(codes.InvalidArgument, "Volume ID cannot be empty")
|
||||
}
|
||||
|
||||
if len(req.GetTargetPath()) == 0 {
|
||||
return nil, status.Error(codes.InvalidArgument, "Target Path cannot be empty")
|
||||
}
|
||||
|
||||
if req.GetVolumeCapability() == nil {
|
||||
return nil, status.Error(codes.InvalidArgument, "Volume Capability cannot be empty")
|
||||
}
|
||||
|
||||
s.volsRWL.Lock()
|
||||
defer s.volsRWL.Unlock()
|
||||
|
||||
i, v := s.findVolNoLock("id", req.VolumeId)
|
||||
if i < 0 {
|
||||
return nil, status.Error(codes.NotFound, req.VolumeId)
|
||||
}
|
||||
|
||||
// nodeMntPathKey is the key in the volume's attributes that is set to a
|
||||
// mock mount path if the volume has been published by the node
|
||||
nodeMntPathKey := path.Join(s.nodeID, req.TargetPath)
|
||||
|
||||
// Check to see if the volume has already been published.
|
||||
if v.VolumeContext[nodeMntPathKey] != "" {
|
||||
|
||||
// Requests marked Readonly fail due to volumes published by
|
||||
// the Mock driver supporting only RW mode.
|
||||
if req.Readonly {
|
||||
return nil, status.Error(codes.AlreadyExists, req.VolumeId)
|
||||
}
|
||||
|
||||
return &csi.NodePublishVolumeResponse{}, nil
|
||||
}
|
||||
|
||||
// Publish the volume.
|
||||
if req.GetStagingTargetPath() != "" {
|
||||
v.VolumeContext[nodeMntPathKey] = req.GetStagingTargetPath()
|
||||
} else {
|
||||
v.VolumeContext[nodeMntPathKey] = device
|
||||
}
|
||||
s.vols[i] = v
|
||||
|
||||
return &csi.NodePublishVolumeResponse{}, nil
|
||||
}
|
||||
|
||||
func (s *service) NodeUnpublishVolume(
|
||||
ctx context.Context,
|
||||
req *csi.NodeUnpublishVolumeRequest) (
|
||||
*csi.NodeUnpublishVolumeResponse, error) {
|
||||
|
||||
if len(req.GetVolumeId()) == 0 {
|
||||
return nil, status.Error(codes.InvalidArgument, "Volume ID cannot be empty")
|
||||
}
|
||||
if len(req.GetTargetPath()) == 0 {
|
||||
return nil, status.Error(codes.InvalidArgument, "Target Path cannot be empty")
|
||||
}
|
||||
|
||||
s.volsRWL.Lock()
|
||||
defer s.volsRWL.Unlock()
|
||||
|
||||
i, v := s.findVolNoLock("id", req.VolumeId)
|
||||
if i < 0 {
|
||||
return nil, status.Error(codes.NotFound, req.VolumeId)
|
||||
}
|
||||
|
||||
// nodeMntPathKey is the key in the volume's attributes that is set to a
|
||||
// mock mount path if the volume has been published by the node
|
||||
nodeMntPathKey := path.Join(s.nodeID, req.TargetPath)
|
||||
|
||||
// Check to see if the volume has already been unpublished.
|
||||
if v.VolumeContext[nodeMntPathKey] == "" {
|
||||
return &csi.NodeUnpublishVolumeResponse{}, nil
|
||||
}
|
||||
|
||||
// Unpublish the volume.
|
||||
delete(v.VolumeContext, nodeMntPathKey)
|
||||
s.vols[i] = v
|
||||
|
||||
return &csi.NodeUnpublishVolumeResponse{}, nil
|
||||
}
|
||||
|
||||
func (s *service) NodeGetCapabilities(
|
||||
ctx context.Context,
|
||||
req *csi.NodeGetCapabilitiesRequest) (
|
||||
*csi.NodeGetCapabilitiesResponse, error) {
|
||||
|
||||
return &csi.NodeGetCapabilitiesResponse{
|
||||
Capabilities: []*csi.NodeServiceCapability{
|
||||
{
|
||||
Type: &csi.NodeServiceCapability_Rpc{
|
||||
Rpc: &csi.NodeServiceCapability_RPC{
|
||||
Type: csi.NodeServiceCapability_RPC_UNKNOWN,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: &csi.NodeServiceCapability_Rpc{
|
||||
Rpc: &csi.NodeServiceCapability_RPC{
|
||||
Type: csi.NodeServiceCapability_RPC_STAGE_UNSTAGE_VOLUME,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *service) NodeGetInfo(ctx context.Context,
|
||||
req *csi.NodeGetInfoRequest) (*csi.NodeGetInfoResponse, error) {
|
||||
csiNodeResponse := &csi.NodeGetInfoResponse{
|
||||
NodeId: s.nodeID,
|
||||
}
|
||||
if s.config.AttachLimit > 0 {
|
||||
csiNodeResponse.MaxVolumesPerNode = s.config.AttachLimit
|
||||
}
|
||||
return csiNodeResponse, nil
|
||||
}
|
||||
|
||||
func (s *service) NodeGetVolumeStats(ctx context.Context,
|
||||
req *csi.NodeGetVolumeStatsRequest) (*csi.NodeGetVolumeStatsResponse, error) {
|
||||
return &csi.NodeGetVolumeStatsResponse{}, nil
|
||||
|
||||
}
|
147
vendor/github.com/kubernetes-csi/csi-test/mock/service/service.go
generated
vendored
147
vendor/github.com/kubernetes-csi/csi-test/mock/service/service.go
generated
vendored
@@ -1,147 +0,0 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/container-storage-interface/spec/lib/go/csi"
|
||||
"github.com/kubernetes-csi/csi-test/mock/cache"
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"github.com/golang/protobuf/ptypes"
|
||||
)
|
||||
|
||||
const (
|
||||
// Name is the name of the CSI plug-in.
|
||||
Name = "io.kubernetes.storage.mock"
|
||||
|
||||
// VendorVersion is the version returned by GetPluginInfo.
|
||||
VendorVersion = "0.3.0"
|
||||
)
|
||||
|
||||
// Manifest is the SP's manifest.
|
||||
var Manifest = map[string]string{
|
||||
"url": "https://github.com/kubernetes-csi/csi-test/mock",
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
DisableAttach bool
|
||||
DriverName string
|
||||
AttachLimit int64
|
||||
}
|
||||
|
||||
// Service is the CSI Mock service provider.
|
||||
type Service interface {
|
||||
csi.ControllerServer
|
||||
csi.IdentityServer
|
||||
csi.NodeServer
|
||||
}
|
||||
|
||||
type service struct {
|
||||
sync.Mutex
|
||||
nodeID string
|
||||
vols []csi.Volume
|
||||
volsRWL sync.RWMutex
|
||||
volsNID uint64
|
||||
snapshots cache.SnapshotCache
|
||||
snapshotsNID uint64
|
||||
config Config
|
||||
}
|
||||
|
||||
type Volume struct {
|
||||
sync.Mutex
|
||||
VolumeCSI csi.Volume
|
||||
NodeID string
|
||||
ISStaged bool
|
||||
ISPublished bool
|
||||
StageTargetPath string
|
||||
TargetPath string
|
||||
}
|
||||
|
||||
var MockVolumes map[string]Volume
|
||||
|
||||
// New returns a new Service.
|
||||
func New(config Config) Service {
|
||||
s := &service{
|
||||
nodeID: config.DriverName,
|
||||
config: config,
|
||||
}
|
||||
s.snapshots = cache.NewSnapshotCache()
|
||||
s.vols = []csi.Volume{
|
||||
s.newVolume("Mock Volume 1", gib100),
|
||||
s.newVolume("Mock Volume 2", gib100),
|
||||
s.newVolume("Mock Volume 3", gib100),
|
||||
}
|
||||
MockVolumes = map[string]Volume{}
|
||||
|
||||
s.snapshots.Add(s.newSnapshot("Mock Snapshot 1", "1", map[string]string{"Description": "snapshot 1"}))
|
||||
s.snapshots.Add(s.newSnapshot("Mock Snapshot 2", "2", map[string]string{"Description": "snapshot 2"}))
|
||||
s.snapshots.Add(s.newSnapshot("Mock Snapshot 3", "3", map[string]string{"Description": "snapshot 3"}))
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
const (
|
||||
kib int64 = 1024
|
||||
mib int64 = kib * 1024
|
||||
gib int64 = mib * 1024
|
||||
gib100 int64 = gib * 100
|
||||
tib int64 = gib * 1024
|
||||
tib100 int64 = tib * 100
|
||||
)
|
||||
|
||||
func (s *service) newVolume(name string, capcity int64) csi.Volume {
|
||||
return csi.Volume{
|
||||
VolumeId: fmt.Sprintf("%d", atomic.AddUint64(&s.volsNID, 1)),
|
||||
VolumeContext: map[string]string{"name": name},
|
||||
CapacityBytes: capcity,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *service) findVol(k, v string) (volIdx int, volInfo csi.Volume) {
|
||||
s.volsRWL.RLock()
|
||||
defer s.volsRWL.RUnlock()
|
||||
return s.findVolNoLock(k, v)
|
||||
}
|
||||
|
||||
func (s *service) findVolNoLock(k, v string) (volIdx int, volInfo csi.Volume) {
|
||||
volIdx = -1
|
||||
|
||||
for i, vi := range s.vols {
|
||||
switch k {
|
||||
case "id":
|
||||
if strings.EqualFold(v, vi.GetVolumeId()) {
|
||||
return i, vi
|
||||
}
|
||||
case "name":
|
||||
if n, ok := vi.VolumeContext["name"]; ok && strings.EqualFold(v, n) {
|
||||
return i, vi
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (s *service) findVolByName(
|
||||
ctx context.Context, name string) (int, csi.Volume) {
|
||||
|
||||
return s.findVol("name", name)
|
||||
}
|
||||
|
||||
func (s *service) newSnapshot(name, sourceVolumeId string, parameters map[string]string) cache.Snapshot {
|
||||
|
||||
ptime := ptypes.TimestampNow()
|
||||
return cache.Snapshot{
|
||||
Name: name,
|
||||
Parameters: parameters,
|
||||
SnapshotCSI: csi.Snapshot{
|
||||
SnapshotId: fmt.Sprintf("%d", atomic.AddUint64(&s.snapshotsNID, 1)),
|
||||
CreationTime: ptime,
|
||||
SourceVolumeId: sourceVolumeId,
|
||||
ReadyToUse: true,
|
||||
},
|
||||
}
|
||||
}
|
62
vendor/github.com/kubernetes-csi/csi-test/pkg/sanity/README.md
generated
vendored
62
vendor/github.com/kubernetes-csi/csi-test/pkg/sanity/README.md
generated
vendored
@@ -1,62 +0,0 @@
|
||||
# CSI Driver Sanity Tester
|
||||
|
||||
This library provides a simple way to ensure that a CSI driver conforms to
|
||||
the CSI specification. There are two ways to leverage this testing framework.
|
||||
For CSI drivers written in Golang, the framework provides a simple API function
|
||||
to call to test the driver. Another way to run the test suite is to use the
|
||||
command line program [csi-sanity](https://github.com/kubernetes-csi/csi-test/tree/master/cmd/csi-sanity).
|
||||
|
||||
## For Golang CSI Drivers
|
||||
This framework leverages the Ginkgo BDD testing framework to deliver a descriptive
|
||||
test suite for your driver. To test your driver, simply call the API in one of your
|
||||
Golang `TestXXX` functions. For example:
|
||||
|
||||
```go
|
||||
func TestMyDriver(t *testing.T) {
|
||||
// Setup the full driver and its environment
|
||||
... setup driver ...
|
||||
config := &sanity.Config{
|
||||
TargetPath: ...
|
||||
StagingPath: ...
|
||||
Address: endpoint,
|
||||
}
|
||||
|
||||
|
||||
// Now call the test suite
|
||||
sanity.Test(t, config)
|
||||
}
|
||||
```
|
||||
|
||||
Only one such test function is supported because under the hood a
|
||||
Ginkgo test suite gets constructed and executed by the call.
|
||||
|
||||
Alternatively, the tests can also be embedded inside a Ginkgo test
|
||||
suite. In that case it is possible to define multiple tests with
|
||||
different configurations:
|
||||
|
||||
```go
|
||||
var _ = Describe("MyCSIDriver", func () {
|
||||
Context("Config A", func () {
|
||||
var config &sanity.Config
|
||||
|
||||
BeforeEach(func() {
|
||||
//... setup driver and config...
|
||||
})
|
||||
|
||||
AfterEach(func() {
|
||||
//...tear down driver...
|
||||
})
|
||||
|
||||
Describe("CSI sanity", func() {
|
||||
sanity.GinkgoTest(config)
|
||||
})
|
||||
})
|
||||
|
||||
Context("Config B", func () {
|
||||
// other configs
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
## Command line program
|
||||
Please see [csi-sanity](https://github.com/kubernetes-csi/csi-test/tree/master/cmd/csi-sanity)
|
134
vendor/github.com/kubernetes-csi/csi-test/pkg/sanity/cleanup.go
generated
vendored
134
vendor/github.com/kubernetes-csi/csi-test/pkg/sanity/cleanup.go
generated
vendored
@@ -1,134 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 Intel Corporation
|
||||
|
||||
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 sanity
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
|
||||
"github.com/container-storage-interface/spec/lib/go/csi"
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
)
|
||||
|
||||
// VolumeInfo keeps track of the information needed to delete a volume.
|
||||
type VolumeInfo struct {
|
||||
// Node on which the volume was published, empty if none
|
||||
// or publishing is not supported.
|
||||
NodeID string
|
||||
|
||||
// Volume ID assigned by CreateVolume.
|
||||
VolumeID string
|
||||
}
|
||||
|
||||
// Cleanup keeps track of resources, in particular volumes, which need
|
||||
// to be freed when testing is done.
|
||||
type Cleanup struct {
|
||||
Context *SanityContext
|
||||
ControllerClient csi.ControllerClient
|
||||
NodeClient csi.NodeClient
|
||||
ControllerPublishSupported bool
|
||||
NodeStageSupported bool
|
||||
|
||||
// Maps from volume name to the node ID for which the volume
|
||||
// is published and the volume ID.
|
||||
volumes map[string]VolumeInfo
|
||||
}
|
||||
|
||||
// RegisterVolume adds or updates an entry for the volume with the
|
||||
// given name.
|
||||
func (cl *Cleanup) RegisterVolume(name string, info VolumeInfo) {
|
||||
if cl.volumes == nil {
|
||||
cl.volumes = make(map[string]VolumeInfo)
|
||||
}
|
||||
cl.volumes[name] = info
|
||||
}
|
||||
|
||||
// MaybeRegisterVolume adds or updates an entry for the volume with
|
||||
// the given name if CreateVolume was successful.
|
||||
func (cl *Cleanup) MaybeRegisterVolume(name string, vol *csi.CreateVolumeResponse, err error) {
|
||||
if err == nil && vol.GetVolume().GetVolumeId() != "" {
|
||||
cl.RegisterVolume(name, VolumeInfo{VolumeID: vol.GetVolume().GetVolumeId()})
|
||||
}
|
||||
}
|
||||
|
||||
// UnregisterVolume removes the entry for the volume with the
|
||||
// given name, thus preventing all cleanup operations for it.
|
||||
func (cl *Cleanup) UnregisterVolume(name string) {
|
||||
if cl.volumes != nil {
|
||||
delete(cl.volumes, name)
|
||||
}
|
||||
}
|
||||
|
||||
// DeleteVolumes stops using the registered volumes and tries to delete all of them.
|
||||
func (cl *Cleanup) DeleteVolumes() {
|
||||
if cl.volumes == nil {
|
||||
return
|
||||
}
|
||||
logger := log.New(GinkgoWriter, "cleanup: ", 0)
|
||||
ctx := context.Background()
|
||||
|
||||
for name, info := range cl.volumes {
|
||||
logger.Printf("deleting %s = %s", name, info.VolumeID)
|
||||
if _, err := cl.NodeClient.NodeUnpublishVolume(
|
||||
ctx,
|
||||
&csi.NodeUnpublishVolumeRequest{
|
||||
VolumeId: info.VolumeID,
|
||||
TargetPath: cl.Context.Config.TargetPath,
|
||||
},
|
||||
); err != nil {
|
||||
logger.Printf("warning: NodeUnpublishVolume: %s", err)
|
||||
}
|
||||
|
||||
if cl.NodeStageSupported {
|
||||
if _, err := cl.NodeClient.NodeUnstageVolume(
|
||||
ctx,
|
||||
&csi.NodeUnstageVolumeRequest{
|
||||
VolumeId: info.VolumeID,
|
||||
StagingTargetPath: cl.Context.Config.StagingPath,
|
||||
},
|
||||
); err != nil {
|
||||
logger.Printf("warning: NodeUnstageVolume: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
if cl.ControllerPublishSupported && info.NodeID != "" {
|
||||
if _, err := cl.ControllerClient.ControllerUnpublishVolume(
|
||||
ctx,
|
||||
&csi.ControllerUnpublishVolumeRequest{
|
||||
VolumeId: info.VolumeID,
|
||||
NodeId: info.NodeID,
|
||||
Secrets: cl.Context.Secrets.ControllerUnpublishVolumeSecret,
|
||||
},
|
||||
); err != nil {
|
||||
logger.Printf("warning: ControllerUnpublishVolume: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
if _, err := cl.ControllerClient.DeleteVolume(
|
||||
ctx,
|
||||
&csi.DeleteVolumeRequest{
|
||||
VolumeId: info.VolumeID,
|
||||
Secrets: cl.Context.Secrets.DeleteVolumeSecret,
|
||||
},
|
||||
); err != nil {
|
||||
logger.Printf("error: DeleteVolume: %s", err)
|
||||
}
|
||||
|
||||
cl.UnregisterVolume(name)
|
||||
}
|
||||
}
|
1699
vendor/github.com/kubernetes-csi/csi-test/pkg/sanity/controller.go
generated
vendored
1699
vendor/github.com/kubernetes-csi/csi-test/pkg/sanity/controller.go
generated
vendored
File diff suppressed because it is too large
Load Diff
99
vendor/github.com/kubernetes-csi/csi-test/pkg/sanity/identity.go
generated
vendored
99
vendor/github.com/kubernetes-csi/csi-test/pkg/sanity/identity.go
generated
vendored
@@ -1,99 +0,0 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
package sanity
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"regexp"
|
||||
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
|
||||
"github.com/container-storage-interface/spec/lib/go/csi"
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
var _ = DescribeSanity("Identity Service", func(sc *SanityContext) {
|
||||
var (
|
||||
c csi.IdentityClient
|
||||
)
|
||||
|
||||
BeforeEach(func() {
|
||||
c = csi.NewIdentityClient(sc.Conn)
|
||||
})
|
||||
|
||||
Describe("GetPluginCapabilities", func() {
|
||||
It("should return appropriate capabilities", func() {
|
||||
req := &csi.GetPluginCapabilitiesRequest{}
|
||||
res, err := c.GetPluginCapabilities(context.Background(), req)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(res).NotTo(BeNil())
|
||||
|
||||
By("checking successful response")
|
||||
Expect(res.GetCapabilities()).NotTo(BeNil())
|
||||
for _, cap := range res.GetCapabilities() {
|
||||
switch cap.GetService().GetType() {
|
||||
case csi.PluginCapability_Service_CONTROLLER_SERVICE:
|
||||
case csi.PluginCapability_Service_VOLUME_ACCESSIBILITY_CONSTRAINTS:
|
||||
default:
|
||||
Fail(fmt.Sprintf("Unknown capability: %v\n", cap.GetService().GetType()))
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
Describe("Probe", func() {
|
||||
It("should return appropriate information", func() {
|
||||
req := &csi.ProbeRequest{}
|
||||
res, err := c.Probe(context.Background(), req)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(res).NotTo(BeNil())
|
||||
|
||||
By("verifying return status")
|
||||
serverError, ok := status.FromError(err)
|
||||
Expect(ok).To(BeTrue())
|
||||
Expect(serverError.Code() == codes.FailedPrecondition ||
|
||||
serverError.Code() == codes.OK).To(BeTrue())
|
||||
|
||||
if res.GetReady() != nil {
|
||||
Expect(res.GetReady().GetValue() == true ||
|
||||
res.GetReady().GetValue() == false).To(BeTrue())
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
Describe("GetPluginInfo", func() {
|
||||
It("should return appropriate information", func() {
|
||||
req := &csi.GetPluginInfoRequest{}
|
||||
res, err := c.GetPluginInfo(context.Background(), req)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(res).NotTo(BeNil())
|
||||
|
||||
By("verifying name size and characters")
|
||||
Expect(res.GetName()).ToNot(HaveLen(0))
|
||||
Expect(len(res.GetName())).To(BeNumerically("<=", 63))
|
||||
Expect(regexp.
|
||||
MustCompile("^[a-zA-Z][A-Za-z0-9-\\.\\_]{0,61}[a-zA-Z]$").
|
||||
MatchString(res.GetName())).To(BeTrue())
|
||||
})
|
||||
})
|
||||
})
|
517
vendor/github.com/kubernetes-csi/csi-test/pkg/sanity/node.go
generated
vendored
517
vendor/github.com/kubernetes-csi/csi-test/pkg/sanity/node.go
generated
vendored
@@ -1,517 +0,0 @@
|
||||
/*
|
||||
Copyright 2017 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 sanity
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
|
||||
"github.com/container-storage-interface/spec/lib/go/csi"
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
func isNodeCapabilitySupported(c csi.NodeClient,
|
||||
capType csi.NodeServiceCapability_RPC_Type,
|
||||
) bool {
|
||||
|
||||
caps, err := c.NodeGetCapabilities(
|
||||
context.Background(),
|
||||
&csi.NodeGetCapabilitiesRequest{})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(caps).NotTo(BeNil())
|
||||
|
||||
for _, cap := range caps.GetCapabilities() {
|
||||
Expect(cap.GetRpc()).NotTo(BeNil())
|
||||
if cap.GetRpc().GetType() == capType {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func isPluginCapabilitySupported(c csi.IdentityClient,
|
||||
capType csi.PluginCapability_Service_Type,
|
||||
) bool {
|
||||
|
||||
caps, err := c.GetPluginCapabilities(
|
||||
context.Background(),
|
||||
&csi.GetPluginCapabilitiesRequest{})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(caps).NotTo(BeNil())
|
||||
Expect(caps.GetCapabilities()).NotTo(BeNil())
|
||||
|
||||
for _, cap := range caps.GetCapabilities() {
|
||||
Expect(cap.GetService()).NotTo(BeNil())
|
||||
if cap.GetService().GetType() == capType {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
var _ = DescribeSanity("Node Service", func(sc *SanityContext) {
|
||||
var (
|
||||
cl *Cleanup
|
||||
c csi.NodeClient
|
||||
s csi.ControllerClient
|
||||
|
||||
controllerPublishSupported bool
|
||||
nodeStageSupported bool
|
||||
)
|
||||
|
||||
BeforeEach(func() {
|
||||
c = csi.NewNodeClient(sc.Conn)
|
||||
s = csi.NewControllerClient(sc.Conn)
|
||||
|
||||
controllerPublishSupported = isControllerCapabilitySupported(
|
||||
s,
|
||||
csi.ControllerServiceCapability_RPC_PUBLISH_UNPUBLISH_VOLUME)
|
||||
nodeStageSupported = isNodeCapabilitySupported(c, csi.NodeServiceCapability_RPC_STAGE_UNSTAGE_VOLUME)
|
||||
if nodeStageSupported {
|
||||
err := createMountTargetLocation(sc.Config.StagingPath)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
}
|
||||
cl = &Cleanup{
|
||||
Context: sc,
|
||||
NodeClient: c,
|
||||
ControllerClient: s,
|
||||
ControllerPublishSupported: controllerPublishSupported,
|
||||
NodeStageSupported: nodeStageSupported,
|
||||
}
|
||||
})
|
||||
|
||||
AfterEach(func() {
|
||||
cl.DeleteVolumes()
|
||||
})
|
||||
|
||||
Describe("NodeGetCapabilities", func() {
|
||||
It("should return appropriate capabilities", func() {
|
||||
caps, err := c.NodeGetCapabilities(
|
||||
context.Background(),
|
||||
&csi.NodeGetCapabilitiesRequest{})
|
||||
|
||||
By("checking successful response")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(caps).NotTo(BeNil())
|
||||
|
||||
for _, cap := range caps.GetCapabilities() {
|
||||
Expect(cap.GetRpc()).NotTo(BeNil())
|
||||
|
||||
switch cap.GetRpc().GetType() {
|
||||
case csi.NodeServiceCapability_RPC_UNKNOWN:
|
||||
case csi.NodeServiceCapability_RPC_STAGE_UNSTAGE_VOLUME:
|
||||
case csi.NodeServiceCapability_RPC_GET_VOLUME_STATS:
|
||||
default:
|
||||
Fail(fmt.Sprintf("Unknown capability: %v\n", cap.GetRpc().GetType()))
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
Describe("NodeGetInfo", func() {
|
||||
var (
|
||||
i csi.IdentityClient
|
||||
accessibilityConstraintSupported bool
|
||||
)
|
||||
|
||||
BeforeEach(func() {
|
||||
i = csi.NewIdentityClient(sc.Conn)
|
||||
accessibilityConstraintSupported = isPluginCapabilitySupported(i, csi.PluginCapability_Service_VOLUME_ACCESSIBILITY_CONSTRAINTS)
|
||||
})
|
||||
|
||||
It("should return approproate values", func() {
|
||||
ninfo, err := c.NodeGetInfo(
|
||||
context.Background(),
|
||||
&csi.NodeGetInfoRequest{})
|
||||
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(ninfo).NotTo(BeNil())
|
||||
Expect(ninfo.GetNodeId()).NotTo(BeEmpty())
|
||||
Expect(ninfo.GetMaxVolumesPerNode()).NotTo(BeNumerically("<", 0))
|
||||
|
||||
if accessibilityConstraintSupported {
|
||||
Expect(ninfo.GetAccessibleTopology()).NotTo(BeNil())
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
Describe("NodePublishVolume", func() {
|
||||
It("should fail when no volume id is provided", func() {
|
||||
_, err := c.NodePublishVolume(
|
||||
context.Background(),
|
||||
&csi.NodePublishVolumeRequest{
|
||||
Secrets: sc.Secrets.NodePublishVolumeSecret,
|
||||
},
|
||||
)
|
||||
Expect(err).To(HaveOccurred())
|
||||
|
||||
serverError, ok := status.FromError(err)
|
||||
Expect(ok).To(BeTrue())
|
||||
Expect(serverError.Code()).To(Equal(codes.InvalidArgument))
|
||||
})
|
||||
|
||||
It("should fail when no target path is provided", func() {
|
||||
_, err := c.NodePublishVolume(
|
||||
context.Background(),
|
||||
&csi.NodePublishVolumeRequest{
|
||||
VolumeId: "id",
|
||||
Secrets: sc.Secrets.NodePublishVolumeSecret,
|
||||
},
|
||||
)
|
||||
Expect(err).To(HaveOccurred())
|
||||
|
||||
serverError, ok := status.FromError(err)
|
||||
Expect(ok).To(BeTrue())
|
||||
Expect(serverError.Code()).To(Equal(codes.InvalidArgument))
|
||||
})
|
||||
|
||||
It("should fail when no volume capability is provided", func() {
|
||||
_, err := c.NodePublishVolume(
|
||||
context.Background(),
|
||||
&csi.NodePublishVolumeRequest{
|
||||
VolumeId: "id",
|
||||
TargetPath: sc.Config.TargetPath,
|
||||
Secrets: sc.Secrets.NodePublishVolumeSecret,
|
||||
},
|
||||
)
|
||||
Expect(err).To(HaveOccurred())
|
||||
|
||||
serverError, ok := status.FromError(err)
|
||||
Expect(ok).To(BeTrue())
|
||||
Expect(serverError.Code()).To(Equal(codes.InvalidArgument))
|
||||
})
|
||||
})
|
||||
|
||||
Describe("NodeUnpublishVolume", func() {
|
||||
It("should fail when no volume id is provided", func() {
|
||||
|
||||
_, err := c.NodeUnpublishVolume(
|
||||
context.Background(),
|
||||
&csi.NodeUnpublishVolumeRequest{})
|
||||
Expect(err).To(HaveOccurred())
|
||||
|
||||
serverError, ok := status.FromError(err)
|
||||
Expect(ok).To(BeTrue())
|
||||
Expect(serverError.Code()).To(Equal(codes.InvalidArgument))
|
||||
})
|
||||
|
||||
It("should fail when no target path is provided", func() {
|
||||
|
||||
_, err := c.NodeUnpublishVolume(
|
||||
context.Background(),
|
||||
&csi.NodeUnpublishVolumeRequest{
|
||||
VolumeId: "id",
|
||||
})
|
||||
Expect(err).To(HaveOccurred())
|
||||
|
||||
serverError, ok := status.FromError(err)
|
||||
Expect(ok).To(BeTrue())
|
||||
Expect(serverError.Code()).To(Equal(codes.InvalidArgument))
|
||||
})
|
||||
})
|
||||
|
||||
Describe("NodeStageVolume", func() {
|
||||
var (
|
||||
device string
|
||||
)
|
||||
|
||||
BeforeEach(func() {
|
||||
if !nodeStageSupported {
|
||||
Skip("NodeStageVolume not supported")
|
||||
}
|
||||
|
||||
device = "/dev/mock"
|
||||
})
|
||||
|
||||
It("should fail when no volume id is provided", func() {
|
||||
_, err := c.NodeStageVolume(
|
||||
context.Background(),
|
||||
&csi.NodeStageVolumeRequest{
|
||||
StagingTargetPath: sc.Config.StagingPath,
|
||||
VolumeCapability: &csi.VolumeCapability{
|
||||
AccessType: &csi.VolumeCapability_Mount{
|
||||
Mount: &csi.VolumeCapability_MountVolume{},
|
||||
},
|
||||
AccessMode: &csi.VolumeCapability_AccessMode{
|
||||
Mode: csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER,
|
||||
},
|
||||
},
|
||||
PublishContext: map[string]string{
|
||||
"device": device,
|
||||
},
|
||||
Secrets: sc.Secrets.NodeStageVolumeSecret,
|
||||
},
|
||||
)
|
||||
Expect(err).To(HaveOccurred())
|
||||
|
||||
serverError, ok := status.FromError(err)
|
||||
Expect(ok).To(BeTrue())
|
||||
Expect(serverError.Code()).To(Equal(codes.InvalidArgument))
|
||||
})
|
||||
|
||||
It("should fail when no staging target path is provided", func() {
|
||||
_, err := c.NodeStageVolume(
|
||||
context.Background(),
|
||||
&csi.NodeStageVolumeRequest{
|
||||
VolumeId: "id",
|
||||
VolumeCapability: &csi.VolumeCapability{
|
||||
AccessType: &csi.VolumeCapability_Mount{
|
||||
Mount: &csi.VolumeCapability_MountVolume{},
|
||||
},
|
||||
AccessMode: &csi.VolumeCapability_AccessMode{
|
||||
Mode: csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER,
|
||||
},
|
||||
},
|
||||
PublishContext: map[string]string{
|
||||
"device": device,
|
||||
},
|
||||
Secrets: sc.Secrets.NodeStageVolumeSecret,
|
||||
},
|
||||
)
|
||||
Expect(err).To(HaveOccurred())
|
||||
|
||||
serverError, ok := status.FromError(err)
|
||||
Expect(ok).To(BeTrue())
|
||||
Expect(serverError.Code()).To(Equal(codes.InvalidArgument))
|
||||
})
|
||||
|
||||
It("should fail when no volume capability is provided", func() {
|
||||
_, err := c.NodeStageVolume(
|
||||
context.Background(),
|
||||
&csi.NodeStageVolumeRequest{
|
||||
VolumeId: "id",
|
||||
StagingTargetPath: sc.Config.StagingPath,
|
||||
PublishContext: map[string]string{
|
||||
"device": device,
|
||||
},
|
||||
Secrets: sc.Secrets.NodeStageVolumeSecret,
|
||||
},
|
||||
)
|
||||
Expect(err).To(HaveOccurred())
|
||||
|
||||
serverError, ok := status.FromError(err)
|
||||
Expect(ok).To(BeTrue())
|
||||
Expect(serverError.Code()).To(Equal(codes.InvalidArgument))
|
||||
})
|
||||
})
|
||||
|
||||
Describe("NodeUnstageVolume", func() {
|
||||
BeforeEach(func() {
|
||||
if !nodeStageSupported {
|
||||
Skip("NodeUnstageVolume not supported")
|
||||
}
|
||||
})
|
||||
|
||||
It("should fail when no volume id is provided", func() {
|
||||
|
||||
_, err := c.NodeUnstageVolume(
|
||||
context.Background(),
|
||||
&csi.NodeUnstageVolumeRequest{
|
||||
StagingTargetPath: sc.Config.StagingPath,
|
||||
})
|
||||
Expect(err).To(HaveOccurred())
|
||||
|
||||
serverError, ok := status.FromError(err)
|
||||
Expect(ok).To(BeTrue())
|
||||
Expect(serverError.Code()).To(Equal(codes.InvalidArgument))
|
||||
})
|
||||
|
||||
It("should fail when no staging target path is provided", func() {
|
||||
|
||||
_, err := c.NodeUnstageVolume(
|
||||
context.Background(),
|
||||
&csi.NodeUnstageVolumeRequest{
|
||||
VolumeId: "id",
|
||||
})
|
||||
Expect(err).To(HaveOccurred())
|
||||
|
||||
serverError, ok := status.FromError(err)
|
||||
Expect(ok).To(BeTrue())
|
||||
Expect(serverError.Code()).To(Equal(codes.InvalidArgument))
|
||||
})
|
||||
})
|
||||
|
||||
It("should work", func() {
|
||||
name := uniqueString("sanity-node-full")
|
||||
|
||||
// Create Volume First
|
||||
By("creating a single node writer volume")
|
||||
vol, err := s.CreateVolume(
|
||||
context.Background(),
|
||||
&csi.CreateVolumeRequest{
|
||||
Name: name,
|
||||
VolumeCapabilities: []*csi.VolumeCapability{
|
||||
{
|
||||
AccessType: &csi.VolumeCapability_Mount{
|
||||
Mount: &csi.VolumeCapability_MountVolume{},
|
||||
},
|
||||
AccessMode: &csi.VolumeCapability_AccessMode{
|
||||
Mode: csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER,
|
||||
},
|
||||
},
|
||||
},
|
||||
Secrets: sc.Secrets.CreateVolumeSecret,
|
||||
},
|
||||
)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(vol).NotTo(BeNil())
|
||||
Expect(vol.GetVolume()).NotTo(BeNil())
|
||||
Expect(vol.GetVolume().GetVolumeId()).NotTo(BeEmpty())
|
||||
cl.RegisterVolume(name, VolumeInfo{VolumeID: vol.GetVolume().GetVolumeId()})
|
||||
|
||||
By("getting a node id")
|
||||
nid, err := c.NodeGetInfo(
|
||||
context.Background(),
|
||||
&csi.NodeGetInfoRequest{})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(nid).NotTo(BeNil())
|
||||
Expect(nid.GetNodeId()).NotTo(BeEmpty())
|
||||
|
||||
var conpubvol *csi.ControllerPublishVolumeResponse
|
||||
if controllerPublishSupported {
|
||||
By("controller publishing volume")
|
||||
|
||||
conpubvol, err = s.ControllerPublishVolume(
|
||||
context.Background(),
|
||||
&csi.ControllerPublishVolumeRequest{
|
||||
VolumeId: vol.GetVolume().GetVolumeId(),
|
||||
NodeId: nid.GetNodeId(),
|
||||
VolumeCapability: &csi.VolumeCapability{
|
||||
AccessType: &csi.VolumeCapability_Mount{
|
||||
Mount: &csi.VolumeCapability_MountVolume{},
|
||||
},
|
||||
AccessMode: &csi.VolumeCapability_AccessMode{
|
||||
Mode: csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER,
|
||||
},
|
||||
},
|
||||
VolumeContext: vol.GetVolume().GetVolumeContext(),
|
||||
Readonly: false,
|
||||
Secrets: sc.Secrets.ControllerPublishVolumeSecret,
|
||||
},
|
||||
)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
cl.RegisterVolume(name, VolumeInfo{VolumeID: vol.GetVolume().GetVolumeId(), NodeID: nid.GetNodeId()})
|
||||
Expect(conpubvol).NotTo(BeNil())
|
||||
}
|
||||
// NodeStageVolume
|
||||
if nodeStageSupported {
|
||||
By("node staging volume")
|
||||
nodestagevol, err := c.NodeStageVolume(
|
||||
context.Background(),
|
||||
&csi.NodeStageVolumeRequest{
|
||||
VolumeId: vol.GetVolume().GetVolumeId(),
|
||||
VolumeCapability: &csi.VolumeCapability{
|
||||
AccessType: &csi.VolumeCapability_Mount{
|
||||
Mount: &csi.VolumeCapability_MountVolume{},
|
||||
},
|
||||
AccessMode: &csi.VolumeCapability_AccessMode{
|
||||
Mode: csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER,
|
||||
},
|
||||
},
|
||||
StagingTargetPath: sc.Config.StagingPath,
|
||||
VolumeContext: vol.GetVolume().GetVolumeContext(),
|
||||
PublishContext: conpubvol.GetPublishContext(),
|
||||
Secrets: sc.Secrets.NodeStageVolumeSecret,
|
||||
},
|
||||
)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(nodestagevol).NotTo(BeNil())
|
||||
}
|
||||
// NodePublishVolume
|
||||
By("publishing the volume on a node")
|
||||
var stagingPath string
|
||||
if nodeStageSupported {
|
||||
stagingPath = sc.Config.StagingPath
|
||||
}
|
||||
nodepubvol, err := c.NodePublishVolume(
|
||||
context.Background(),
|
||||
&csi.NodePublishVolumeRequest{
|
||||
VolumeId: vol.GetVolume().GetVolumeId(),
|
||||
TargetPath: sc.Config.TargetPath,
|
||||
StagingTargetPath: stagingPath,
|
||||
VolumeCapability: &csi.VolumeCapability{
|
||||
AccessType: &csi.VolumeCapability_Mount{
|
||||
Mount: &csi.VolumeCapability_MountVolume{},
|
||||
},
|
||||
AccessMode: &csi.VolumeCapability_AccessMode{
|
||||
Mode: csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER,
|
||||
},
|
||||
},
|
||||
VolumeContext: vol.GetVolume().GetVolumeContext(),
|
||||
PublishContext: conpubvol.GetPublishContext(),
|
||||
Secrets: sc.Secrets.NodePublishVolumeSecret,
|
||||
},
|
||||
)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(nodepubvol).NotTo(BeNil())
|
||||
|
||||
// NodeUnpublishVolume
|
||||
By("cleaning up calling nodeunpublish")
|
||||
nodeunpubvol, err := c.NodeUnpublishVolume(
|
||||
context.Background(),
|
||||
&csi.NodeUnpublishVolumeRequest{
|
||||
VolumeId: vol.GetVolume().GetVolumeId(),
|
||||
TargetPath: sc.Config.TargetPath,
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(nodeunpubvol).NotTo(BeNil())
|
||||
|
||||
if nodeStageSupported {
|
||||
By("cleaning up calling nodeunstage")
|
||||
nodeunstagevol, err := c.NodeUnstageVolume(
|
||||
context.Background(),
|
||||
&csi.NodeUnstageVolumeRequest{
|
||||
VolumeId: vol.GetVolume().GetVolumeId(),
|
||||
StagingTargetPath: sc.Config.StagingPath,
|
||||
},
|
||||
)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(nodeunstagevol).NotTo(BeNil())
|
||||
}
|
||||
|
||||
if controllerPublishSupported {
|
||||
By("cleaning up calling controllerunpublishing")
|
||||
|
||||
controllerunpubvol, err := s.ControllerUnpublishVolume(
|
||||
context.Background(),
|
||||
&csi.ControllerUnpublishVolumeRequest{
|
||||
VolumeId: vol.GetVolume().GetVolumeId(),
|
||||
NodeId: nid.GetNodeId(),
|
||||
Secrets: sc.Secrets.ControllerUnpublishVolumeSecret,
|
||||
},
|
||||
)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(controllerunpubvol).NotTo(BeNil())
|
||||
}
|
||||
|
||||
By("cleaning up deleting the volume")
|
||||
|
||||
_, err = s.DeleteVolume(
|
||||
context.Background(),
|
||||
&csi.DeleteVolumeRequest{
|
||||
VolumeId: vol.GetVolume().GetVolumeId(),
|
||||
Secrets: sc.Secrets.DeleteVolumeSecret,
|
||||
},
|
||||
)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
})
|
194
vendor/github.com/kubernetes-csi/csi-test/pkg/sanity/sanity.go
generated
vendored
194
vendor/github.com/kubernetes-csi/csi-test/pkg/sanity/sanity.go
generated
vendored
@@ -1,194 +0,0 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
package sanity
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/kubernetes-csi/csi-test/utils"
|
||||
yaml "gopkg.in/yaml.v2"
|
||||
|
||||
"google.golang.org/grpc"
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
// CSISecrets consists of secrets used in CSI credentials.
|
||||
type CSISecrets struct {
|
||||
CreateVolumeSecret map[string]string `yaml:"CreateVolumeSecret"`
|
||||
DeleteVolumeSecret map[string]string `yaml:"DeleteVolumeSecret"`
|
||||
ControllerPublishVolumeSecret map[string]string `yaml:"ControllerPublishVolumeSecret"`
|
||||
ControllerUnpublishVolumeSecret map[string]string `yaml:"ControllerUnpublishVolumeSecret"`
|
||||
NodeStageVolumeSecret map[string]string `yaml:"NodeStageVolumeSecret"`
|
||||
NodePublishVolumeSecret map[string]string `yaml:"NodePublishVolumeSecret"`
|
||||
CreateSnapshotSecret map[string]string `yaml:"CreateSnapshotSecret"`
|
||||
DeleteSnapshotSecret map[string]string `yaml:"DeleteSnapshotSecret"`
|
||||
}
|
||||
|
||||
// Config provides the configuration for the sanity tests. It
|
||||
// needs to be initialized by the user of the sanity package.
|
||||
type Config struct {
|
||||
TargetPath string
|
||||
StagingPath string
|
||||
Address string
|
||||
SecretsFile string
|
||||
|
||||
TestVolumeSize int64
|
||||
TestVolumeParametersFile string
|
||||
TestVolumeParameters map[string]string
|
||||
}
|
||||
|
||||
// SanityContext holds the variables that each test can depend on. It
|
||||
// gets initialized before each test block runs.
|
||||
type SanityContext struct {
|
||||
Config *Config
|
||||
Conn *grpc.ClientConn
|
||||
Secrets *CSISecrets
|
||||
|
||||
connAddress string
|
||||
}
|
||||
|
||||
// Test will test the CSI driver at the specified address by
|
||||
// setting up a Ginkgo suite and running it.
|
||||
func Test(t *testing.T, reqConfig *Config) {
|
||||
path := reqConfig.TestVolumeParametersFile
|
||||
if len(path) != 0 {
|
||||
yamlFile, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("failed to read file %q: %v", path, err))
|
||||
}
|
||||
err = yaml.Unmarshal(yamlFile, &reqConfig.TestVolumeParameters)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("error unmarshaling yaml: %v", err))
|
||||
}
|
||||
}
|
||||
|
||||
sc := &SanityContext{
|
||||
Config: reqConfig,
|
||||
}
|
||||
|
||||
registerTestsInGinkgo(sc)
|
||||
RegisterFailHandler(Fail)
|
||||
RunSpecs(t, "CSI Driver Test Suite")
|
||||
}
|
||||
|
||||
func GinkgoTest(reqConfig *Config) {
|
||||
sc := &SanityContext{
|
||||
Config: reqConfig,
|
||||
}
|
||||
|
||||
registerTestsInGinkgo(sc)
|
||||
}
|
||||
|
||||
func (sc *SanityContext) setup() {
|
||||
var err error
|
||||
|
||||
if len(sc.Config.SecretsFile) > 0 {
|
||||
sc.Secrets, err = loadSecrets(sc.Config.SecretsFile)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
} else {
|
||||
sc.Secrets = &CSISecrets{}
|
||||
}
|
||||
|
||||
// It is possible that a test sets sc.Config.Address
|
||||
// dynamically (and differently!) in a BeforeEach, so only
|
||||
// reuse the connection if the address is still the same.
|
||||
if sc.Conn == nil || sc.connAddress != sc.Config.Address {
|
||||
By("connecting to CSI driver")
|
||||
sc.Conn, err = utils.Connect(sc.Config.Address)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
sc.connAddress = sc.Config.Address
|
||||
} else {
|
||||
By(fmt.Sprintf("reusing connection to CSI driver at %s", sc.connAddress))
|
||||
}
|
||||
|
||||
By("creating mount and staging directories")
|
||||
err = createMountTargetLocation(sc.Config.TargetPath)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
if len(sc.Config.StagingPath) > 0 {
|
||||
err = createMountTargetLocation(sc.Config.StagingPath)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
}
|
||||
}
|
||||
|
||||
func (sc *SanityContext) teardown() {
|
||||
// We intentionally do not close the connection to the CSI
|
||||
// driver here because the large amount of connection attempts
|
||||
// caused test failures
|
||||
// (https://github.com/kubernetes-csi/csi-test/issues/101). We
|
||||
// could fix this with retries
|
||||
// (https://github.com/kubernetes-csi/csi-test/pull/97) but
|
||||
// that requires more discussion, so instead we just connect
|
||||
// once per process instead of once per test case. This was
|
||||
// also said to be faster
|
||||
// (https://github.com/kubernetes-csi/csi-test/pull/98).
|
||||
}
|
||||
|
||||
func createMountTargetLocation(targetPath string) error {
|
||||
fileInfo, err := os.Stat(targetPath)
|
||||
if err != nil && os.IsNotExist(err) {
|
||||
return os.MkdirAll(targetPath, 0755)
|
||||
} else if err != nil {
|
||||
return err
|
||||
}
|
||||
if !fileInfo.IsDir() {
|
||||
return fmt.Errorf("Target location %s is not a directory", targetPath)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func loadSecrets(path string) (*CSISecrets, error) {
|
||||
var creds CSISecrets
|
||||
|
||||
yamlFile, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
return &creds, fmt.Errorf("failed to read file %q: #%v", path, err)
|
||||
}
|
||||
|
||||
err = yaml.Unmarshal(yamlFile, &creds)
|
||||
if err != nil {
|
||||
return &creds, fmt.Errorf("error unmarshaling yaml: #%v", err)
|
||||
}
|
||||
|
||||
return &creds, nil
|
||||
}
|
||||
|
||||
var uniqueSuffix = "-" + pseudoUUID()
|
||||
|
||||
// pseudoUUID returns a unique string generated from random
|
||||
// bytes, empty string in case of error.
|
||||
func pseudoUUID() string {
|
||||
b := make([]byte, 8)
|
||||
if _, err := rand.Read(b); err != nil {
|
||||
// Shouldn't happen?!
|
||||
return ""
|
||||
}
|
||||
return fmt.Sprintf("%08X-%08X", b[0:4], b[4:8])
|
||||
}
|
||||
|
||||
// uniqueString returns a unique string by appending a random
|
||||
// number. In case of an error, just the prefix is returned, so it
|
||||
// alone should already be fairly unique.
|
||||
func uniqueString(prefix string) string {
|
||||
return prefix + uniqueSuffix
|
||||
}
|
56
vendor/github.com/kubernetes-csi/csi-test/pkg/sanity/tests.go
generated
vendored
56
vendor/github.com/kubernetes-csi/csi-test/pkg/sanity/tests.go
generated
vendored
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 Intel Corporation
|
||||
|
||||
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 sanity
|
||||
|
||||
import (
|
||||
. "github.com/onsi/ginkgo"
|
||||
)
|
||||
|
||||
type test struct {
|
||||
text string
|
||||
body func(*SanityContext)
|
||||
}
|
||||
|
||||
var tests []test
|
||||
|
||||
// DescribeSanity must be used instead of the usual Ginkgo Describe to
|
||||
// register a test block. The difference is that the body function
|
||||
// will be called multiple times with the right context (when
|
||||
// setting up a Ginkgo suite or a testing.T test, with the right
|
||||
// configuration).
|
||||
func DescribeSanity(text string, body func(*SanityContext)) bool {
|
||||
tests = append(tests, test{text, body})
|
||||
return true
|
||||
}
|
||||
|
||||
// registerTestsInGinkgo invokes the actual Gingko Describe
|
||||
// for the tests registered earlier with DescribeSanity.
|
||||
func registerTestsInGinkgo(sc *SanityContext) {
|
||||
for _, test := range tests {
|
||||
Describe(test.text, func() {
|
||||
BeforeEach(func() {
|
||||
sc.setup()
|
||||
})
|
||||
|
||||
test.body(sc)
|
||||
|
||||
AfterEach(func() {
|
||||
sc.teardown()
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
188
vendor/github.com/kubernetes-csi/csi-test/test/co_test.go
generated
vendored
188
vendor/github.com/kubernetes-csi/csi-test/test/co_test.go
generated
vendored
@@ -1,188 +0,0 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
package test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/container-storage-interface/spec/lib/go/csi"
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/golang/protobuf/proto"
|
||||
mock_driver "github.com/kubernetes-csi/csi-test/driver"
|
||||
mock_utils "github.com/kubernetes-csi/csi-test/utils"
|
||||
)
|
||||
|
||||
func TestPluginInfoResponse(t *testing.T) {
|
||||
|
||||
// Setup mock
|
||||
m := gomock.NewController(t)
|
||||
defer m.Finish()
|
||||
driver := mock_driver.NewMockIdentityServer(m)
|
||||
|
||||
// Setup input
|
||||
in := &csi.GetPluginInfoRequest{}
|
||||
|
||||
// Setup mock outout
|
||||
out := &csi.GetPluginInfoResponse{
|
||||
Name: "mock",
|
||||
VendorVersion: "0.1.1",
|
||||
Manifest: map[string]string{
|
||||
"hello": "world",
|
||||
},
|
||||
}
|
||||
|
||||
// Setup expectation
|
||||
driver.EXPECT().GetPluginInfo(nil, in).Return(out, nil).Times(1)
|
||||
|
||||
// Actual call
|
||||
r, err := driver.GetPluginInfo(nil, in)
|
||||
name := r.GetName()
|
||||
if err != nil {
|
||||
t.Errorf("Error: %s", err.Error())
|
||||
}
|
||||
if name != "mock" {
|
||||
t.Errorf("Unknown name: %s\n", name)
|
||||
}
|
||||
}
|
||||
|
||||
type pbMatcher struct {
|
||||
x proto.Message
|
||||
}
|
||||
|
||||
func (p pbMatcher) Matches(x interface{}) bool {
|
||||
y := x.(proto.Message)
|
||||
return proto.Equal(p.x, y)
|
||||
}
|
||||
|
||||
func (p pbMatcher) String() string {
|
||||
return fmt.Sprintf("pb equal to %v", p.x)
|
||||
}
|
||||
|
||||
func pbMatch(x interface{}) gomock.Matcher {
|
||||
v := x.(proto.Message)
|
||||
return &pbMatcher{v}
|
||||
}
|
||||
|
||||
func TestGRPCGetPluginInfoReponse(t *testing.T) {
|
||||
|
||||
// Setup mock
|
||||
m := gomock.NewController(&mock_utils.SafeGoroutineTester{})
|
||||
defer m.Finish()
|
||||
driver := mock_driver.NewMockIdentityServer(m)
|
||||
|
||||
// Setup input
|
||||
in := &csi.GetPluginInfoRequest{}
|
||||
|
||||
// Setup mock outout
|
||||
out := &csi.GetPluginInfoResponse{
|
||||
Name: "mock",
|
||||
VendorVersion: "0.1.1",
|
||||
Manifest: map[string]string{
|
||||
"hello": "world",
|
||||
},
|
||||
}
|
||||
|
||||
// Setup expectation
|
||||
// !IMPORTANT!: Must set context expected value to gomock.Any() to match any value
|
||||
driver.EXPECT().GetPluginInfo(gomock.Any(), pbMatch(in)).Return(out, nil).Times(1)
|
||||
|
||||
// Create a new RPC
|
||||
server := mock_driver.NewMockCSIDriver(&mock_driver.MockCSIDriverServers{
|
||||
Identity: driver,
|
||||
})
|
||||
conn, err := server.Nexus()
|
||||
if err != nil {
|
||||
t.Errorf("Error: %s", err.Error())
|
||||
}
|
||||
defer server.Close()
|
||||
|
||||
// Make call
|
||||
c := csi.NewIdentityClient(conn)
|
||||
r, err := c.GetPluginInfo(context.Background(), in)
|
||||
if err != nil {
|
||||
t.Errorf("Error: %s", err.Error())
|
||||
}
|
||||
|
||||
name := r.GetName()
|
||||
if name != "mock" {
|
||||
t.Errorf("Unknown name: %s\n", name)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGRPCAttach(t *testing.T) {
|
||||
|
||||
// Setup mock
|
||||
m := gomock.NewController(&mock_utils.SafeGoroutineTester{})
|
||||
defer m.Finish()
|
||||
driver := mock_driver.NewMockControllerServer(m)
|
||||
|
||||
// Setup input
|
||||
defaultVolumeID := "myname"
|
||||
defaultNodeID := "MyNodeID"
|
||||
defaultCaps := &csi.VolumeCapability{
|
||||
AccessType: &csi.VolumeCapability_Mount{
|
||||
Mount: &csi.VolumeCapability_MountVolume{},
|
||||
},
|
||||
AccessMode: &csi.VolumeCapability_AccessMode{
|
||||
Mode: csi.VolumeCapability_AccessMode_MULTI_NODE_MULTI_WRITER,
|
||||
},
|
||||
}
|
||||
publishVolumeInfo := map[string]string{
|
||||
"first": "foo",
|
||||
"second": "bar",
|
||||
"third": "baz",
|
||||
}
|
||||
defaultRequest := &csi.ControllerPublishVolumeRequest{
|
||||
VolumeId: defaultVolumeID,
|
||||
NodeId: defaultNodeID,
|
||||
VolumeCapability: defaultCaps,
|
||||
Readonly: false,
|
||||
}
|
||||
|
||||
// Setup mock outout
|
||||
out := &csi.ControllerPublishVolumeResponse{
|
||||
PublishContext: publishVolumeInfo,
|
||||
}
|
||||
|
||||
// Setup expectation
|
||||
// !IMPORTANT!: Must set context expected value to gomock.Any() to match any value
|
||||
driver.EXPECT().ControllerPublishVolume(gomock.Any(), pbMatch(defaultRequest)).Return(out, nil).Times(1)
|
||||
|
||||
// Create a new RPC
|
||||
server := mock_driver.NewMockCSIDriver(&mock_driver.MockCSIDriverServers{
|
||||
Controller: driver,
|
||||
})
|
||||
conn, err := server.Nexus()
|
||||
if err != nil {
|
||||
t.Errorf("Error: %s", err.Error())
|
||||
}
|
||||
defer server.Close()
|
||||
|
||||
// Make call
|
||||
c := csi.NewControllerClient(conn)
|
||||
r, err := c.ControllerPublishVolume(context.Background(), defaultRequest)
|
||||
if err != nil {
|
||||
t.Errorf("Error: %s", err.Error())
|
||||
}
|
||||
|
||||
info := r.GetPublishContext()
|
||||
if !reflect.DeepEqual(info, publishVolumeInfo) {
|
||||
t.Errorf("Invalid publish info: %v", info)
|
||||
}
|
||||
}
|
127
vendor/github.com/kubernetes-csi/csi-test/test/driver_test.go
generated
vendored
127
vendor/github.com/kubernetes-csi/csi-test/test/driver_test.go
generated
vendored
@@ -1,127 +0,0 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
package test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
"github.com/container-storage-interface/spec/lib/go/csi"
|
||||
"github.com/kubernetes-csi/csi-test/utils"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/reflection"
|
||||
)
|
||||
|
||||
// Example simple driver
|
||||
// This example assumes that your driver will create the server and listen on
|
||||
// some unix domain socket or port for tests.
|
||||
type simpleDriver struct {
|
||||
listener net.Listener
|
||||
server *grpc.Server
|
||||
wg sync.WaitGroup
|
||||
}
|
||||
|
||||
func (s *simpleDriver) GetPluginCapabilities(context.Context, *csi.GetPluginCapabilitiesRequest) (*csi.GetPluginCapabilitiesResponse, error) {
|
||||
// TODO: Return some simple Plugin Capabilities
|
||||
return &csi.GetPluginCapabilitiesResponse{}, nil
|
||||
}
|
||||
|
||||
func (s *simpleDriver) Probe(context.Context, *csi.ProbeRequest) (*csi.ProbeResponse, error) {
|
||||
return &csi.ProbeResponse{}, nil
|
||||
}
|
||||
|
||||
func (s *simpleDriver) GetPluginInfo(
|
||||
context.Context, *csi.GetPluginInfoRequest) (*csi.GetPluginInfoResponse, error) {
|
||||
return &csi.GetPluginInfoResponse{
|
||||
Name: "simpleDriver",
|
||||
VendorVersion: "0.1.1",
|
||||
Manifest: map[string]string{
|
||||
"hello": "world",
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *simpleDriver) goServe() {
|
||||
s.wg.Add(1)
|
||||
go func() {
|
||||
defer s.wg.Done()
|
||||
s.server.Serve(s.listener)
|
||||
}()
|
||||
}
|
||||
|
||||
func (s *simpleDriver) Address() string {
|
||||
return s.listener.Addr().String()
|
||||
}
|
||||
|
||||
func (s *simpleDriver) 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
|
||||
}
|
||||
s.listener = l
|
||||
|
||||
// Create a new grpc server
|
||||
s.server = grpc.NewServer()
|
||||
|
||||
csi.RegisterIdentityServer(s.server, s)
|
||||
reflection.Register(s.server)
|
||||
|
||||
// Start listening for requests
|
||||
s.goServe()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *simpleDriver) Stop() {
|
||||
s.server.Stop()
|
||||
s.wg.Wait()
|
||||
}
|
||||
|
||||
//
|
||||
// Tests
|
||||
//
|
||||
func TestSimpleDriver(t *testing.T) {
|
||||
|
||||
// Setup simple driver
|
||||
s := &simpleDriver{}
|
||||
err := s.Start()
|
||||
if err != nil {
|
||||
t.Errorf("Error: %s", err.Error())
|
||||
}
|
||||
defer s.Stop()
|
||||
|
||||
// Setup a connection to the driver
|
||||
conn, err := utils.Connect(s.Address())
|
||||
if err != nil {
|
||||
t.Errorf("Error: %s", err.Error())
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
// Make a call
|
||||
c := csi.NewIdentityClient(conn)
|
||||
r, err := c.GetPluginInfo(context.Background(), &csi.GetPluginInfoRequest{})
|
||||
if err != nil {
|
||||
t.Errorf("Error: %s", err.Error())
|
||||
}
|
||||
|
||||
// Verify
|
||||
name := r.GetName()
|
||||
if name != "simpleDriver" {
|
||||
t.Errorf("Unknown name: %s\n", name)
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user