add prune and remove unused packages
This commit is contained in:
31
vendor/github.com/kubernetes-csi/csi-lib-utils/CONTRIBUTING.md
generated
vendored
31
vendor/github.com/kubernetes-csi/csi-lib-utils/CONTRIBUTING.md
generated
vendored
@@ -1,31 +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](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:
|
||||
|
||||
<!---
|
||||
If your repo has certain guidelines for contribution, put them here ahead of the general k8s resources
|
||||
-->
|
||||
|
||||
- [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!
|
||||
|
||||
<!---
|
||||
Custom Information - if you're copying this template for the first time you can add custom content here, for example:
|
||||
|
||||
## Contact Information
|
||||
|
||||
- [Slack channel](https://kubernetes.slack.com/messages/kubernetes-users) - Replace `kubernetes-users` with your slack channel string, this will send users directly to your channel.
|
||||
- [Mailing list](URL)
|
||||
|
||||
-->
|
165
vendor/github.com/kubernetes-csi/csi-lib-utils/Gopkg.lock
generated
vendored
165
vendor/github.com/kubernetes-csi/csi-lib-utils/Gopkg.lock
generated
vendored
@@ -1,165 +0,0 @@
|
||||
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
|
||||
|
||||
|
||||
[[projects]]
|
||||
digest = "1:ffe9824d294da03b391f44e1ae8281281b4afc1bdaa9588c9097785e3af10cec"
|
||||
name = "github.com/davecgh/go-spew"
|
||||
packages = ["spew"]
|
||||
pruneopts = "NUT"
|
||||
revision = "8991bc29aa16c548c550c7ff78260e27b9ab7c73"
|
||||
version = "v1.1.1"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:bff0ce7c8e3d6357fa5a8549bbe4bdb620bddc13c11ae569aa7248ea92e2139f"
|
||||
name = "github.com/golang/protobuf"
|
||||
packages = [
|
||||
"descriptor",
|
||||
"proto",
|
||||
"protoc-gen-go/descriptor",
|
||||
"ptypes",
|
||||
"ptypes/any",
|
||||
"ptypes/duration",
|
||||
"ptypes/timestamp",
|
||||
"ptypes/wrappers",
|
||||
]
|
||||
pruneopts = "NUT"
|
||||
revision = "aa810b61a9c79d51363740d207bb46cf8e620ed5"
|
||||
version = "v1.2.0"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:0028cb19b2e4c3112225cd871870f2d9cf49b9b4276531f03438a88e94be86fe"
|
||||
name = "github.com/pmezard/go-difflib"
|
||||
packages = ["difflib"]
|
||||
pruneopts = "NUT"
|
||||
revision = "792786c7400a136282c1664665ae0a8db921c6c2"
|
||||
version = "v1.0.0"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:0331452965d8695c0a5633e0f509012987681a654f388f2ad0c3b2d7f7004b1c"
|
||||
name = "github.com/stretchr/testify"
|
||||
packages = [
|
||||
"assert",
|
||||
"require",
|
||||
]
|
||||
pruneopts = "NUT"
|
||||
revision = "f35b8ab0b5a2cef36673838d662e249dd9c94686"
|
||||
version = "v1.2.2"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:dc5dcbb306af980306fab456d4788e88c880177227bd488a92d5bef7d8743497"
|
||||
name = "golang.org/x/net"
|
||||
packages = [
|
||||
"context",
|
||||
"http/httpguts",
|
||||
"http2",
|
||||
"http2/hpack",
|
||||
"idna",
|
||||
"internal/timeseries",
|
||||
"trace",
|
||||
]
|
||||
pruneopts = "NUT"
|
||||
revision = "fae4c4e3ad76c295c3d6d259f898136b4bf833a8"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:134392bed1074be912a37ea13483f27e6e827f4e4d6cc319f69d3ac3617d5ac0"
|
||||
name = "golang.org/x/sys"
|
||||
packages = ["unix"]
|
||||
pruneopts = "NUT"
|
||||
revision = "4ed8d59d0b35e1e29334a206d1b3f38b1e5dfb31"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:e7071ed636b5422cc51c0e3a6cebc229d6c9fffc528814b519a980641422d619"
|
||||
name = "golang.org/x/text"
|
||||
packages = [
|
||||
"collate",
|
||||
"collate/build",
|
||||
"internal/colltab",
|
||||
"internal/gen",
|
||||
"internal/tag",
|
||||
"internal/triegen",
|
||||
"internal/ucd",
|
||||
"language",
|
||||
"secure/bidirule",
|
||||
"transform",
|
||||
"unicode/bidi",
|
||||
"unicode/cldr",
|
||||
"unicode/norm",
|
||||
"unicode/rangetable",
|
||||
]
|
||||
pruneopts = "NUT"
|
||||
revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0"
|
||||
version = "v0.3.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:56b0bca90b7e5d1facf5fbdacba23e4e0ce069d25381b8e2f70ef1e7ebfb9c1a"
|
||||
name = "google.golang.org/genproto"
|
||||
packages = ["googleapis/rpc/status"]
|
||||
pruneopts = "NUT"
|
||||
revision = "31ac5d88444a9e7ad18077db9a165d793ad06a2e"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:2f91d3e11b666570f8c923912f1cc8cf2f0c6b7371b2687ee67a8f73f08c6272"
|
||||
name = "google.golang.org/grpc"
|
||||
packages = [
|
||||
".",
|
||||
"balancer",
|
||||
"balancer/base",
|
||||
"balancer/roundrobin",
|
||||
"codes",
|
||||
"connectivity",
|
||||
"credentials",
|
||||
"encoding",
|
||||
"encoding/proto",
|
||||
"grpclog",
|
||||
"internal",
|
||||
"internal/backoff",
|
||||
"internal/channelz",
|
||||
"internal/envconfig",
|
||||
"internal/grpcrand",
|
||||
"internal/transport",
|
||||
"keepalive",
|
||||
"metadata",
|
||||
"naming",
|
||||
"peer",
|
||||
"resolver",
|
||||
"resolver/dns",
|
||||
"resolver/passthrough",
|
||||
"stats",
|
||||
"status",
|
||||
"tap",
|
||||
]
|
||||
pruneopts = "NUT"
|
||||
revision = "2e463a05d100327ca47ac218281906921038fd95"
|
||||
version = "v1.16.0"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:9cc257b3c9ff6a0158c9c661ab6eebda1fe8a4a4453cd5c4044dc9a2ebfb992b"
|
||||
name = "k8s.io/klog"
|
||||
packages = ["."]
|
||||
pruneopts = "NUT"
|
||||
revision = "a5bc97fbc634d635061f3146511332c7e313a55a"
|
||||
version = "v0.1.0"
|
||||
|
||||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
input-imports = [
|
||||
"github.com/golang/protobuf/descriptor",
|
||||
"github.com/golang/protobuf/proto",
|
||||
"github.com/golang/protobuf/protoc-gen-go/descriptor",
|
||||
"github.com/golang/protobuf/ptypes/timestamp",
|
||||
"github.com/golang/protobuf/ptypes/wrappers",
|
||||
"github.com/stretchr/testify/assert",
|
||||
"github.com/stretchr/testify/require",
|
||||
"golang.org/x/net/context",
|
||||
"google.golang.org/grpc",
|
||||
"google.golang.org/grpc/codes",
|
||||
"google.golang.org/grpc/connectivity",
|
||||
"google.golang.org/grpc/status",
|
||||
"k8s.io/klog",
|
||||
]
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
7
vendor/github.com/kubernetes-csi/csi-lib-utils/Gopkg.toml
generated
vendored
7
vendor/github.com/kubernetes-csi/csi-lib-utils/Gopkg.toml
generated
vendored
@@ -1,7 +0,0 @@
|
||||
# Refer to https://golang.github.io/dep/docs/Gopkg.toml.html
|
||||
# for detailed Gopkg.toml documentation.
|
||||
|
||||
[prune]
|
||||
go-tests = true
|
||||
non-go = true
|
||||
unused-packages = true
|
20
vendor/github.com/kubernetes-csi/csi-lib-utils/Makefile
generated
vendored
20
vendor/github.com/kubernetes-csi/csi-lib-utils/Makefile
generated
vendored
@@ -1,20 +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.
|
||||
|
||||
# No individual commands at the moment, just packages.
|
||||
CMDS=
|
||||
all:
|
||||
go build `go list ./... | grep -v 'vendor'`
|
||||
|
||||
include release-tools/build.make
|
7
vendor/github.com/kubernetes-csi/csi-lib-utils/OWNERS
generated
vendored
7
vendor/github.com/kubernetes-csi/csi-lib-utils/OWNERS
generated
vendored
@@ -1,7 +0,0 @@
|
||||
# See the OWNERS docs: https://git.k8s.io/community/contributors/guide/owners.md
|
||||
|
||||
approvers:
|
||||
- saad-ali
|
||||
- jsafrane
|
||||
- msau42
|
||||
- pohly
|
19
vendor/github.com/kubernetes-csi/csi-lib-utils/README.md
generated
vendored
19
vendor/github.com/kubernetes-csi/csi-lib-utils/README.md
generated
vendored
@@ -1,19 +0,0 @@
|
||||
# csi-lib-utils
|
||||
|
||||
TBD
|
||||
|
||||
## 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](http://slack.k8s.io/)
|
||||
- [Mailing List](https://groups.google.com/forum/#!forum/kubernetes-dev)
|
||||
|
||||
### Code of conduct
|
||||
|
||||
Participation in the Kubernetes community is governed by the [Kubernetes Code of Conduct](code-of-conduct.md).
|
||||
|
||||
[owners]: https://git.k8s.io/community/contributors/guide/owners.md
|
||||
[Creative Commons 4.0]: https://git.k8s.io/website/LICENSE
|
13
vendor/github.com/kubernetes-csi/csi-lib-utils/SECURITY_CONTACTS
generated
vendored
13
vendor/github.com/kubernetes-csi/csi-lib-utils/SECURITY_CONTACTS
generated
vendored
@@ -1,13 +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
|
3
vendor/github.com/kubernetes-csi/csi-lib-utils/code-of-conduct.md
generated
vendored
3
vendor/github.com/kubernetes-csi/csi-lib-utils/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)
|
308
vendor/github.com/kubernetes-csi/csi-lib-utils/connection/connection_test.go
generated
vendored
308
vendor/github.com/kubernetes-csi/csi-lib-utils/connection/connection_test.go
generated
vendored
@@ -1,308 +0,0 @@
|
||||
/*
|
||||
Copyright 2019 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package connection
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"path"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/connectivity"
|
||||
"google.golang.org/grpc/status"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func tmpDir(t *testing.T) string {
|
||||
dir, err := ioutil.TempDir("", "connect")
|
||||
require.NoError(t, err, "creating temp directory")
|
||||
return dir
|
||||
}
|
||||
|
||||
const (
|
||||
serverSock = "server.sock"
|
||||
)
|
||||
|
||||
// startServer creates a gRPC server without any registered services.
|
||||
// The returned address can be used to connect to it. The cleanup
|
||||
// function stops it. It can be called multiple times.
|
||||
func startServer(t *testing.T, tmp string) (string, func()) {
|
||||
addr := path.Join(tmp, serverSock)
|
||||
listener, err := net.Listen("unix", addr)
|
||||
require.NoError(t, err, "listening on %s", addr)
|
||||
server := grpc.NewServer()
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
if err := server.Serve(listener); err != nil {
|
||||
t.Logf("starting server failed: %s", err)
|
||||
}
|
||||
}()
|
||||
return addr, func() {
|
||||
server.Stop()
|
||||
wg.Wait()
|
||||
if err := os.Remove(addr); err != nil && !os.IsNotExist(err) {
|
||||
t.Logf("remove Unix socket: %s", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestConnect(t *testing.T) {
|
||||
tmp := tmpDir(t)
|
||||
defer os.RemoveAll(tmp)
|
||||
addr, stopServer := startServer(t, tmp)
|
||||
defer stopServer()
|
||||
|
||||
conn, err := Connect(addr)
|
||||
if assert.NoError(t, err, "connect via absolute path") &&
|
||||
assert.NotNil(t, conn, "got a connection") {
|
||||
assert.Equal(t, connectivity.Ready, conn.GetState(), "connection ready")
|
||||
err = conn.Close()
|
||||
assert.NoError(t, err, "closing connection")
|
||||
}
|
||||
}
|
||||
|
||||
func TestConnectUnix(t *testing.T) {
|
||||
tmp := tmpDir(t)
|
||||
defer os.RemoveAll(tmp)
|
||||
addr, stopServer := startServer(t, tmp)
|
||||
defer stopServer()
|
||||
|
||||
conn, err := Connect("unix:///" + addr)
|
||||
if assert.NoError(t, err, "connect with unix:/// prefix") &&
|
||||
assert.NotNil(t, conn, "got a connection") {
|
||||
assert.Equal(t, connectivity.Ready, conn.GetState(), "connection ready")
|
||||
err = conn.Close()
|
||||
assert.NoError(t, err, "closing connection")
|
||||
}
|
||||
}
|
||||
|
||||
func TestWaitForServer(t *testing.T) {
|
||||
tmp := tmpDir(t)
|
||||
defer os.RemoveAll(tmp)
|
||||
|
||||
// We cannot test that Connect() waits forever for the server
|
||||
// to appear, because then we would have to let the test run
|
||||
// forever.... What we can test is that it returns shortly
|
||||
// after the server appears.
|
||||
startTime := time.Now()
|
||||
var startTimeServer time.Time
|
||||
var stopServer func()
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
defer func() {
|
||||
wg.Wait()
|
||||
stopServer()
|
||||
}()
|
||||
// Here we pick a relatively long delay before we start the
|
||||
// server. If gRPC did go into an exponential backoff before
|
||||
// retrying the connection attempt, then it probably would
|
||||
// not react promptly to the server becoming ready. Currently
|
||||
// it looks like gRPC tries to connect once per second, with
|
||||
// no exponential backoff.
|
||||
delay := 10 * time.Second
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
t.Logf("sleeping %s before starting server", delay)
|
||||
time.Sleep(delay)
|
||||
startTimeServer = time.Now()
|
||||
_, stopServer = startServer(t, tmp)
|
||||
}()
|
||||
conn, err := Connect(path.Join(tmp, serverSock))
|
||||
if assert.NoError(t, err, "connect via absolute path") {
|
||||
endTime := time.Now()
|
||||
assert.NotNil(t, conn, "got a connection")
|
||||
assert.Equal(t, connectivity.Ready.String(), conn.GetState().String(), "connection ready")
|
||||
if assert.InEpsilon(t, 1*time.Second, endTime.Sub(startTimeServer), 5, "connection established shortly after server starts") {
|
||||
assert.InEpsilon(t, delay, endTime.Sub(startTime), 1)
|
||||
}
|
||||
err = conn.Close()
|
||||
assert.NoError(t, err, "closing connection")
|
||||
}
|
||||
}
|
||||
|
||||
func TestTimout(t *testing.T) {
|
||||
tmp := tmpDir(t)
|
||||
defer os.RemoveAll(tmp)
|
||||
|
||||
startTime := time.Now()
|
||||
timeout := 5 * time.Second
|
||||
conn, err := connect(path.Join(tmp, "no-such.sock"), []grpc.DialOption{grpc.WithTimeout(timeout)}, nil)
|
||||
endTime := time.Now()
|
||||
if assert.Error(t, err, "connection should fail") {
|
||||
assert.InEpsilon(t, timeout, endTime.Sub(startTime), 1, "connection timeout")
|
||||
} else {
|
||||
err := conn.Close()
|
||||
assert.NoError(t, err, "closing connection")
|
||||
}
|
||||
}
|
||||
|
||||
func TestReconnect(t *testing.T) {
|
||||
tmp := tmpDir(t)
|
||||
defer os.RemoveAll(tmp)
|
||||
addr, stopServer := startServer(t, tmp)
|
||||
defer func() {
|
||||
stopServer()
|
||||
}()
|
||||
|
||||
// Allow reconnection (the default).
|
||||
conn, err := Connect(addr)
|
||||
if assert.NoError(t, err, "connect via absolute path") &&
|
||||
assert.NotNil(t, conn, "got a connection") {
|
||||
defer conn.Close()
|
||||
assert.Equal(t, connectivity.Ready, conn.GetState(), "connection ready")
|
||||
|
||||
if err := conn.Invoke(context.Background(), "/connect.v0.Test/Ping", nil, nil); assert.Error(t, err) {
|
||||
errStatus, _ := status.FromError(err)
|
||||
assert.Equal(t, codes.Unimplemented, errStatus.Code(), "not implemented")
|
||||
}
|
||||
|
||||
stopServer()
|
||||
startTime := time.Now()
|
||||
if err := conn.Invoke(context.Background(), "/connect.v0.Test/Ping", nil, nil); assert.Error(t, err) {
|
||||
endTime := time.Now()
|
||||
errStatus, _ := status.FromError(err)
|
||||
assert.Equal(t, codes.Unavailable, errStatus.Code(), "connection lost")
|
||||
assert.InEpsilon(t, time.Second, endTime.Sub(startTime), 1, "connection loss should be detected quickly")
|
||||
}
|
||||
|
||||
// No reconnection either when the server comes back.
|
||||
_, stopServer = startServer(t, tmp)
|
||||
// We need to give gRPC some time. It does not attempt to reconnect
|
||||
// immediately. If we send the method call too soon, the test passes
|
||||
// even though a later method call will go through again.
|
||||
time.Sleep(5 * time.Second)
|
||||
startTime = time.Now()
|
||||
if err := conn.Invoke(context.Background(), "/connect.v0.Test/Ping", nil, nil); assert.Error(t, err) {
|
||||
endTime := time.Now()
|
||||
errStatus, _ := status.FromError(err)
|
||||
assert.Equal(t, codes.Unimplemented, errStatus.Code(), "not implemented")
|
||||
assert.InEpsilon(t, time.Second, endTime.Sub(startTime), 1, "connection loss should be covered from quickly")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDisconnect(t *testing.T) {
|
||||
tmp := tmpDir(t)
|
||||
defer os.RemoveAll(tmp)
|
||||
addr, stopServer := startServer(t, tmp)
|
||||
defer func() {
|
||||
stopServer()
|
||||
}()
|
||||
|
||||
reconnectCount := 0
|
||||
conn, err := Connect(addr, OnConnectionLoss(func() bool {
|
||||
reconnectCount++
|
||||
// Don't reconnect.
|
||||
return false
|
||||
}))
|
||||
if assert.NoError(t, err, "connect via absolute path") &&
|
||||
assert.NotNil(t, conn, "got a connection") {
|
||||
defer conn.Close()
|
||||
assert.Equal(t, connectivity.Ready, conn.GetState(), "connection ready")
|
||||
|
||||
if err := conn.Invoke(context.Background(), "/connect.v0.Test/Ping", nil, nil); assert.Error(t, err) {
|
||||
errStatus, _ := status.FromError(err)
|
||||
assert.Equal(t, codes.Unimplemented, errStatus.Code(), "not implemented")
|
||||
}
|
||||
|
||||
stopServer()
|
||||
startTime := time.Now()
|
||||
if err := conn.Invoke(context.Background(), "/connect.v0.Test/Ping", nil, nil); assert.Error(t, err) {
|
||||
endTime := time.Now()
|
||||
errStatus, _ := status.FromError(err)
|
||||
assert.Equal(t, codes.Unavailable, errStatus.Code(), "connection lost")
|
||||
assert.InEpsilon(t, time.Second, endTime.Sub(startTime), 1, "connection loss should be detected quickly")
|
||||
}
|
||||
|
||||
// No reconnection either when the server comes back.
|
||||
_, stopServer = startServer(t, tmp)
|
||||
// We need to give gRPC some time. It does not attempt to reconnect
|
||||
// immediately. If we send the method call too soon, the test passes
|
||||
// even though a later method call will go through again.
|
||||
time.Sleep(5 * time.Second)
|
||||
startTime = time.Now()
|
||||
if err := conn.Invoke(context.Background(), "/connect.v0.Test/Ping", nil, nil); assert.Error(t, err) {
|
||||
endTime := time.Now()
|
||||
errStatus, _ := status.FromError(err)
|
||||
assert.Equal(t, codes.Unavailable, errStatus.Code(), "connection still lost")
|
||||
assert.InEpsilon(t, time.Second, endTime.Sub(startTime), 1, "connection loss should be detected quickly")
|
||||
}
|
||||
|
||||
assert.Equal(t, 1, reconnectCount, "connection loss callback should be called once")
|
||||
}
|
||||
}
|
||||
|
||||
func TestExplicitReconnect(t *testing.T) {
|
||||
tmp := tmpDir(t)
|
||||
defer os.RemoveAll(tmp)
|
||||
addr, stopServer := startServer(t, tmp)
|
||||
defer func() {
|
||||
stopServer()
|
||||
}()
|
||||
|
||||
reconnectCount := 0
|
||||
conn, err := Connect(addr, OnConnectionLoss(func() bool {
|
||||
reconnectCount++
|
||||
// Reconnect.
|
||||
return true
|
||||
}))
|
||||
if assert.NoError(t, err, "connect via absolute path") &&
|
||||
assert.NotNil(t, conn, "got a connection") {
|
||||
defer conn.Close()
|
||||
assert.Equal(t, connectivity.Ready, conn.GetState(), "connection ready")
|
||||
|
||||
if err := conn.Invoke(context.Background(), "/connect.v0.Test/Ping", nil, nil); assert.Error(t, err) {
|
||||
errStatus, _ := status.FromError(err)
|
||||
assert.Equal(t, codes.Unimplemented, errStatus.Code(), "not implemented")
|
||||
}
|
||||
|
||||
stopServer()
|
||||
startTime := time.Now()
|
||||
if err := conn.Invoke(context.Background(), "/connect.v0.Test/Ping", nil, nil); assert.Error(t, err) {
|
||||
endTime := time.Now()
|
||||
errStatus, _ := status.FromError(err)
|
||||
assert.Equal(t, codes.Unavailable, errStatus.Code(), "connection lost")
|
||||
assert.InEpsilon(t, time.Second, endTime.Sub(startTime), 1, "connection loss should be detected quickly")
|
||||
}
|
||||
|
||||
// No reconnection either when the server comes back.
|
||||
_, stopServer = startServer(t, tmp)
|
||||
// We need to give gRPC some time. It does not attempt to reconnect
|
||||
// immediately. If we send the method call too soon, the test passes
|
||||
// even though a later method call will go through again.
|
||||
time.Sleep(5 * time.Second)
|
||||
startTime = time.Now()
|
||||
if err := conn.Invoke(context.Background(), "/connect.v0.Test/Ping", nil, nil); assert.Error(t, err) {
|
||||
endTime := time.Now()
|
||||
errStatus, _ := status.FromError(err)
|
||||
assert.Equal(t, codes.Unimplemented, errStatus.Code(), "connection still lost")
|
||||
assert.InEpsilon(t, time.Second, endTime.Sub(startTime), 1, "connection loss should be recovered from quickly")
|
||||
}
|
||||
|
||||
assert.Equal(t, 1, reconnectCount, "connection loss callback should be called once")
|
||||
}
|
||||
}
|
224
vendor/github.com/kubernetes-csi/csi-lib-utils/protosanitizer/protosanitizer_test.go
generated
vendored
224
vendor/github.com/kubernetes-csi/csi-lib-utils/protosanitizer/protosanitizer_test.go
generated
vendored
@@ -1,224 +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.
|
||||
*/
|
||||
|
||||
package protosanitizer
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
csi03 "github.com/kubernetes-csi/csi-lib-utils/protosanitizer/test/csi03"
|
||||
csi "github.com/kubernetes-csi/csi-lib-utils/protosanitizer/test/csi10"
|
||||
"github.com/kubernetes-csi/csi-lib-utils/protosanitizer/test/csitest"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestStripSecrets(t *testing.T) {
|
||||
secretName := "secret-abc"
|
||||
secretValue := "123"
|
||||
|
||||
// CSI 0.3.0.
|
||||
createVolumeCSI03 := &csi03.CreateVolumeRequest{
|
||||
AccessibilityRequirements: &csi03.TopologyRequirement{
|
||||
Requisite: []*csi03.Topology{
|
||||
&csi03.Topology{
|
||||
Segments: map[string]string{
|
||||
"foo": "bar",
|
||||
"x": "y",
|
||||
},
|
||||
},
|
||||
&csi03.Topology{
|
||||
Segments: map[string]string{
|
||||
"a": "b",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Name: "foo",
|
||||
VolumeCapabilities: []*csi03.VolumeCapability{
|
||||
&csi03.VolumeCapability{
|
||||
AccessType: &csi03.VolumeCapability_Mount{
|
||||
Mount: &csi03.VolumeCapability_MountVolume{
|
||||
FsType: "ext4",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
CapacityRange: &csi03.CapacityRange{
|
||||
RequiredBytes: 1024,
|
||||
},
|
||||
ControllerCreateSecrets: map[string]string{
|
||||
secretName: secretValue,
|
||||
"secret-xyz": "987",
|
||||
},
|
||||
}
|
||||
|
||||
// Current spec.
|
||||
createVolume := &csi.CreateVolumeRequest{
|
||||
AccessibilityRequirements: &csi.TopologyRequirement{
|
||||
Requisite: []*csi.Topology{
|
||||
&csi.Topology{
|
||||
Segments: map[string]string{
|
||||
"foo": "bar",
|
||||
"x": "y",
|
||||
},
|
||||
},
|
||||
&csi.Topology{
|
||||
Segments: map[string]string{
|
||||
"a": "b",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Name: "foo",
|
||||
VolumeCapabilities: []*csi.VolumeCapability{
|
||||
&csi.VolumeCapability{
|
||||
AccessType: &csi.VolumeCapability_Mount{
|
||||
Mount: &csi.VolumeCapability_MountVolume{
|
||||
FsType: "ext4",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
CapacityRange: &csi.CapacityRange{
|
||||
RequiredBytes: 1024,
|
||||
},
|
||||
Secrets: map[string]string{
|
||||
secretName: secretValue,
|
||||
"secret-xyz": "987",
|
||||
},
|
||||
}
|
||||
|
||||
// Revised spec with more secret fields.
|
||||
createVolumeFuture := &csitest.CreateVolumeRequest{
|
||||
CapacityRange: &csitest.CapacityRange{
|
||||
RequiredBytes: 1024,
|
||||
},
|
||||
MaybeSecretMap: map[int64]*csitest.VolumeCapability{
|
||||
1: &csitest.VolumeCapability{ArraySecret: "aaa"},
|
||||
2: &csitest.VolumeCapability{ArraySecret: "bbb"},
|
||||
},
|
||||
Name: "foo",
|
||||
NewSecretInt: 42,
|
||||
Seecreets: map[string]string{
|
||||
secretName: secretValue,
|
||||
"secret-xyz": "987",
|
||||
},
|
||||
VolumeCapabilities: []*csitest.VolumeCapability{
|
||||
&csitest.VolumeCapability{
|
||||
AccessType: &csitest.VolumeCapability_Mount{
|
||||
Mount: &csitest.VolumeCapability_MountVolume{
|
||||
FsType: "ext4",
|
||||
},
|
||||
},
|
||||
ArraySecret: "knock knock",
|
||||
},
|
||||
&csitest.VolumeCapability{
|
||||
ArraySecret: "Who's there?",
|
||||
},
|
||||
},
|
||||
VolumeContentSource: &csitest.VolumeContentSource{
|
||||
Type: &csitest.VolumeContentSource_Volume{
|
||||
Volume: &csitest.VolumeContentSource_VolumeSource{
|
||||
VolumeId: "abc",
|
||||
OneofSecretField: "hello",
|
||||
},
|
||||
},
|
||||
NestedSecretField: "world",
|
||||
},
|
||||
}
|
||||
|
||||
type testcase struct {
|
||||
original, stripped interface{}
|
||||
}
|
||||
|
||||
cases := []testcase{
|
||||
{nil, "null"},
|
||||
{1, "1"},
|
||||
{"hello world", `"hello world"`},
|
||||
{true, "true"},
|
||||
{false, "false"},
|
||||
{&csi.CreateVolumeRequest{}, `{}`},
|
||||
// Test case from https://github.com/kubernetes-csi/csi-lib-utils/pull/1#pullrequestreview-180126394.
|
||||
{&csi.CreateVolumeRequest{
|
||||
Name: "test-volume",
|
||||
CapacityRange: &csi.CapacityRange{
|
||||
RequiredBytes: int64(1024),
|
||||
LimitBytes: int64(1024),
|
||||
},
|
||||
VolumeCapabilities: []*csi.VolumeCapability{
|
||||
&csi.VolumeCapability{
|
||||
AccessType: &csi.VolumeCapability_Mount{
|
||||
Mount: &csi.VolumeCapability_MountVolume{
|
||||
FsType: "ext4",
|
||||
MountFlags: []string{"flag1", "flag2", "flag3"},
|
||||
},
|
||||
},
|
||||
AccessMode: &csi.VolumeCapability_AccessMode{
|
||||
Mode: csi.VolumeCapability_AccessMode_MULTI_NODE_MULTI_WRITER,
|
||||
},
|
||||
},
|
||||
},
|
||||
Secrets: map[string]string{"secret1": "secret1", "secret2": "secret2"},
|
||||
Parameters: map[string]string{"param1": "param1", "param2": "param2"},
|
||||
VolumeContentSource: &csi.VolumeContentSource{},
|
||||
AccessibilityRequirements: &csi.TopologyRequirement{},
|
||||
}, `{"accessibility_requirements":{},"capacity_range":{"limit_bytes":1024,"required_bytes":1024},"name":"test-volume","parameters":{"param1":"param1","param2":"param2"},"secrets":"***stripped***","volume_capabilities":[{"AccessType":{"Mount":{"fs_type":"ext4","mount_flags":["flag1","flag2","flag3"]}},"access_mode":{"mode":5}}],"volume_content_source":{"Type":null}}`},
|
||||
{createVolume, `{"accessibility_requirements":{"requisite":[{"segments":{"foo":"bar","x":"y"}},{"segments":{"a":"b"}}]},"capacity_range":{"required_bytes":1024},"name":"foo","secrets":"***stripped***","volume_capabilities":[{"AccessType":{"Mount":{"fs_type":"ext4"}}}]}`},
|
||||
{createVolumeCSI03, `{"accessibility_requirements":{"requisite":[{"segments":{"foo":"bar","x":"y"}},{"segments":{"a":"b"}}]},"capacity_range":{"required_bytes":1024},"controller_create_secrets":"***stripped***","name":"foo","volume_capabilities":[{"AccessType":{"Mount":{"fs_type":"ext4"}}}]}`},
|
||||
{&csitest.CreateVolumeRequest{}, `{}`},
|
||||
{createVolumeFuture,
|
||||
// Secrets are *not* removed from all fields yet. This will have to be fixed one way or another
|
||||
// before the CSI spec can start using secrets there (currently it doesn't).
|
||||
// The test is still useful because it shows that also complicated fields get serialized.
|
||||
// `{"capacity_range":{"required_bytes":1024},"maybe_secret_map":{"1":{"AccessType":null,"array_secret":"***stripped***"},"2":{"AccessType":null,"array_secret":"***stripped***"}},"name":"foo","new_secret_int":"***stripped***","seecreets":"***stripped***","volume_capabilities":[{"AccessType":{"Mount":{"fs_type":"ext4"}},"array_secret":"***stripped***"},{"AccessType":null,"array_secret":"***stripped***"}],"volume_content_source":{"Type":{"Volume":{"oneof_secret_field":"***stripped***","volume_id":"abc"}},"nested_secret_field":"***stripped***"}}`,
|
||||
`{"capacity_range":{"required_bytes":1024},"maybe_secret_map":{"1":{"AccessType":null,"array_secret":"aaa"},"2":{"AccessType":null,"array_secret":"bbb"}},"name":"foo","new_secret_int":"***stripped***","seecreets":"***stripped***","volume_capabilities":[{"AccessType":{"Mount":{"fs_type":"ext4"}},"array_secret":"***stripped***"},{"AccessType":null,"array_secret":"***stripped***"}],"volume_content_source":{"Type":{"Volume":{"oneof_secret_field":"hello","volume_id":"abc"}},"nested_secret_field":"***stripped***"}}`,
|
||||
},
|
||||
}
|
||||
|
||||
// Message from revised spec as received by a sidecar based on the current spec.
|
||||
// The XXX_unrecognized field contains secrets and must not get logged.
|
||||
unknownFields := &csi.CreateVolumeRequest{}
|
||||
data, err := proto.Marshal(createVolumeFuture)
|
||||
if assert.NoError(t, err, "marshall future message") &&
|
||||
assert.NoError(t, proto.Unmarshal(data, unknownFields), "unmarshal with unknown fields") {
|
||||
cases = append(cases, testcase{unknownFields,
|
||||
`{"capacity_range":{"required_bytes":1024},"name":"foo","secrets":"***stripped***","volume_capabilities":[{"AccessType":{"Mount":{"fs_type":"ext4"}}},{"AccessType":null}],"volume_content_source":{"Type":{"Volume":{"volume_id":"abc"}}}}`,
|
||||
})
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
before := fmt.Sprint(c.original)
|
||||
var stripped fmt.Stringer
|
||||
if _, ok := c.original.(*csi03.CreateVolumeRequest); ok {
|
||||
stripped = StripSecretsCSI03(c.original)
|
||||
} else {
|
||||
stripped = StripSecrets(c.original)
|
||||
}
|
||||
if assert.Equal(t, c.stripped, fmt.Sprintf("%s", stripped), "unexpected result for fmt s of %s", c.original) {
|
||||
if assert.Equal(t, c.stripped, fmt.Sprintf("%v", stripped), "unexpected result for fmt v of %s", c.original) {
|
||||
assert.Equal(t, c.stripped, fmt.Sprintf("%+v", stripped), "unexpected result for fmt +v of %s", c.original)
|
||||
}
|
||||
}
|
||||
assert.Equal(t, before, fmt.Sprint(c.original), "original value modified")
|
||||
}
|
||||
|
||||
// The secret is hidden because StripSecrets is a struct referencing it.
|
||||
dump := fmt.Sprintf("%#v", StripSecrets(createVolume))
|
||||
assert.NotContains(t, dump, secretName)
|
||||
assert.NotContains(t, dump, secretValue)
|
||||
}
|
5
vendor/github.com/kubernetes-csi/csi-lib-utils/protosanitizer/test/.gitignore
generated
vendored
5
vendor/github.com/kubernetes-csi/csi-lib-utils/protosanitizer/test/.gitignore
generated
vendored
@@ -1,5 +0,0 @@
|
||||
/protoc
|
||||
/protoc-gen-go
|
||||
/csi.a
|
||||
/.protoc
|
||||
.build
|
136
vendor/github.com/kubernetes-csi/csi-lib-utils/protosanitizer/test/Makefile
generated
vendored
136
vendor/github.com/kubernetes-csi/csi-lib-utils/protosanitizer/test/Makefile
generated
vendored
@@ -1,136 +0,0 @@
|
||||
all: build
|
||||
|
||||
########################################################################
|
||||
## GOLANG ##
|
||||
########################################################################
|
||||
|
||||
# If GOPATH isn't defined then set its default location.
|
||||
ifeq (,$(strip $(GOPATH)))
|
||||
GOPATH := $(HOME)/go
|
||||
else
|
||||
# If GOPATH is already set then update GOPATH to be its own
|
||||
# first element.
|
||||
GOPATH := $(word 1,$(subst :, ,$(GOPATH)))
|
||||
endif
|
||||
export GOPATH
|
||||
|
||||
|
||||
########################################################################
|
||||
## PROTOC ##
|
||||
########################################################################
|
||||
|
||||
# Only set PROTOC_VER if it has an empty value.
|
||||
ifeq (,$(strip $(PROTOC_VER)))
|
||||
PROTOC_VER := 3.5.1
|
||||
endif
|
||||
|
||||
PROTOC_OS := $(shell uname -s)
|
||||
ifeq (Darwin,$(PROTOC_OS))
|
||||
PROTOC_OS := osx
|
||||
endif
|
||||
|
||||
PROTOC_ARCH := $(shell uname -m)
|
||||
ifeq (i386,$(PROTOC_ARCH))
|
||||
PROTOC_ARCH := x86_32
|
||||
endif
|
||||
|
||||
PROTOC := ./protoc
|
||||
PROTOC_ZIP := protoc-$(PROTOC_VER)-$(PROTOC_OS)-$(PROTOC_ARCH).zip
|
||||
PROTOC_URL := https://github.com/google/protobuf/releases/download/v$(PROTOC_VER)/$(PROTOC_ZIP)
|
||||
PROTOC_TMP_DIR := .protoc
|
||||
PROTOC_TMP_BIN := $(PROTOC_TMP_DIR)/bin/protoc
|
||||
|
||||
$(PROTOC):
|
||||
-mkdir -p "$(PROTOC_TMP_DIR)" && \
|
||||
curl -L $(PROTOC_URL) -o "$(PROTOC_TMP_DIR)/$(PROTOC_ZIP)" && \
|
||||
unzip "$(PROTOC_TMP_DIR)/$(PROTOC_ZIP)" -d "$(PROTOC_TMP_DIR)" && \
|
||||
chmod 0755 "$(PROTOC_TMP_BIN)" && \
|
||||
cp -f "$(PROTOC_TMP_BIN)" "$@"
|
||||
stat "$@" > /dev/null 2>&1
|
||||
|
||||
|
||||
########################################################################
|
||||
## PROTOC-GEN-GO ##
|
||||
########################################################################
|
||||
|
||||
# This is the recipe for getting and installing the go plug-in
|
||||
# for protoc
|
||||
PROTOC_GEN_GO_PKG := github.com/golang/protobuf/protoc-gen-go
|
||||
PROTOC_GEN_GO := protoc-gen-go
|
||||
$(PROTOC_GEN_GO): PROTOBUF_PKG := $(dir $(PROTOC_GEN_GO_PKG))
|
||||
$(PROTOC_GEN_GO): PROTOBUF_VERSION := v1.2.0
|
||||
$(PROTOC_GEN_GO):
|
||||
mkdir -p $(dir $(GOPATH)/src/$(PROTOBUF_PKG))
|
||||
test -d $(GOPATH)/src/$(PROTOBUF_PKG)/.git || git clone https://$(PROTOBUF_PKG) $(GOPATH)/src/$(PROTOBUF_PKG)
|
||||
(cd $(GOPATH)/src/$(PROTOBUF_PKG) && \
|
||||
(test "$$(git describe --tags | head -1)" = "$(PROTOBUF_VERSION)" || \
|
||||
(git fetch && git checkout tags/$(PROTOBUF_VERSION))))
|
||||
(cd $(GOPATH)/src/$(PROTOBUF_PKG) && go get -v -d $$(go list -f '{{ .ImportPath }}' ./...)) && \
|
||||
go build -o "$@" $(PROTOC_GEN_GO_PKG)
|
||||
|
||||
|
||||
########################################################################
|
||||
## PATH ##
|
||||
########################################################################
|
||||
|
||||
# Update PATH with the current directory. This enables the protoc
|
||||
# binary to discover the protoc-gen-go binary, built inside this
|
||||
# directory.
|
||||
export PATH := $(shell pwd):$(PATH)
|
||||
|
||||
|
||||
########################################################################
|
||||
## BUILD ##
|
||||
########################################################################
|
||||
CSI_PROTO := ./csitest.proto
|
||||
CSI_PKG_ROOT := github.com/kubernetes-csi/csi-lib-utils/protosanitizer/test
|
||||
CSI_PKG_SUB := $(shell cat $(CSI_PROTO) | sed -n -e 's/^package.\([^;]*\).v[0-9]\+;$$/\1/p'|tr '.' '/')
|
||||
CSI_BUILD := $(CSI_PKG_SUB)/.build
|
||||
CSI_GO := $(CSI_PKG_SUB)/csitest.pb.go
|
||||
CSI_A := csi.a
|
||||
CSI_GO_TMP := $(CSI_BUILD)/$(CSI_PKG_ROOT)/csitest.pb.go
|
||||
|
||||
# This recipe generates the go language bindings to a temp area.
|
||||
$(CSI_GO_TMP): HERE := $(shell pwd)
|
||||
$(CSI_GO_TMP): PTYPES_PKG := github.com/golang/protobuf/ptypes
|
||||
$(CSI_GO_TMP): GO_OUT := plugins=grpc
|
||||
$(CSI_GO_TMP): GO_OUT := $(GO_OUT),Mgoogle/protobuf/descriptor.proto=github.com/golang/protobuf/protoc-gen-go/descriptor
|
||||
$(CSI_GO_TMP): GO_OUT := $(GO_OUT),Mgoogle/protobuf/wrappers.proto=$(PTYPES_PKG)/wrappers
|
||||
$(CSI_GO_TMP): GO_OUT := $(GO_OUT):"$(HERE)/$(CSI_BUILD)"
|
||||
$(CSI_GO_TMP): INCLUDE := -I$(GOPATH)/src -I$(HERE)/$(PROTOC_TMP_DIR)/include
|
||||
$(CSI_GO_TMP): $(CSI_PROTO) | $(PROTOC) $(PROTOC_GEN_GO)
|
||||
@mkdir -p "$(@D)"
|
||||
(cd "$(GOPATH)/src" && \
|
||||
$(HERE)/$(PROTOC) $(INCLUDE) --go_out=$(GO_OUT) "$(CSI_PKG_ROOT)/$(<F)")
|
||||
|
||||
# The temp language bindings are compared to the ones that are
|
||||
# versioned. If they are different then it means the language
|
||||
# bindings were not updated prior to being committed.
|
||||
$(CSI_GO): $(CSI_GO_TMP)
|
||||
ifeq (true,$(TRAVIS))
|
||||
diff "$@" "$?"
|
||||
else
|
||||
@mkdir -p "$(@D)"
|
||||
diff "$@" "$?" > /dev/null 2>&1 || cp -f "$?" "$@"
|
||||
endif
|
||||
|
||||
# This recipe builds the Go archive from the sources in three steps:
|
||||
#
|
||||
# 1. Go get any missing dependencies.
|
||||
# 2. Cache the packages.
|
||||
# 3. Build the archive file.
|
||||
$(CSI_A): $(CSI_GO)
|
||||
go get -v -d ./...
|
||||
go install ./$(CSI_PKG_SUB)
|
||||
go build -o "$@" ./$(CSI_PKG_SUB)
|
||||
|
||||
build: $(CSI_A)
|
||||
|
||||
clean:
|
||||
go clean -i ./...
|
||||
rm -rf "$(CSI_A)" "$(CSI_GO)" "$(CSI_BUILD)"
|
||||
|
||||
clobber: clean
|
||||
rm -fr "$(PROTOC)" "$(PROTOC_GEN_GO)" "$(CSI_PKG_SUB)" "$(PROTOC_TMP_DIR)"
|
||||
|
||||
.PHONY: clean clobber
|
2
vendor/github.com/kubernetes-csi/csi-lib-utils/protosanitizer/test/README.md
generated
vendored
2
vendor/github.com/kubernetes-csi/csi-lib-utils/protosanitizer/test/README.md
generated
vendored
@@ -1,2 +0,0 @@
|
||||
This is a *modified* version of the CSI 1.0.0 spec. It's only purpose is
|
||||
to test the stripping of secret fields.
|
1203
vendor/github.com/kubernetes-csi/csi-lib-utils/protosanitizer/test/csi.proto
generated
vendored
1203
vendor/github.com/kubernetes-csi/csi-lib-utils/protosanitizer/test/csi.proto
generated
vendored
File diff suppressed because it is too large
Load Diff
4991
vendor/github.com/kubernetes-csi/csi-lib-utils/protosanitizer/test/csi03/csi.pb.go
generated
vendored
4991
vendor/github.com/kubernetes-csi/csi-lib-utils/protosanitizer/test/csi03/csi.pb.go
generated
vendored
File diff suppressed because it is too large
Load Diff
5277
vendor/github.com/kubernetes-csi/csi-lib-utils/protosanitizer/test/csi10/csi.pb.go
generated
vendored
5277
vendor/github.com/kubernetes-csi/csi-lib-utils/protosanitizer/test/csi10/csi.pb.go
generated
vendored
File diff suppressed because it is too large
Load Diff
1217
vendor/github.com/kubernetes-csi/csi-lib-utils/protosanitizer/test/csitest.proto
generated
vendored
1217
vendor/github.com/kubernetes-csi/csi-lib-utils/protosanitizer/test/csitest.proto
generated
vendored
File diff suppressed because it is too large
Load Diff
5326
vendor/github.com/kubernetes-csi/csi-lib-utils/protosanitizer/test/csitest/csitest.pb.go
generated
vendored
5326
vendor/github.com/kubernetes-csi/csi-lib-utils/protosanitizer/test/csitest/csitest.pb.go
generated
vendored
File diff suppressed because it is too large
Load Diff
31
vendor/github.com/kubernetes-csi/csi-lib-utils/release-tools/CONTRIBUTING.md
generated
vendored
31
vendor/github.com/kubernetes-csi/csi-lib-utils/release-tools/CONTRIBUTING.md
generated
vendored
@@ -1,31 +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](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:
|
||||
|
||||
<!---
|
||||
If your repo has certain guidelines for contribution, put them here ahead of the general k8s resources
|
||||
-->
|
||||
|
||||
- [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!
|
||||
|
||||
<!---
|
||||
Custom Information - if you're copying this template for the first time you can add custom content here, for example:
|
||||
|
||||
## Contact Information
|
||||
|
||||
- [Slack channel](https://kubernetes.slack.com/messages/kubernetes-users) - Replace `kubernetes-users` with your slack channel string, this will send users directly to your channel.
|
||||
- [Mailing list](URL)
|
||||
|
||||
-->
|
11
vendor/github.com/kubernetes-csi/csi-lib-utils/release-tools/OWNERS
generated
vendored
11
vendor/github.com/kubernetes-csi/csi-lib-utils/release-tools/OWNERS
generated
vendored
@@ -1,11 +0,0 @@
|
||||
# See the OWNERS docs: https://git.k8s.io/community/contributors/guide/owners.md
|
||||
|
||||
approvers:
|
||||
- saad-ali
|
||||
- msau42
|
||||
- pohly
|
||||
|
||||
reviewers:
|
||||
- saad-ali
|
||||
- msau42
|
||||
- pohly
|
51
vendor/github.com/kubernetes-csi/csi-lib-utils/release-tools/README.md
generated
vendored
51
vendor/github.com/kubernetes-csi/csi-lib-utils/release-tools/README.md
generated
vendored
@@ -1,51 +0,0 @@
|
||||
# [csi-release-tools](https://github.com/kubernetes-csi/csi-release-tools)
|
||||
|
||||
These build and test rules can be shared between different Go projects
|
||||
without modifications. Customization for the different projects happen
|
||||
in the top-level Makefile.
|
||||
|
||||
The rules include support for building and pushing Docker images, with
|
||||
the following features:
|
||||
- one or more command and image per project
|
||||
- push canary and/or tagged release images
|
||||
- automatically derive the image tag(s) from repo tags
|
||||
- the source code revision is stored in a "revision" image label
|
||||
- never overwrites an existing release image
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
The expected repository layout is:
|
||||
- `cmd/*/*.go` - source code for each command
|
||||
- `cmd/*/Dockerfile` - docker file for each command or
|
||||
Dockerfile in the root when only building a single command
|
||||
- `Makefile` - includes `release-tools/build.make` and sets
|
||||
configuration variables
|
||||
- `.travis.yml` - a symlink to `release-tools/.travis.yml`
|
||||
|
||||
To create a release, tag a certain revision with a name that
|
||||
starts with `v`, for example `v1.0.0`, then `make push`
|
||||
while that commit is checked out.
|
||||
|
||||
It does not matter on which branch that revision exists, i.e. it is
|
||||
possible to create releases directly from master. A release branch can
|
||||
still be created for maintenance releases later if needed.
|
||||
|
||||
Release branches are expected to be named `release-x.y` for releases
|
||||
`x.y.z`. Building from such a branch creates `x.y-canary`
|
||||
images. Building from master creates the main `canary` image.
|
||||
|
||||
Sharing and updating
|
||||
--------------------
|
||||
|
||||
[`git subtree`](https://github.com/git/git/blob/master/contrib/subtree/git-subtree.txt)
|
||||
is the recommended way of maintaining a copy of the rules inside the
|
||||
`release-tools` directory of a project. This way, it is possible to make
|
||||
changes also locally, test them and then push them back to the shared
|
||||
repository at a later time.
|
||||
|
||||
Cheat sheet:
|
||||
|
||||
- `git subtree add --prefix=release-tools https://github.com/kubernetes-csi/csi-release-tools.git master` - add release tools to a repo which does not have them yet (only once)
|
||||
- `git subtree pull --prefix=release-tools https://github.com/kubernetes-csi/csi-release-tools.git master` - update local copy to latest upstream (whenever upstream changes)
|
||||
- edit, `git commit`, `git subtree push --prefix=release-tools git@github.com:<user>/csi-release-tools.git <my-new-or-existing-branch>` - push to a new branch before submitting a PR
|
5
vendor/github.com/kubernetes-csi/csi-lib-utils/release-tools/RELEASE.md
generated
vendored
5
vendor/github.com/kubernetes-csi/csi-lib-utils/release-tools/RELEASE.md
generated
vendored
@@ -1,5 +0,0 @@
|
||||
# Release Process
|
||||
|
||||
No tagged releases are planned at this point. The intention is to keep
|
||||
the master branch in a state such that it can be used for all
|
||||
supported branches in downstream repos which use these files.
|
14
vendor/github.com/kubernetes-csi/csi-lib-utils/release-tools/SECURITY_CONTACTS
generated
vendored
14
vendor/github.com/kubernetes-csi/csi-lib-utils/release-tools/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
|
||||
msau42
|
124
vendor/github.com/kubernetes-csi/csi-lib-utils/release-tools/build.make
generated
vendored
124
vendor/github.com/kubernetes-csi/csi-lib-utils/release-tools/build.make
generated
vendored
@@ -1,124 +0,0 @@
|
||||
# Copyright 2019 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.
|
||||
|
||||
.PHONY: build-% build container-% container push-% push clean test
|
||||
|
||||
# A space-separated list of all commands in the repository, must be
|
||||
# set in main Makefile of a repository.
|
||||
# CMDS=
|
||||
|
||||
# This is the default. It can be overridden in the main Makefile after
|
||||
# including build.make.
|
||||
REGISTRY_NAME=quay.io/k8scsi
|
||||
|
||||
# Revision that gets built into each binary via the main.version
|
||||
# string. Uses the `git describe` output based on the most recent
|
||||
# version tag with a short revision suffix or, if nothing has been
|
||||
# tagged yet, just the revision.
|
||||
#
|
||||
# Beware that tags may also be missing in shallow clones as done by
|
||||
# some CI systems (like TravisCI, which pulls only 50 commits).
|
||||
REV=$(shell git describe --long --tags --match='v*' --dirty 2>/dev/null || git rev-list -n1 HEAD)
|
||||
|
||||
# A space-separated list of image tags under which the current build is to be pushed.
|
||||
# Determined dynamically.
|
||||
IMAGE_TAGS=
|
||||
|
||||
# A "canary" image gets built if the current commit is the head of the remote "master" branch.
|
||||
# That branch does not exist when building some other branch in TravisCI.
|
||||
IMAGE_TAGS+=$(shell if [ "$$(git rev-list -n1 HEAD)" = "$$(git rev-list -n1 origin/master 2>/dev/null)" ]; then echo "canary"; fi)
|
||||
|
||||
# A "X.Y.Z-canary" image gets built if the current commit is the head of a "origin/release-X.Y.Z" branch.
|
||||
# The actual suffix does not matter, only the "release-" prefix is checked.
|
||||
IMAGE_TAGS+=$(shell git branch -r --points-at=HEAD | grep 'origin/release-' | grep -v -e ' -> ' | sed -e 's;.*/release-\(.*\);\1-canary;')
|
||||
|
||||
# A release image "vX.Y.Z" gets built if there is a tag of that format for the current commit.
|
||||
# --abbrev=0 suppresses long format, only showing the closest tag.
|
||||
IMAGE_TAGS+=$(shell tagged="$$(git describe --tags --match='v*' --abbrev=0)"; if [ "$$tagged" ] && [ "$$(git rev-list -n1 HEAD)" = "$$(git rev-list -n1 $$tagged)" ]; then echo $$tagged; fi)
|
||||
|
||||
# Images are named after the command contained in them.
|
||||
IMAGE_NAME=$(REGISTRY_NAME)/$*
|
||||
|
||||
ifdef V
|
||||
# Adding "-alsologtostderr" assumes that all test binaries contain glog. This is not guaranteed.
|
||||
TESTARGS = -v -args -alsologtostderr -v 5
|
||||
else
|
||||
TESTARGS =
|
||||
endif
|
||||
|
||||
# Specific packages can be excluded from each of the tests below by setting the *_FILTER_CMD variables
|
||||
# to something like "| grep -v 'github.com/kubernetes-csi/project/pkg/foobar'". See usage below.
|
||||
|
||||
build-%:
|
||||
mkdir -p bin
|
||||
CGO_ENABLED=0 GOOS=linux go build -a -ldflags '-X main.version=$(REV) -extldflags "-static"' -o ./bin/$* ./cmd/$*
|
||||
|
||||
container-%: build-%
|
||||
docker build -t $*:latest -f $(shell if [ -e ./cmd/$*/Dockerfile ]; then echo ./cmd/$*/Dockerfile; else echo Dockerfile; fi) --label revision=$(REV) .
|
||||
|
||||
push-%: container-%
|
||||
set -ex; \
|
||||
push_image () { \
|
||||
docker tag $*:latest $(IMAGE_NAME):$$tag; \
|
||||
docker push $(IMAGE_NAME):$$tag; \
|
||||
}; \
|
||||
for tag in $(IMAGE_TAGS); do \
|
||||
if [ "$$tag" = "canary" ] || echo "$$tag" | grep -q -e '-canary$$'; then \
|
||||
: "creating or overwriting canary image"; \
|
||||
push_image; \
|
||||
elif docker pull $(IMAGE_NAME):$$tag 2>&1 | tee /dev/stderr | grep -q "manifest for $(IMAGE_NAME):$$tag not found"; then \
|
||||
: "creating release image"; \
|
||||
push_image; \
|
||||
else \
|
||||
: "release image $(IMAGE_NAME):$$tag already exists, skipping push"; \
|
||||
fi; \
|
||||
done
|
||||
|
||||
build: $(CMDS:%=build-%)
|
||||
container: $(CMDS:%=container-%)
|
||||
push: $(CMDS:%=push-%)
|
||||
|
||||
clean:
|
||||
-rm -rf bin
|
||||
|
||||
test:
|
||||
|
||||
.PHONY: test-go
|
||||
test: test-go
|
||||
test-go:
|
||||
@ echo; echo "### $@:"
|
||||
go test `go list ./... | grep -v 'vendor' $(TEST_GO_FILTER_CMD)` $(TESTARGS)
|
||||
|
||||
.PHONY: test-vet
|
||||
test: test-vet
|
||||
test-vet:
|
||||
@ echo; echo "### $@:"
|
||||
go vet `go list ./... | grep -v vendor $(TEST_VET_FILTER_CMD)`
|
||||
|
||||
.PHONY: test-fmt
|
||||
test: test-fmt
|
||||
test-fmt:
|
||||
@ echo; echo "### $@:"
|
||||
files=$$(find . -name '*.go' | grep -v './vendor' $(TEST_FMT_FILTER_CMD)); \
|
||||
if [ $$(gofmt -d $$files | wc -l) -ne 0 ]; then \
|
||||
echo "formatting errors:"; \
|
||||
gofmt -d $$files; \
|
||||
false; \
|
||||
fi
|
||||
|
||||
.PHONY: test-subtree
|
||||
test: test-subtree
|
||||
test-subtree:
|
||||
@ echo; echo "### $@:"
|
||||
./release-tools/verify-subtree.sh release-tools
|
3
vendor/github.com/kubernetes-csi/csi-lib-utils/release-tools/code-of-conduct.md
generated
vendored
3
vendor/github.com/kubernetes-csi/csi-lib-utils/release-tools/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)
|
14
vendor/github.com/kubernetes-csi/csi-lib-utils/release-tools/travis.yml
generated
vendored
14
vendor/github.com/kubernetes-csi/csi-lib-utils/release-tools/travis.yml
generated
vendored
@@ -1,14 +0,0 @@
|
||||
language: go
|
||||
sudo: required
|
||||
services:
|
||||
- docker
|
||||
matrix:
|
||||
include:
|
||||
- go: 1.11.1
|
||||
script:
|
||||
- make -k all test
|
||||
after_success:
|
||||
- if [ "${TRAVIS_PULL_REQUEST}" == "false" ]; then
|
||||
docker login -u "${DOCKER_USERNAME}" -p "${DOCKER_PASSWORD}" quay.io;
|
||||
make push;
|
||||
fi
|
41
vendor/github.com/kubernetes-csi/csi-lib-utils/release-tools/verify-subtree.sh
generated
vendored
41
vendor/github.com/kubernetes-csi/csi-lib-utils/release-tools/verify-subtree.sh
generated
vendored
@@ -1,41 +0,0 @@
|
||||
#! /bin/sh -e
|
||||
#
|
||||
# Copyright 2019 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.
|
||||
|
||||
# This script verifies that the content of a directory managed
|
||||
# by "git subtree" has not been modified locally. It does that
|
||||
# by looking for commits that modify the files with the
|
||||
# subtree prefix (aka directory) while ignoring merge
|
||||
# commits. Merge commits are where "git subtree" pulls the
|
||||
# upstream files into the directory.
|
||||
#
|
||||
# Theoretically a developer can subvert this check by modifying files
|
||||
# in a merge commit, but in practice that shouldn't happen.
|
||||
|
||||
DIR="$1"
|
||||
if [ ! "$DIR" ]; then
|
||||
echo "usage: $0 <directory>" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
REV=$(git log -n1 --format=format:%H --no-merges -- "$DIR")
|
||||
if [ "$REV" ]; then
|
||||
echo "Directory '$DIR' contains non-upstream changes:"
|
||||
echo
|
||||
git log --no-merges -- "$DIR"
|
||||
exit 1
|
||||
else
|
||||
echo "$DIR is a clean copy of upstream."
|
||||
fi
|
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