Update go dependencies
This commit is contained in:
parent
15ffb51394
commit
bb4d483837
1621 changed files with 86368 additions and 284392 deletions
149
vendor/k8s.io/kubernetes/pkg/util/file/file_test.go
generated
vendored
149
vendor/k8s.io/kubernetes/pkg/util/file/file_test.go
generated
vendored
|
|
@ -1,149 +0,0 @@
|
|||
/*
|
||||
Copyright 2017 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 file
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"testing"
|
||||
|
||||
"github.com/spf13/afero"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func RecoverEnv(wd, tmpDir string) {
|
||||
os.Chdir(wd)
|
||||
os.RemoveAll(tmpDir)
|
||||
}
|
||||
|
||||
func TestFileUtils(t *testing.T) {
|
||||
fs := &afero.Afero{Fs: afero.NewOsFs()}
|
||||
// Create tmp dir
|
||||
tmpDir, err := fs.TempDir(os.TempDir(), "util_file_test_")
|
||||
if err != nil {
|
||||
t.Fatal("Failed to test: failed to create temp dir.")
|
||||
}
|
||||
|
||||
// create tmp file
|
||||
tmpFile, err := fs.TempFile(tmpDir, "test_file_exists_")
|
||||
if err != nil {
|
||||
t.Fatal("Failed to test: failed to create temp file.")
|
||||
}
|
||||
|
||||
// create tmp sym link
|
||||
tmpSymlinkName := filepath.Join(tmpDir, "test_file_exists_sym_link")
|
||||
err = os.Symlink(tmpFile.Name(), tmpSymlinkName)
|
||||
if err != nil {
|
||||
t.Fatal("Failed to test: failed to create sym link.")
|
||||
}
|
||||
|
||||
// create tmp sub dir
|
||||
tmpSubDir, err := fs.TempDir(tmpDir, "sub_")
|
||||
if err != nil {
|
||||
t.Fatal("Failed to test: failed to create temp sub dir.")
|
||||
}
|
||||
|
||||
// record the current dir
|
||||
currentDir, err := os.Getwd()
|
||||
if err != nil {
|
||||
t.Fatal("Failed to test: failed to get current dir.")
|
||||
}
|
||||
|
||||
// change the work dir to temp dir
|
||||
err = os.Chdir(tmpDir)
|
||||
if err != nil {
|
||||
t.Fatal("Failed to test: failed to change work dir.")
|
||||
}
|
||||
|
||||
// recover test environment
|
||||
defer RecoverEnv(currentDir, tmpDir)
|
||||
|
||||
t.Run("TestFileExists", func(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
fileName string
|
||||
expectedError bool
|
||||
expectedValue bool
|
||||
}{
|
||||
{"file_not_exists", filepath.Join(tmpDir, "file_not_exist_case"), false, false},
|
||||
{"file_exists", tmpFile.Name(), false, true},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
realValued, realError := FileExists(test.fileName)
|
||||
if test.expectedError {
|
||||
assert.Errorf(t, realError, "Failed to test with '%s': %s", test.fileName, test.name)
|
||||
} else {
|
||||
assert.EqualValuesf(t, test.expectedValue, realValued, "Failed to test with '%s': %s", test.fileName, test.name)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("TestFileOrSymlinkExists", func(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
fileName string
|
||||
expectedError bool
|
||||
expectedValue bool
|
||||
}{
|
||||
{"file_not_exists", filepath.Join(tmpDir, "file_not_exist_case"), false, false},
|
||||
{"file_exists", tmpFile.Name(), false, true},
|
||||
{"symlink_exists", tmpSymlinkName, false, true},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
realValued, realError := FileOrSymlinkExists(test.fileName)
|
||||
if test.expectedError {
|
||||
assert.Errorf(t, realError, "Failed to test with '%s': %s", test.fileName, test.name)
|
||||
} else {
|
||||
assert.EqualValuesf(t, test.expectedValue, realValued, "Failed to test with '%s': %s", test.fileName, test.name)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("TestReadDirNoStat", func(t *testing.T) {
|
||||
_, tmpFileSimpleName := filepath.Split(tmpFile.Name())
|
||||
_, tmpSymlinkSimpleName := filepath.Split(tmpSymlinkName)
|
||||
_, tmpSubDirSimpleName := filepath.Split(tmpSubDir)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
dirName string
|
||||
expectedError bool
|
||||
expectedValue []string
|
||||
}{
|
||||
{"dir_not_exists", filepath.Join(tmpDir, "file_not_exist_case"), true, []string{}},
|
||||
{"dir_is_empty", "", false, []string{tmpFileSimpleName, tmpSymlinkSimpleName, tmpSubDirSimpleName}},
|
||||
{"dir_exists", tmpDir, false, []string{tmpFileSimpleName, tmpSymlinkSimpleName, tmpSubDirSimpleName}},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
realValued, realError := ReadDirNoStat(test.dirName)
|
||||
|
||||
// execute sort action before compare
|
||||
sort.Strings(realValued)
|
||||
sort.Strings(test.expectedValue)
|
||||
|
||||
if test.expectedError {
|
||||
assert.Errorf(t, realError, "Failed to test with '%s': %s", test.dirName, test.name)
|
||||
} else {
|
||||
assert.EqualValuesf(t, test.expectedValue, realValued, "Failed to test with '%s': %s", test.dirName, test.name)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
147
vendor/k8s.io/kubernetes/pkg/util/hash/hash_test.go
generated
vendored
147
vendor/k8s.io/kubernetes/pkg/util/hash/hash_test.go
generated
vendored
|
|
@ -1,147 +0,0 @@
|
|||
/*
|
||||
Copyright 2015 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 hash
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"hash/adler32"
|
||||
"testing"
|
||||
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
)
|
||||
|
||||
type A struct {
|
||||
x int
|
||||
y string
|
||||
}
|
||||
|
||||
type B struct {
|
||||
x []int
|
||||
y map[string]bool
|
||||
}
|
||||
|
||||
type C struct {
|
||||
x int
|
||||
y string
|
||||
}
|
||||
|
||||
func (c C) String() string {
|
||||
return fmt.Sprintf("%d:%s", c.x, c.y)
|
||||
}
|
||||
|
||||
func TestDeepHashObject(t *testing.T) {
|
||||
successCases := []func() interface{}{
|
||||
func() interface{} { return 8675309 },
|
||||
func() interface{} { return "Jenny, I got your number" },
|
||||
func() interface{} { return []string{"eight", "six", "seven"} },
|
||||
func() interface{} { return [...]int{5, 3, 0, 9} },
|
||||
func() interface{} { return map[int]string{8: "8", 6: "6", 7: "7"} },
|
||||
func() interface{} { return map[string]int{"5": 5, "3": 3, "0": 0, "9": 9} },
|
||||
func() interface{} { return A{867, "5309"} },
|
||||
func() interface{} { return &A{867, "5309"} },
|
||||
func() interface{} {
|
||||
return B{[]int{8, 6, 7}, map[string]bool{"5": true, "3": true, "0": true, "9": true}}
|
||||
},
|
||||
func() interface{} { return map[A]bool{{8675309, "Jenny"}: true, {9765683, "!Jenny"}: false} },
|
||||
func() interface{} { return map[C]bool{{8675309, "Jenny"}: true, {9765683, "!Jenny"}: false} },
|
||||
func() interface{} { return map[*A]bool{{8675309, "Jenny"}: true, {9765683, "!Jenny"}: false} },
|
||||
func() interface{} { return map[*C]bool{{8675309, "Jenny"}: true, {9765683, "!Jenny"}: false} },
|
||||
}
|
||||
|
||||
for _, tc := range successCases {
|
||||
hasher1 := adler32.New()
|
||||
DeepHashObject(hasher1, tc())
|
||||
hash1 := hasher1.Sum32()
|
||||
DeepHashObject(hasher1, tc())
|
||||
hash2 := hasher1.Sum32()
|
||||
if hash1 != hash2 {
|
||||
t.Fatalf("hash of the same object (%q) produced different results: %d vs %d", toString(tc()), hash1, hash2)
|
||||
}
|
||||
for i := 0; i < 100; i++ {
|
||||
hasher2 := adler32.New()
|
||||
|
||||
DeepHashObject(hasher1, tc())
|
||||
hash1a := hasher1.Sum32()
|
||||
DeepHashObject(hasher2, tc())
|
||||
hash2a := hasher2.Sum32()
|
||||
|
||||
if hash1a != hash1 {
|
||||
t.Errorf("repeated hash of the same object (%q) produced different results: %d vs %d", toString(tc()), hash1, hash1a)
|
||||
}
|
||||
if hash2a != hash2 {
|
||||
t.Errorf("repeated hash of the same object (%q) produced different results: %d vs %d", toString(tc()), hash2, hash2a)
|
||||
}
|
||||
if hash1a != hash2a {
|
||||
t.Errorf("hash of the same object produced (%q) different results: %d vs %d", toString(tc()), hash1a, hash2a)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func toString(obj interface{}) string {
|
||||
return spew.Sprintf("%#v", obj)
|
||||
}
|
||||
|
||||
type wheel struct {
|
||||
radius uint32
|
||||
}
|
||||
|
||||
type unicycle struct {
|
||||
primaryWheel *wheel
|
||||
licencePlateID string
|
||||
tags map[string]string
|
||||
}
|
||||
|
||||
func TestDeepObjectPointer(t *testing.T) {
|
||||
// Arrange
|
||||
wheel1 := wheel{radius: 17}
|
||||
wheel2 := wheel{radius: 22}
|
||||
wheel3 := wheel{radius: 17}
|
||||
|
||||
myUni1 := unicycle{licencePlateID: "blah", primaryWheel: &wheel1, tags: map[string]string{"color": "blue", "name": "john"}}
|
||||
myUni2 := unicycle{licencePlateID: "blah", primaryWheel: &wheel2, tags: map[string]string{"color": "blue", "name": "john"}}
|
||||
myUni3 := unicycle{licencePlateID: "blah", primaryWheel: &wheel3, tags: map[string]string{"color": "blue", "name": "john"}}
|
||||
|
||||
// Run it more than once to verify determinism of hasher.
|
||||
for i := 0; i < 100; i++ {
|
||||
hasher1 := adler32.New()
|
||||
hasher2 := adler32.New()
|
||||
hasher3 := adler32.New()
|
||||
// Act
|
||||
DeepHashObject(hasher1, myUni1)
|
||||
hash1 := hasher1.Sum32()
|
||||
DeepHashObject(hasher1, myUni1)
|
||||
hash1a := hasher1.Sum32()
|
||||
DeepHashObject(hasher2, myUni2)
|
||||
hash2 := hasher2.Sum32()
|
||||
DeepHashObject(hasher3, myUni3)
|
||||
hash3 := hasher3.Sum32()
|
||||
|
||||
// Assert
|
||||
if hash1 != hash1a {
|
||||
t.Errorf("repeated hash of the same object produced different results: %d vs %d", hash1, hash1a)
|
||||
}
|
||||
|
||||
if hash1 == hash2 {
|
||||
t.Errorf("hash1 (%d) and hash2(%d) must be different because they have different values for wheel size", hash1, hash2)
|
||||
}
|
||||
|
||||
if hash1 != hash3 {
|
||||
t.Errorf("hash1 (%d) and hash3(%d) must be the same because although they point to different objects, they have the same values for wheel size", hash1, hash3)
|
||||
}
|
||||
}
|
||||
}
|
||||
1
vendor/k8s.io/kubernetes/pkg/util/mount/BUILD
generated
vendored
1
vendor/k8s.io/kubernetes/pkg/util/mount/BUILD
generated
vendored
|
|
@ -102,6 +102,7 @@ go_test(
|
|||
] + select({
|
||||
"@io_bazel_rules_go//go/platform:linux": [
|
||||
"//vendor/github.com/golang/glog:go_default_library",
|
||||
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||
],
|
||||
"@io_bazel_rules_go//go/platform:windows": [
|
||||
"//vendor/github.com/stretchr/testify/assert:go_default_library",
|
||||
|
|
|
|||
165
vendor/k8s.io/kubernetes/pkg/util/mount/exec_mount_test.go
generated
vendored
165
vendor/k8s.io/kubernetes/pkg/util/mount/exec_mount_test.go
generated
vendored
|
|
@ -1,165 +0,0 @@
|
|||
// +build linux
|
||||
|
||||
/*
|
||||
Copyright 2017 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 mount
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var (
|
||||
sourcePath = "/mnt/srv"
|
||||
destinationPath = "/mnt/dst"
|
||||
fsType = "xfs"
|
||||
mountOptions = []string{"vers=1", "foo=bar"}
|
||||
)
|
||||
|
||||
func TestMount(t *testing.T) {
|
||||
exec := NewFakeExec(func(cmd string, args ...string) ([]byte, error) {
|
||||
if cmd != "mount" {
|
||||
t.Errorf("expected mount command, got %q", cmd)
|
||||
}
|
||||
// mount -t fstype -o options source target
|
||||
expectedArgs := []string{"-t", fsType, "-o", strings.Join(mountOptions, ","), sourcePath, destinationPath}
|
||||
if !reflect.DeepEqual(expectedArgs, args) {
|
||||
t.Errorf("expected arguments %q, got %q", strings.Join(expectedArgs, " "), strings.Join(args, " "))
|
||||
}
|
||||
return nil, nil
|
||||
})
|
||||
|
||||
wrappedMounter := &fakeMounter{t}
|
||||
mounter := NewExecMounter(exec, wrappedMounter)
|
||||
|
||||
mounter.Mount(sourcePath, destinationPath, fsType, mountOptions)
|
||||
}
|
||||
|
||||
func TestBindMount(t *testing.T) {
|
||||
cmdCount := 0
|
||||
exec := NewFakeExec(func(cmd string, args ...string) ([]byte, error) {
|
||||
cmdCount++
|
||||
if cmd != "mount" {
|
||||
t.Errorf("expected mount command, got %q", cmd)
|
||||
}
|
||||
var expectedArgs []string
|
||||
switch cmdCount {
|
||||
case 1:
|
||||
// mount -t fstype -o "bind" source target
|
||||
expectedArgs = []string{"-t", fsType, "-o", "bind", sourcePath, destinationPath}
|
||||
case 2:
|
||||
// mount -t fstype -o "remount,opts" source target
|
||||
expectedArgs = []string{"-t", fsType, "-o", "remount," + strings.Join(mountOptions, ","), sourcePath, destinationPath}
|
||||
}
|
||||
if !reflect.DeepEqual(expectedArgs, args) {
|
||||
t.Errorf("expected arguments %q, got %q", strings.Join(expectedArgs, " "), strings.Join(args, " "))
|
||||
}
|
||||
return nil, nil
|
||||
})
|
||||
|
||||
wrappedMounter := &fakeMounter{t}
|
||||
mounter := NewExecMounter(exec, wrappedMounter)
|
||||
bindOptions := append(mountOptions, "bind")
|
||||
mounter.Mount(sourcePath, destinationPath, fsType, bindOptions)
|
||||
}
|
||||
|
||||
func TestUnmount(t *testing.T) {
|
||||
exec := NewFakeExec(func(cmd string, args ...string) ([]byte, error) {
|
||||
if cmd != "umount" {
|
||||
t.Errorf("expected unmount command, got %q", cmd)
|
||||
}
|
||||
// unmount $target
|
||||
expectedArgs := []string{destinationPath}
|
||||
if !reflect.DeepEqual(expectedArgs, args) {
|
||||
t.Errorf("expected arguments %q, got %q", strings.Join(expectedArgs, " "), strings.Join(args, " "))
|
||||
}
|
||||
return nil, nil
|
||||
})
|
||||
|
||||
wrappedMounter := &fakeMounter{t}
|
||||
mounter := NewExecMounter(exec, wrappedMounter)
|
||||
|
||||
mounter.Unmount(destinationPath)
|
||||
}
|
||||
|
||||
/* Fake wrapped mounter */
|
||||
type fakeMounter struct {
|
||||
t *testing.T
|
||||
}
|
||||
|
||||
func (fm *fakeMounter) Mount(source string, target string, fstype string, options []string) error {
|
||||
// Mount() of wrapped mounter should never be called. We call exec instead.
|
||||
fm.t.Errorf("Unexpected wrapped mount call")
|
||||
return fmt.Errorf("Unexpected wrapped mount call")
|
||||
}
|
||||
|
||||
func (fm *fakeMounter) Unmount(target string) error {
|
||||
// umount() of wrapped mounter should never be called. We call exec instead.
|
||||
fm.t.Errorf("Unexpected wrapped mount call")
|
||||
return fmt.Errorf("Unexpected wrapped mount call")
|
||||
}
|
||||
|
||||
func (fm *fakeMounter) List() ([]MountPoint, error) {
|
||||
return nil, nil
|
||||
}
|
||||
func (fm *fakeMounter) IsMountPointMatch(mp MountPoint, dir string) bool {
|
||||
return false
|
||||
}
|
||||
func (fm *fakeMounter) IsNotMountPoint(file string) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
func (fm *fakeMounter) IsLikelyNotMountPoint(file string) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
func (fm *fakeMounter) DeviceOpened(pathname string) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
func (fm *fakeMounter) PathIsDevice(pathname string) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
func (fm *fakeMounter) GetDeviceNameFromMount(mountPath, pluginDir string) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
func (fm *fakeMounter) MakeRShared(path string) error {
|
||||
return nil
|
||||
}
|
||||
func (fm *fakeMounter) MakeFile(pathname string) error {
|
||||
return nil
|
||||
}
|
||||
func (fm *fakeMounter) MakeDir(pathname string) error {
|
||||
return nil
|
||||
}
|
||||
func (fm *fakeMounter) ExistsPath(pathname string) bool {
|
||||
return false
|
||||
}
|
||||
func (fm *fakeMounter) GetFileType(pathname string) (FileType, error) {
|
||||
return FileTypeFile, nil
|
||||
}
|
||||
func (fm *fakeMounter) PrepareSafeSubpath(subPath Subpath) (newHostPath string, cleanupAction func(), err error) {
|
||||
return subPath.Path, nil, nil
|
||||
}
|
||||
|
||||
func (fm *fakeMounter) CleanSubPaths(podDir string, volumeName string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (fm *fakeMounter) SafeMakeDir(pathname string, base string, perm os.FileMode) error {
|
||||
return nil
|
||||
}
|
||||
12
vendor/k8s.io/kubernetes/pkg/util/mount/fake.go
generated
vendored
12
vendor/k8s.io/kubernetes/pkg/util/mount/fake.go
generated
vendored
|
|
@ -58,8 +58,10 @@ func (f *FakeMounter) Mount(source string, target string, fstype string, options
|
|||
f.mutex.Lock()
|
||||
defer f.mutex.Unlock()
|
||||
|
||||
// find 'bind' option
|
||||
opts := []string{}
|
||||
|
||||
for _, option := range options {
|
||||
// find 'bind' option
|
||||
if option == "bind" {
|
||||
// This is a bind-mount. In order to mimic linux behaviour, we must
|
||||
// use the original device of the bind-mount as the real source.
|
||||
|
|
@ -78,7 +80,11 @@ func (f *FakeMounter) Mount(source string, target string, fstype string, options
|
|||
break
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
// find 'ro' option
|
||||
if option == "ro" {
|
||||
// reuse MountPoint.Opts field to mark mount as readonly
|
||||
opts = append(opts, "ro")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -88,7 +94,7 @@ func (f *FakeMounter) Mount(source string, target string, fstype string, options
|
|||
absTarget = target
|
||||
}
|
||||
|
||||
f.MountPoints = append(f.MountPoints, MountPoint{Device: source, Path: absTarget, Type: fstype})
|
||||
f.MountPoints = append(f.MountPoints, MountPoint{Device: source, Path: absTarget, Type: fstype, Opts: opts})
|
||||
glog.V(5).Infof("Fake mounter: mounted %s to %s", source, absTarget)
|
||||
f.Log = append(f.Log, FakeAction{Action: FakeActionMount, Target: absTarget, Source: source, FSType: fstype})
|
||||
return nil
|
||||
|
|
|
|||
45
vendor/k8s.io/kubernetes/pkg/util/mount/mount.go
generated
vendored
45
vendor/k8s.io/kubernetes/pkg/util/mount/mount.go
generated
vendored
|
|
@ -19,6 +19,7 @@ limitations under the License.
|
|||
package mount
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
|
@ -123,6 +124,8 @@ type Subpath struct {
|
|||
PodDir string
|
||||
// Name of the container
|
||||
ContainerName string
|
||||
// True if the mount needs to be readonly
|
||||
ReadOnly bool
|
||||
}
|
||||
|
||||
// Exec executes command where mount utilities are. This can be either the host,
|
||||
|
|
@ -281,7 +284,13 @@ func IsNotMountPoint(mounter Interface, file string) (bool, error) {
|
|||
// The list equals:
|
||||
// options - 'bind' + 'remount' (no duplicate)
|
||||
func isBind(options []string) (bool, []string) {
|
||||
bindRemountOpts := []string{"remount"}
|
||||
// Because we have an FD opened on the subpath bind mount, the "bind" option
|
||||
// needs to be included, otherwise the mount target will error as busy if you
|
||||
// remount as readonly.
|
||||
//
|
||||
// As a consequence, all read only bind mounts will no longer change the underlying
|
||||
// volume mount to be read only.
|
||||
bindRemountOpts := []string{"bind", "remount"}
|
||||
bind := false
|
||||
|
||||
if len(options) != 0 {
|
||||
|
|
@ -337,3 +346,37 @@ func startsWithBackstep(rel string) bool {
|
|||
// normalize to / and check for ../
|
||||
return rel == ".." || strings.HasPrefix(filepath.ToSlash(rel), "../")
|
||||
}
|
||||
|
||||
// getFileType checks for file/directory/socket and block/character devices
|
||||
func getFileType(pathname string) (FileType, error) {
|
||||
var pathType FileType
|
||||
info, err := os.Stat(pathname)
|
||||
if os.IsNotExist(err) {
|
||||
return pathType, fmt.Errorf("path %q does not exist", pathname)
|
||||
}
|
||||
// err in call to os.Stat
|
||||
if err != nil {
|
||||
return pathType, err
|
||||
}
|
||||
|
||||
// checks whether the mode is the target mode
|
||||
isSpecificMode := func(mode, targetMode os.FileMode) bool {
|
||||
return mode&targetMode == targetMode
|
||||
}
|
||||
|
||||
mode := info.Mode()
|
||||
if mode.IsDir() {
|
||||
return FileTypeDirectory, nil
|
||||
} else if mode.IsRegular() {
|
||||
return FileTypeFile, nil
|
||||
} else if isSpecificMode(mode, os.ModeSocket) {
|
||||
return FileTypeSocket, nil
|
||||
} else if isSpecificMode(mode, os.ModeDevice) {
|
||||
if isSpecificMode(mode, os.ModeCharDevice) {
|
||||
return FileTypeCharDev, nil
|
||||
}
|
||||
return FileTypeBlockDev, nil
|
||||
}
|
||||
|
||||
return pathType, fmt.Errorf("only recognise file, directory, socket, block device and character device")
|
||||
}
|
||||
|
|
|
|||
33
vendor/k8s.io/kubernetes/pkg/util/mount/mount_linux.go
generated
vendored
33
vendor/k8s.io/kubernetes/pkg/util/mount/mount_linux.go
generated
vendored
|
|
@ -423,31 +423,7 @@ func (mounter *Mounter) MakeRShared(path string) error {
|
|||
}
|
||||
|
||||
func (mounter *Mounter) GetFileType(pathname string) (FileType, error) {
|
||||
var pathType FileType
|
||||
finfo, err := os.Stat(pathname)
|
||||
if os.IsNotExist(err) {
|
||||
return pathType, fmt.Errorf("path %q does not exist", pathname)
|
||||
}
|
||||
// err in call to os.Stat
|
||||
if err != nil {
|
||||
return pathType, err
|
||||
}
|
||||
|
||||
mode := finfo.Sys().(*syscall.Stat_t).Mode
|
||||
switch mode & syscall.S_IFMT {
|
||||
case syscall.S_IFSOCK:
|
||||
return FileTypeSocket, nil
|
||||
case syscall.S_IFBLK:
|
||||
return FileTypeBlockDev, nil
|
||||
case syscall.S_IFCHR:
|
||||
return FileTypeCharDev, nil
|
||||
case syscall.S_IFDIR:
|
||||
return FileTypeDirectory, nil
|
||||
case syscall.S_IFREG:
|
||||
return FileTypeFile, nil
|
||||
}
|
||||
|
||||
return pathType, fmt.Errorf("only recognise file, directory, socket, block device and character device")
|
||||
return getFileType(pathname)
|
||||
}
|
||||
|
||||
func (mounter *Mounter) MakeDir(pathname string) error {
|
||||
|
|
@ -801,8 +777,13 @@ func doBindSubPath(mounter Interface, subpath Subpath, kubeletPid int) (hostPath
|
|||
mountSource := fmt.Sprintf("/proc/%d/fd/%v", kubeletPid, fd)
|
||||
|
||||
// Do the bind mount
|
||||
options := []string{"bind"}
|
||||
if subpath.ReadOnly {
|
||||
options = append(options, "ro")
|
||||
}
|
||||
|
||||
glog.V(5).Infof("bind mounting %q at %q", mountSource, bindPathTarget)
|
||||
if err = mounter.Mount(mountSource, bindPathTarget, "" /*fstype*/, []string{"bind"}); err != nil {
|
||||
if err = mounter.Mount(mountSource, bindPathTarget, "" /*fstype*/, options); err != nil {
|
||||
return "", fmt.Errorf("error mounting %s: %s", subpath.Path, err)
|
||||
}
|
||||
|
||||
|
|
|
|||
1661
vendor/k8s.io/kubernetes/pkg/util/mount/mount_linux_test.go
generated
vendored
1661
vendor/k8s.io/kubernetes/pkg/util/mount/mount_linux_test.go
generated
vendored
File diff suppressed because it is too large
Load diff
26
vendor/k8s.io/kubernetes/pkg/util/mount/mount_windows.go
generated
vendored
26
vendor/k8s.io/kubernetes/pkg/util/mount/mount_windows.go
generated
vendored
|
|
@ -201,31 +201,7 @@ func (mounter *Mounter) MakeRShared(path string) error {
|
|||
|
||||
// GetFileType checks for sockets/block/character devices
|
||||
func (mounter *Mounter) GetFileType(pathname string) (FileType, error) {
|
||||
var pathType FileType
|
||||
info, err := os.Stat(pathname)
|
||||
if os.IsNotExist(err) {
|
||||
return pathType, fmt.Errorf("path %q does not exist", pathname)
|
||||
}
|
||||
// err in call to os.Stat
|
||||
if err != nil {
|
||||
return pathType, err
|
||||
}
|
||||
|
||||
mode := info.Sys().(*syscall.Win32FileAttributeData).FileAttributes
|
||||
switch mode & syscall.S_IFMT {
|
||||
case syscall.S_IFSOCK:
|
||||
return FileTypeSocket, nil
|
||||
case syscall.S_IFBLK:
|
||||
return FileTypeBlockDev, nil
|
||||
case syscall.S_IFCHR:
|
||||
return FileTypeCharDev, nil
|
||||
case syscall.S_IFDIR:
|
||||
return FileTypeDirectory, nil
|
||||
case syscall.S_IFREG:
|
||||
return FileTypeFile, nil
|
||||
}
|
||||
|
||||
return pathType, fmt.Errorf("only recognise file, directory, socket, block device and character device")
|
||||
return getFileType(pathname)
|
||||
}
|
||||
|
||||
// MakeFile creates a new directory
|
||||
|
|
|
|||
553
vendor/k8s.io/kubernetes/pkg/util/mount/mount_windows_test.go
generated
vendored
553
vendor/k8s.io/kubernetes/pkg/util/mount/mount_windows_test.go
generated
vendored
|
|
@ -1,553 +0,0 @@
|
|||
// +build windows
|
||||
|
||||
/*
|
||||
Copyright 2017 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 mount
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestNormalizeWindowsPath(t *testing.T) {
|
||||
path := `/var/lib/kubelet/pods/146f8428-83e7-11e7-8dd4-000d3a31dac4/volumes/kubernetes.io~azure-disk`
|
||||
normalizedPath := normalizeWindowsPath(path)
|
||||
if normalizedPath != `c:\var\lib\kubelet\pods\146f8428-83e7-11e7-8dd4-000d3a31dac4\volumes\kubernetes.io~azure-disk` {
|
||||
t.Errorf("normizeWindowsPath test failed, normalizedPath : %q", normalizedPath)
|
||||
}
|
||||
|
||||
path = `/var/lib/kubelet/pods/146f8428-83e7-11e7-8dd4-000d3a31dac4\volumes\kubernetes.io~azure-disk`
|
||||
normalizedPath = normalizeWindowsPath(path)
|
||||
if normalizedPath != `c:\var\lib\kubelet\pods\146f8428-83e7-11e7-8dd4-000d3a31dac4\volumes\kubernetes.io~azure-disk` {
|
||||
t.Errorf("normizeWindowsPath test failed, normalizedPath : %q", normalizedPath)
|
||||
}
|
||||
|
||||
path = `/`
|
||||
normalizedPath = normalizeWindowsPath(path)
|
||||
if normalizedPath != `c:\` {
|
||||
t.Errorf("normizeWindowsPath test failed, normalizedPath : %q", normalizedPath)
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateDiskNumber(t *testing.T) {
|
||||
diskNum := "0"
|
||||
if err := ValidateDiskNumber(diskNum); err != nil {
|
||||
t.Errorf("TestValidateDiskNumber test failed, disk number : %s", diskNum)
|
||||
}
|
||||
|
||||
diskNum = "99"
|
||||
if err := ValidateDiskNumber(diskNum); err != nil {
|
||||
t.Errorf("TestValidateDiskNumber test failed, disk number : %s", diskNum)
|
||||
}
|
||||
|
||||
diskNum = "ab"
|
||||
if err := ValidateDiskNumber(diskNum); err == nil {
|
||||
t.Errorf("TestValidateDiskNumber test failed, disk number : %s", diskNum)
|
||||
}
|
||||
|
||||
diskNum = "100"
|
||||
if err := ValidateDiskNumber(diskNum); err == nil {
|
||||
t.Errorf("TestValidateDiskNumber test failed, disk number : %s", diskNum)
|
||||
}
|
||||
}
|
||||
|
||||
func makeLink(link, target string) error {
|
||||
if output, err := exec.Command("cmd", "/c", "mklink", "/D", link, target).CombinedOutput(); err != nil {
|
||||
return fmt.Errorf("mklink failed: %v, link(%q) target(%q) output: %q", err, link, target, string(output))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func removeLink(link string) error {
|
||||
if output, err := exec.Command("cmd", "/c", "rmdir", link).CombinedOutput(); err != nil {
|
||||
return fmt.Errorf("rmdir failed: %v, output: %q", err, string(output))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func setEquivalent(set1, set2 []string) bool {
|
||||
map1 := make(map[string]bool)
|
||||
map2 := make(map[string]bool)
|
||||
for _, s := range set1 {
|
||||
map1[s] = true
|
||||
}
|
||||
for _, s := range set2 {
|
||||
map2[s] = true
|
||||
}
|
||||
|
||||
for s := range map1 {
|
||||
if !map2[s] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
for s := range map2 {
|
||||
if !map1[s] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// this func must run in admin mode, otherwise it will fail
|
||||
func TestGetMountRefs(t *testing.T) {
|
||||
fm := &FakeMounter{MountPoints: []MountPoint{}}
|
||||
mountPath := `c:\secondmountpath`
|
||||
expectedRefs := []string{`c:\`, `c:\firstmountpath`, mountPath}
|
||||
|
||||
// remove symbolic links first
|
||||
for i := 1; i < len(expectedRefs); i++ {
|
||||
removeLink(expectedRefs[i])
|
||||
}
|
||||
|
||||
// create symbolic links
|
||||
for i := 1; i < len(expectedRefs); i++ {
|
||||
if err := makeLink(expectedRefs[i], expectedRefs[i-1]); err != nil {
|
||||
t.Errorf("makeLink failed: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
if refs, err := GetMountRefs(fm, mountPath); err != nil || !setEquivalent(expectedRefs, refs) {
|
||||
t.Errorf("getMountRefs(%q) = %v, error: %v; expected %v", mountPath, refs, err, expectedRefs)
|
||||
}
|
||||
|
||||
// remove symbolic links
|
||||
for i := 1; i < len(expectedRefs); i++ {
|
||||
if err := removeLink(expectedRefs[i]); err != nil {
|
||||
t.Errorf("removeLink failed: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDoSafeMakeDir(t *testing.T) {
|
||||
const testingVolumePath = `c:\tmp\DoSafeMakeDirTest`
|
||||
os.MkdirAll(testingVolumePath, 0755)
|
||||
defer os.RemoveAll(testingVolumePath)
|
||||
|
||||
tests := []struct {
|
||||
volumePath string
|
||||
subPath string
|
||||
expectError bool
|
||||
symlinkTarget string
|
||||
}{
|
||||
{
|
||||
volumePath: testingVolumePath,
|
||||
subPath: ``,
|
||||
expectError: true,
|
||||
symlinkTarget: "",
|
||||
},
|
||||
{
|
||||
volumePath: testingVolumePath,
|
||||
subPath: filepath.Join(testingVolumePath, `x`),
|
||||
expectError: false,
|
||||
symlinkTarget: "",
|
||||
},
|
||||
{
|
||||
volumePath: testingVolumePath,
|
||||
subPath: filepath.Join(testingVolumePath, `a\b\c\d`),
|
||||
expectError: false,
|
||||
symlinkTarget: "",
|
||||
},
|
||||
{
|
||||
volumePath: testingVolumePath,
|
||||
subPath: filepath.Join(testingVolumePath, `symlink`),
|
||||
expectError: false,
|
||||
symlinkTarget: `c:\tmp`,
|
||||
},
|
||||
{
|
||||
volumePath: testingVolumePath,
|
||||
subPath: filepath.Join(testingVolumePath, `symlink\c\d`),
|
||||
expectError: true,
|
||||
symlinkTarget: "",
|
||||
},
|
||||
{
|
||||
volumePath: testingVolumePath,
|
||||
subPath: filepath.Join(testingVolumePath, `symlink\y926`),
|
||||
expectError: true,
|
||||
symlinkTarget: "",
|
||||
},
|
||||
{
|
||||
volumePath: testingVolumePath,
|
||||
subPath: filepath.Join(testingVolumePath, `a\b\symlink`),
|
||||
expectError: false,
|
||||
symlinkTarget: `c:\tmp`,
|
||||
},
|
||||
{
|
||||
volumePath: testingVolumePath,
|
||||
subPath: filepath.Join(testingVolumePath, `a\x\symlink`),
|
||||
expectError: false,
|
||||
symlinkTarget: filepath.Join(testingVolumePath, `a`),
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
if len(test.volumePath) > 0 && len(test.subPath) > 0 && len(test.symlinkTarget) > 0 {
|
||||
// make all parent sub directories
|
||||
if parent := filepath.Dir(test.subPath); parent != "." {
|
||||
os.MkdirAll(parent, 0755)
|
||||
}
|
||||
|
||||
// make last element as symlink
|
||||
linkPath := test.subPath
|
||||
if _, err := os.Stat(linkPath); err != nil && os.IsNotExist(err) {
|
||||
if err := makeLink(linkPath, test.symlinkTarget); err != nil {
|
||||
t.Fatalf("unexpected error: %v", fmt.Errorf("mklink link(%q) target(%q) error: %q", linkPath, test.symlinkTarget, err))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
err := doSafeMakeDir(test.subPath, test.volumePath, os.FileMode(0755))
|
||||
if test.expectError {
|
||||
assert.NotNil(t, err, "Expect error during doSafeMakeDir(%s, %s)", test.subPath, test.volumePath)
|
||||
continue
|
||||
}
|
||||
assert.Nil(t, err, "Expect no error during doSafeMakeDir(%s, %s)", test.subPath, test.volumePath)
|
||||
if _, err := os.Stat(test.subPath); os.IsNotExist(err) {
|
||||
t.Errorf("subPath should exists after doSafeMakeDir(%s, %s)", test.subPath, test.volumePath)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestLockAndCheckSubPath(t *testing.T) {
|
||||
const testingVolumePath = `c:\tmp\LockAndCheckSubPathTest`
|
||||
|
||||
tests := []struct {
|
||||
volumePath string
|
||||
subPath string
|
||||
expectedHandleCount int
|
||||
expectError bool
|
||||
symlinkTarget string
|
||||
}{
|
||||
{
|
||||
volumePath: `c:\`,
|
||||
subPath: ``,
|
||||
expectedHandleCount: 0,
|
||||
expectError: false,
|
||||
symlinkTarget: "",
|
||||
},
|
||||
{
|
||||
volumePath: ``,
|
||||
subPath: `a`,
|
||||
expectedHandleCount: 0,
|
||||
expectError: false,
|
||||
symlinkTarget: "",
|
||||
},
|
||||
{
|
||||
volumePath: testingVolumePath,
|
||||
subPath: filepath.Join(testingVolumePath, `a`),
|
||||
expectedHandleCount: 1,
|
||||
expectError: false,
|
||||
symlinkTarget: "",
|
||||
},
|
||||
{
|
||||
volumePath: testingVolumePath,
|
||||
subPath: filepath.Join(testingVolumePath, `a\b\c\d`),
|
||||
expectedHandleCount: 4,
|
||||
expectError: false,
|
||||
symlinkTarget: "",
|
||||
},
|
||||
{
|
||||
volumePath: testingVolumePath,
|
||||
subPath: filepath.Join(testingVolumePath, `symlink`),
|
||||
expectedHandleCount: 0,
|
||||
expectError: true,
|
||||
symlinkTarget: `c:\tmp`,
|
||||
},
|
||||
{
|
||||
volumePath: testingVolumePath,
|
||||
subPath: filepath.Join(testingVolumePath, `a\b\c\symlink`),
|
||||
expectedHandleCount: 0,
|
||||
expectError: true,
|
||||
symlinkTarget: `c:\tmp`,
|
||||
},
|
||||
{
|
||||
volumePath: testingVolumePath,
|
||||
subPath: filepath.Join(testingVolumePath, `a\b\c\d\symlink`),
|
||||
expectedHandleCount: 2,
|
||||
expectError: false,
|
||||
symlinkTarget: filepath.Join(testingVolumePath, `a\b`),
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
if len(test.volumePath) > 0 && len(test.subPath) > 0 {
|
||||
os.MkdirAll(test.volumePath, 0755)
|
||||
if len(test.symlinkTarget) == 0 {
|
||||
// make all intermediate sub directories
|
||||
os.MkdirAll(test.subPath, 0755)
|
||||
} else {
|
||||
// make all parent sub directories
|
||||
if parent := filepath.Dir(test.subPath); parent != "." {
|
||||
os.MkdirAll(parent, 0755)
|
||||
}
|
||||
|
||||
// make last element as symlink
|
||||
linkPath := test.subPath
|
||||
if _, err := os.Stat(linkPath); err != nil && os.IsNotExist(err) {
|
||||
if err := makeLink(linkPath, test.symlinkTarget); err != nil {
|
||||
t.Fatalf("unexpected error: %v", fmt.Errorf("mklink link(%q) target(%q) error: %q", linkPath, test.symlinkTarget, err))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fileHandles, err := lockAndCheckSubPath(test.volumePath, test.subPath)
|
||||
unlockPath(fileHandles)
|
||||
assert.Equal(t, test.expectedHandleCount, len(fileHandles))
|
||||
if test.expectError {
|
||||
assert.NotNil(t, err, "Expect error during LockAndCheckSubPath(%s, %s)", test.volumePath, test.subPath)
|
||||
continue
|
||||
}
|
||||
assert.Nil(t, err, "Expect no error during LockAndCheckSubPath(%s, %s)", test.volumePath, test.subPath)
|
||||
}
|
||||
|
||||
// remove dir will happen after closing all file handles
|
||||
assert.Nil(t, os.RemoveAll(testingVolumePath), "Expect no error during remove dir %s", testingVolumePath)
|
||||
}
|
||||
|
||||
func TestLockAndCheckSubPathWithoutSymlink(t *testing.T) {
|
||||
const testingVolumePath = `c:\tmp\LockAndCheckSubPathWithoutSymlinkTest`
|
||||
|
||||
tests := []struct {
|
||||
volumePath string
|
||||
subPath string
|
||||
expectedHandleCount int
|
||||
expectError bool
|
||||
symlinkTarget string
|
||||
}{
|
||||
{
|
||||
volumePath: `c:\`,
|
||||
subPath: ``,
|
||||
expectedHandleCount: 0,
|
||||
expectError: false,
|
||||
symlinkTarget: "",
|
||||
},
|
||||
{
|
||||
volumePath: ``,
|
||||
subPath: `a`,
|
||||
expectedHandleCount: 0,
|
||||
expectError: false,
|
||||
symlinkTarget: "",
|
||||
},
|
||||
{
|
||||
volumePath: testingVolumePath,
|
||||
subPath: filepath.Join(testingVolumePath, `a`),
|
||||
expectedHandleCount: 1,
|
||||
expectError: false,
|
||||
symlinkTarget: "",
|
||||
},
|
||||
{
|
||||
volumePath: testingVolumePath,
|
||||
subPath: filepath.Join(testingVolumePath, `a\b\c\d`),
|
||||
expectedHandleCount: 4,
|
||||
expectError: false,
|
||||
symlinkTarget: "",
|
||||
},
|
||||
{
|
||||
volumePath: testingVolumePath,
|
||||
subPath: filepath.Join(testingVolumePath, `symlink`),
|
||||
expectedHandleCount: 1,
|
||||
expectError: true,
|
||||
symlinkTarget: `c:\tmp`,
|
||||
},
|
||||
{
|
||||
volumePath: testingVolumePath,
|
||||
subPath: filepath.Join(testingVolumePath, `a\b\c\symlink`),
|
||||
expectedHandleCount: 4,
|
||||
expectError: true,
|
||||
symlinkTarget: `c:\tmp`,
|
||||
},
|
||||
{
|
||||
volumePath: testingVolumePath,
|
||||
subPath: filepath.Join(testingVolumePath, `a\b\c\d\symlink`),
|
||||
expectedHandleCount: 5,
|
||||
expectError: true,
|
||||
symlinkTarget: filepath.Join(testingVolumePath, `a\b`),
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
if len(test.volumePath) > 0 && len(test.subPath) > 0 {
|
||||
os.MkdirAll(test.volumePath, 0755)
|
||||
if len(test.symlinkTarget) == 0 {
|
||||
// make all intermediate sub directories
|
||||
os.MkdirAll(test.subPath, 0755)
|
||||
} else {
|
||||
// make all parent sub directories
|
||||
if parent := filepath.Dir(test.subPath); parent != "." {
|
||||
os.MkdirAll(parent, 0755)
|
||||
}
|
||||
|
||||
// make last element as symlink
|
||||
linkPath := test.subPath
|
||||
if _, err := os.Stat(linkPath); err != nil && os.IsNotExist(err) {
|
||||
if err := makeLink(linkPath, test.symlinkTarget); err != nil {
|
||||
t.Fatalf("unexpected error: %v", fmt.Errorf("mklink link(%q) target(%q) error: %q", linkPath, test.symlinkTarget, err))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fileHandles, err := lockAndCheckSubPathWithoutSymlink(test.volumePath, test.subPath)
|
||||
unlockPath(fileHandles)
|
||||
assert.Equal(t, test.expectedHandleCount, len(fileHandles))
|
||||
if test.expectError {
|
||||
assert.NotNil(t, err, "Expect error during LockAndCheckSubPath(%s, %s)", test.volumePath, test.subPath)
|
||||
continue
|
||||
}
|
||||
assert.Nil(t, err, "Expect no error during LockAndCheckSubPath(%s, %s)", test.volumePath, test.subPath)
|
||||
}
|
||||
|
||||
// remove dir will happen after closing all file handles
|
||||
assert.Nil(t, os.RemoveAll(testingVolumePath), "Expect no error during remove dir %s", testingVolumePath)
|
||||
}
|
||||
|
||||
func TestFindExistingPrefix(t *testing.T) {
|
||||
const testingVolumePath = `c:\tmp\FindExistingPrefixTest`
|
||||
|
||||
tests := []struct {
|
||||
base string
|
||||
pathname string
|
||||
expectError bool
|
||||
expectedExistingPath string
|
||||
expectedToCreateDirs []string
|
||||
createSubPathBeforeTest bool
|
||||
}{
|
||||
{
|
||||
base: `c:\tmp\a`,
|
||||
pathname: `c:\tmp\b`,
|
||||
expectError: true,
|
||||
expectedExistingPath: "",
|
||||
expectedToCreateDirs: []string{},
|
||||
createSubPathBeforeTest: false,
|
||||
},
|
||||
{
|
||||
base: ``,
|
||||
pathname: `c:\tmp\b`,
|
||||
expectError: true,
|
||||
expectedExistingPath: "",
|
||||
expectedToCreateDirs: []string{},
|
||||
createSubPathBeforeTest: false,
|
||||
},
|
||||
{
|
||||
base: `c:\tmp\a`,
|
||||
pathname: `d:\tmp\b`,
|
||||
expectError: true,
|
||||
expectedExistingPath: "",
|
||||
expectedToCreateDirs: []string{},
|
||||
createSubPathBeforeTest: false,
|
||||
},
|
||||
{
|
||||
base: testingVolumePath,
|
||||
pathname: testingVolumePath,
|
||||
expectError: false,
|
||||
expectedExistingPath: testingVolumePath,
|
||||
expectedToCreateDirs: []string{},
|
||||
createSubPathBeforeTest: false,
|
||||
},
|
||||
{
|
||||
base: testingVolumePath,
|
||||
pathname: filepath.Join(testingVolumePath, `a\b`),
|
||||
expectError: false,
|
||||
expectedExistingPath: filepath.Join(testingVolumePath, `a\b`),
|
||||
expectedToCreateDirs: []string{},
|
||||
createSubPathBeforeTest: true,
|
||||
},
|
||||
{
|
||||
base: testingVolumePath,
|
||||
pathname: filepath.Join(testingVolumePath, `a\b\c\`),
|
||||
expectError: false,
|
||||
expectedExistingPath: filepath.Join(testingVolumePath, `a\b`),
|
||||
expectedToCreateDirs: []string{`c`},
|
||||
createSubPathBeforeTest: false,
|
||||
},
|
||||
{
|
||||
base: testingVolumePath,
|
||||
pathname: filepath.Join(testingVolumePath, `a\b\c\d`),
|
||||
expectError: false,
|
||||
expectedExistingPath: filepath.Join(testingVolumePath, `a\b`),
|
||||
expectedToCreateDirs: []string{`c`, `d`},
|
||||
createSubPathBeforeTest: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
if test.createSubPathBeforeTest {
|
||||
os.MkdirAll(test.pathname, 0755)
|
||||
}
|
||||
|
||||
existingPath, toCreate, err := findExistingPrefix(test.base, test.pathname)
|
||||
if test.expectError {
|
||||
assert.NotNil(t, err, "Expect error during findExistingPrefix(%s, %s)", test.base, test.pathname)
|
||||
continue
|
||||
}
|
||||
assert.Nil(t, err, "Expect no error during findExistingPrefix(%s, %s)", test.base, test.pathname)
|
||||
|
||||
assert.Equal(t, test.expectedExistingPath, existingPath, "Expect result not equal with findExistingPrefix(%s, %s) return: %q, expected: %q",
|
||||
test.base, test.pathname, existingPath, test.expectedExistingPath)
|
||||
|
||||
assert.Equal(t, test.expectedToCreateDirs, toCreate, "Expect result not equal with findExistingPrefix(%s, %s) return: %q, expected: %q",
|
||||
test.base, test.pathname, toCreate, test.expectedToCreateDirs)
|
||||
|
||||
}
|
||||
// remove dir will happen after closing all file handles
|
||||
assert.Nil(t, os.RemoveAll(testingVolumePath), "Expect no error during remove dir %s", testingVolumePath)
|
||||
}
|
||||
|
||||
func TestPathWithinBase(t *testing.T) {
|
||||
tests := []struct {
|
||||
fullPath string
|
||||
basePath string
|
||||
expectedResult bool
|
||||
}{
|
||||
{
|
||||
fullPath: `c:\tmp\a\b\c`,
|
||||
basePath: `c:\tmp`,
|
||||
expectedResult: true,
|
||||
},
|
||||
{
|
||||
fullPath: `c:\tmp1`,
|
||||
basePath: `c:\tmp2`,
|
||||
expectedResult: false,
|
||||
},
|
||||
{
|
||||
fullPath: `c:\tmp`,
|
||||
basePath: `c:\tmp`,
|
||||
expectedResult: true,
|
||||
},
|
||||
{
|
||||
fullPath: `c:\tmp`,
|
||||
basePath: `c:\tmp\a\b\c`,
|
||||
expectedResult: false,
|
||||
},
|
||||
{
|
||||
fullPath: `c:\kubelet\pods\uuid\volumes\kubernetes.io~configmap\config\..timestamp\file.txt`,
|
||||
basePath: `c:\kubelet\pods\uuid\volumes\kubernetes.io~configmap\config`,
|
||||
expectedResult: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
result := pathWithinBase(test.fullPath, test.basePath)
|
||||
assert.Equal(t, result, test.expectedResult, "Expect result not equal with pathWithinBase(%s, %s) return: %q, expected: %q",
|
||||
test.fullPath, test.basePath, result, test.expectedResult)
|
||||
}
|
||||
}
|
||||
7
vendor/k8s.io/kubernetes/pkg/util/mount/nsenter_mount.go
generated
vendored
7
vendor/k8s.io/kubernetes/pkg/util/mount/nsenter_mount.go
generated
vendored
|
|
@ -235,8 +235,13 @@ func (n *NsenterMounter) MakeRShared(path string) error {
|
|||
|
||||
func (mounter *NsenterMounter) GetFileType(pathname string) (FileType, error) {
|
||||
var pathType FileType
|
||||
outputBytes, err := mounter.ne.Exec("stat", []string{"-L", `--printf "%F"`, pathname}).CombinedOutput()
|
||||
outputBytes, err := mounter.ne.Exec("stat", []string{"-L", "--printf=%F", pathname}).CombinedOutput()
|
||||
if err != nil {
|
||||
if strings.Contains(string(outputBytes), "No such file") {
|
||||
err = fmt.Errorf("%s does not exist", pathname)
|
||||
} else {
|
||||
err = fmt.Errorf("stat %s error: %v", pathname, string(outputBytes))
|
||||
}
|
||||
return pathType, err
|
||||
}
|
||||
|
||||
|
|
|
|||
191
vendor/k8s.io/kubernetes/pkg/util/mount/nsenter_mount_test.go
generated
vendored
191
vendor/k8s.io/kubernetes/pkg/util/mount/nsenter_mount_test.go
generated
vendored
|
|
@ -1,191 +0,0 @@
|
|||
// +build linux
|
||||
|
||||
/*
|
||||
Copyright 2017 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 mount
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"strconv"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestParseFindMnt(t *testing.T) {
|
||||
tests := []struct {
|
||||
input string
|
||||
target string
|
||||
expectError bool
|
||||
}{
|
||||
{
|
||||
// standard mount name, e.g. for AWS
|
||||
"/var/lib/kubelet/plugins/kubernetes.io/aws-ebs/mounts/aws/us-east-1d/vol-020f82b0759f72389 ext4\n",
|
||||
"/var/lib/kubelet/plugins/kubernetes.io/aws-ebs/mounts/aws/us-east-1d/vol-020f82b0759f72389",
|
||||
false,
|
||||
},
|
||||
{
|
||||
// mount name with space, e.g. vSphere
|
||||
"/var/lib/kubelet/plugins/kubernetes.io/vsphere-volume/mounts/[datastore1] kubevols/kubernetes-dynamic-pvc-4aacaa9b-6ba5-11e7-8f64-0050569f1b82.vmdk ext2\n",
|
||||
"/var/lib/kubelet/plugins/kubernetes.io/vsphere-volume/mounts/[datastore1] kubevols/kubernetes-dynamic-pvc-4aacaa9b-6ba5-11e7-8f64-0050569f1b82.vmdk",
|
||||
false,
|
||||
},
|
||||
{
|
||||
// hypotetic mount with several spaces
|
||||
"/var/lib/kubelet/plugins/kubernetes.io/vsphere-volume/mounts/[ d a t a s t o r e 1 ] kubevols/kubernetes-dynamic-pvc-4aacaa9b-6ba5-11e7-8f64-0050569f1b82.vmdk ext2\n",
|
||||
"/var/lib/kubelet/plugins/kubernetes.io/vsphere-volume/mounts/[ d a t a s t o r e 1 ] kubevols/kubernetes-dynamic-pvc-4aacaa9b-6ba5-11e7-8f64-0050569f1b82.vmdk",
|
||||
false,
|
||||
},
|
||||
{
|
||||
// invalid output - no filesystem type
|
||||
"/var/lib/kubelet/plugins/kubernetes.io/vsphere-volume/mounts/blabla",
|
||||
"",
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for i, test := range tests {
|
||||
target, err := parseFindMnt(test.input)
|
||||
if test.expectError && err == nil {
|
||||
t.Errorf("test %d expected error, got nil", i)
|
||||
}
|
||||
if !test.expectError && err != nil {
|
||||
t.Errorf("test %d returned error: %s", i, err)
|
||||
}
|
||||
if target != test.target {
|
||||
t.Errorf("test %d expected %q, got %q", i, test.target, target)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetPidOnHost(t *testing.T) {
|
||||
tempDir, err := ioutil.TempDir("", "get_pid_on_host_tests")
|
||||
if err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
}
|
||||
defer os.RemoveAll(tempDir)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
procFile string
|
||||
expectedPid int
|
||||
expectError bool
|
||||
}{
|
||||
{
|
||||
name: "valid status file",
|
||||
procFile: `Name: cat
|
||||
Umask: 0002
|
||||
State: R (running)
|
||||
Tgid: 15041
|
||||
Ngid: 0
|
||||
Pid: 15041
|
||||
PPid: 22699
|
||||
TracerPid: 0
|
||||
Uid: 1000 1000 1000 1000
|
||||
Gid: 1000 1000 1000 1000
|
||||
FDSize: 256
|
||||
Groups: 10 135 156 157 158 973 984 1000 1001
|
||||
NStgid: 15041
|
||||
NSpid: 15041
|
||||
NSpgid: 15041
|
||||
NSsid: 22699
|
||||
VmPeak: 115016 kB
|
||||
VmSize: 115016 kB
|
||||
VmLck: 0 kB
|
||||
VmPin: 0 kB
|
||||
VmHWM: 816 kB
|
||||
VmRSS: 816 kB
|
||||
RssAnon: 64 kB
|
||||
RssFile: 752 kB
|
||||
RssShmem: 0 kB
|
||||
VmData: 312 kB
|
||||
VmStk: 136 kB
|
||||
VmExe: 32 kB
|
||||
VmLib: 2060 kB
|
||||
VmPTE: 44 kB
|
||||
VmPMD: 12 kB
|
||||
VmSwap: 0 kB
|
||||
HugetlbPages: 0 kB
|
||||
Threads: 1
|
||||
SigQ: 2/60752
|
||||
SigPnd: 0000000000000000
|
||||
ShdPnd: 0000000000000000
|
||||
SigBlk: 0000000000000000
|
||||
SigIgn: 0000000000000000
|
||||
SigCgt: 0000000000000000
|
||||
CapInh: 0000000000000000
|
||||
CapPrm: 0000000000000000
|
||||
CapEff: 0000000000000000
|
||||
CapBnd: 0000003fffffffff
|
||||
CapAmb: 0000000000000000
|
||||
NoNewPrivs: 0
|
||||
Seccomp: 0
|
||||
Cpus_allowed: ff
|
||||
Cpus_allowed_list: 0-7
|
||||
Mems_allowed: 00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000001
|
||||
Mems_allowed_list: 0
|
||||
voluntary_ctxt_switches: 0
|
||||
nonvoluntary_ctxt_switches: 0
|
||||
`,
|
||||
expectedPid: 15041,
|
||||
},
|
||||
{
|
||||
name: "no Pid:",
|
||||
procFile: `Name: cat
|
||||
Umask: 0002
|
||||
State: R (running)
|
||||
Tgid: 15041
|
||||
Ngid: 0
|
||||
PPid: 22699
|
||||
`,
|
||||
expectedPid: 0,
|
||||
expectError: true,
|
||||
},
|
||||
{
|
||||
name: "invalid Pid:",
|
||||
procFile: `Name: cat
|
||||
Umask: 0002
|
||||
State: R (running)
|
||||
Tgid: 15041
|
||||
Ngid: 0
|
||||
Pid: invalid
|
||||
PPid: 22699
|
||||
`,
|
||||
expectedPid: 0,
|
||||
expectError: true,
|
||||
},
|
||||
}
|
||||
|
||||
for i, test := range tests {
|
||||
filename := path.Join(tempDir, strconv.Itoa(i))
|
||||
err := ioutil.WriteFile(filename, []byte(test.procFile), 0666)
|
||||
if err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
}
|
||||
mounter := NsenterMounter{}
|
||||
pid, err := mounter.getPidOnHost(filename)
|
||||
if err != nil && !test.expectError {
|
||||
t.Errorf("Test %q: unexpected error: %s", test.name, err)
|
||||
}
|
||||
if err == nil && test.expectError {
|
||||
t.Errorf("Test %q: expected error, got none", test.name)
|
||||
}
|
||||
if pid != test.expectedPid {
|
||||
t.Errorf("Test %q: expected pid %d, got %d", test.name, test.expectedPid, pid)
|
||||
}
|
||||
}
|
||||
}
|
||||
242
vendor/k8s.io/kubernetes/pkg/util/mount/safe_format_and_mount_test.go
generated
vendored
242
vendor/k8s.io/kubernetes/pkg/util/mount/safe_format_and_mount_test.go
generated
vendored
|
|
@ -1,242 +0,0 @@
|
|||
/*
|
||||
Copyright 2014 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 mount
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
fakeexec "k8s.io/utils/exec/testing"
|
||||
)
|
||||
|
||||
type ErrorMounter struct {
|
||||
*FakeMounter
|
||||
errIndex int
|
||||
err []error
|
||||
}
|
||||
|
||||
func (mounter *ErrorMounter) Mount(source string, target string, fstype string, options []string) error {
|
||||
i := mounter.errIndex
|
||||
mounter.errIndex++
|
||||
if mounter.err != nil && mounter.err[i] != nil {
|
||||
return mounter.err[i]
|
||||
}
|
||||
return mounter.FakeMounter.Mount(source, target, fstype, options)
|
||||
}
|
||||
|
||||
type ExecArgs struct {
|
||||
command string
|
||||
args []string
|
||||
output string
|
||||
err error
|
||||
}
|
||||
|
||||
func TestSafeFormatAndMount(t *testing.T) {
|
||||
if runtime.GOOS == "darwin" || runtime.GOOS == "windows" {
|
||||
t.Skipf("not supported on GOOS=%s", runtime.GOOS)
|
||||
}
|
||||
mntDir, err := ioutil.TempDir(os.TempDir(), "mount")
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create tmp dir: %v", err)
|
||||
}
|
||||
defer os.RemoveAll(mntDir)
|
||||
tests := []struct {
|
||||
description string
|
||||
fstype string
|
||||
mountOptions []string
|
||||
execScripts []ExecArgs
|
||||
mountErrs []error
|
||||
expectedError error
|
||||
}{
|
||||
{
|
||||
description: "Test a read only mount",
|
||||
fstype: "ext4",
|
||||
mountOptions: []string{"ro"},
|
||||
},
|
||||
{
|
||||
description: "Test a normal mount",
|
||||
fstype: "ext4",
|
||||
execScripts: []ExecArgs{
|
||||
{"fsck", []string{"-a", "/dev/foo"}, "", nil},
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Test 'fsck' fails with exit status 4",
|
||||
fstype: "ext4",
|
||||
execScripts: []ExecArgs{
|
||||
{"fsck", []string{"-a", "/dev/foo"}, "", &fakeexec.FakeExitError{Status: 4}},
|
||||
},
|
||||
expectedError: fmt.Errorf("'fsck' found errors on device /dev/foo but could not correct them: ."),
|
||||
},
|
||||
{
|
||||
description: "Test 'fsck' fails with exit status 1 (errors found and corrected)",
|
||||
fstype: "ext4",
|
||||
execScripts: []ExecArgs{
|
||||
{"fsck", []string{"-a", "/dev/foo"}, "", &fakeexec.FakeExitError{Status: 1}},
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Test 'fsck' fails with exit status other than 1 and 4 (likely unformatted device)",
|
||||
fstype: "ext4",
|
||||
execScripts: []ExecArgs{
|
||||
{"fsck", []string{"-a", "/dev/foo"}, "", &fakeexec.FakeExitError{Status: 8}},
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Test that 'blkid' is called and fails",
|
||||
fstype: "ext4",
|
||||
mountErrs: []error{fmt.Errorf("unknown filesystem type '(null)'")},
|
||||
execScripts: []ExecArgs{
|
||||
{"fsck", []string{"-a", "/dev/foo"}, "", nil},
|
||||
{"blkid", []string{"-p", "-s", "TYPE", "-s", "PTTYPE", "-o", "export", "/dev/foo"}, "DEVNAME=/dev/foo\nTYPE=ext4\n", nil},
|
||||
},
|
||||
expectedError: fmt.Errorf("unknown filesystem type '(null)'"),
|
||||
},
|
||||
{
|
||||
description: "Test that 'blkid' is called and confirms unformatted disk, format fails",
|
||||
fstype: "ext4",
|
||||
mountErrs: []error{fmt.Errorf("unknown filesystem type '(null)'")},
|
||||
execScripts: []ExecArgs{
|
||||
{"fsck", []string{"-a", "/dev/foo"}, "", nil},
|
||||
{"blkid", []string{"-p", "-s", "TYPE", "-s", "PTTYPE", "-o", "export", "/dev/foo"}, "", &fakeexec.FakeExitError{Status: 2}},
|
||||
{"mkfs.ext4", []string{"-F", "/dev/foo"}, "", fmt.Errorf("formatting failed")},
|
||||
},
|
||||
expectedError: fmt.Errorf("formatting failed"),
|
||||
},
|
||||
{
|
||||
description: "Test that 'blkid' is called and confirms unformatted disk, format passes, second mount fails",
|
||||
fstype: "ext4",
|
||||
mountErrs: []error{fmt.Errorf("unknown filesystem type '(null)'"), fmt.Errorf("Still cannot mount")},
|
||||
execScripts: []ExecArgs{
|
||||
{"fsck", []string{"-a", "/dev/foo"}, "", nil},
|
||||
{"blkid", []string{"-p", "-s", "TYPE", "-s", "PTTYPE", "-o", "export", "/dev/foo"}, "", &fakeexec.FakeExitError{Status: 2}},
|
||||
{"mkfs.ext4", []string{"-F", "/dev/foo"}, "", nil},
|
||||
},
|
||||
expectedError: fmt.Errorf("Still cannot mount"),
|
||||
},
|
||||
{
|
||||
description: "Test that 'blkid' is called and confirms unformatted disk, format passes, second mount passes",
|
||||
fstype: "ext4",
|
||||
mountErrs: []error{fmt.Errorf("unknown filesystem type '(null)'"), nil},
|
||||
execScripts: []ExecArgs{
|
||||
{"fsck", []string{"-a", "/dev/foo"}, "", nil},
|
||||
{"blkid", []string{"-p", "-s", "TYPE", "-s", "PTTYPE", "-o", "export", "/dev/foo"}, "", &fakeexec.FakeExitError{Status: 2}},
|
||||
{"mkfs.ext4", []string{"-F", "/dev/foo"}, "", nil},
|
||||
},
|
||||
expectedError: nil,
|
||||
},
|
||||
{
|
||||
description: "Test that 'blkid' is called and confirms unformatted disk, format passes, second mount passes with ext3",
|
||||
fstype: "ext3",
|
||||
mountErrs: []error{fmt.Errorf("unknown filesystem type '(null)'"), nil},
|
||||
execScripts: []ExecArgs{
|
||||
{"fsck", []string{"-a", "/dev/foo"}, "", nil},
|
||||
{"blkid", []string{"-p", "-s", "TYPE", "-s", "PTTYPE", "-o", "export", "/dev/foo"}, "", &fakeexec.FakeExitError{Status: 2}},
|
||||
{"mkfs.ext3", []string{"-F", "/dev/foo"}, "", nil},
|
||||
},
|
||||
expectedError: nil,
|
||||
},
|
||||
{
|
||||
description: "test that none ext4 fs does not get called with ext4 options.",
|
||||
fstype: "xfs",
|
||||
mountErrs: []error{fmt.Errorf("unknown filesystem type '(null)'"), nil},
|
||||
execScripts: []ExecArgs{
|
||||
{"fsck", []string{"-a", "/dev/foo"}, "", nil},
|
||||
{"blkid", []string{"-p", "-s", "TYPE", "-s", "PTTYPE", "-o", "export", "/dev/foo"}, "", &fakeexec.FakeExitError{Status: 2}},
|
||||
{"mkfs.xfs", []string{"/dev/foo"}, "", nil},
|
||||
},
|
||||
expectedError: nil,
|
||||
},
|
||||
{
|
||||
description: "Test that 'blkid' is called and reports ext4 partition",
|
||||
fstype: "ext3",
|
||||
mountErrs: []error{fmt.Errorf("unknown filesystem type '(null)'")},
|
||||
execScripts: []ExecArgs{
|
||||
{"fsck", []string{"-a", "/dev/foo"}, "", nil},
|
||||
{"blkid", []string{"-p", "-s", "TYPE", "-s", "PTTYPE", "-o", "export", "/dev/foo"}, "DEVNAME=/dev/foo\nPTTYPE=dos\n", nil},
|
||||
},
|
||||
expectedError: fmt.Errorf("failed to mount the volume as \"ext3\", it already contains unknown data, probably partitions. Mount error: unknown filesystem type '(null)'"),
|
||||
},
|
||||
{
|
||||
description: "Test that 'blkid' is called but has some usage or other errors (an exit code of 4 is returned)",
|
||||
fstype: "xfs",
|
||||
mountErrs: []error{fmt.Errorf("unknown filesystem type '(null)'"), nil},
|
||||
execScripts: []ExecArgs{
|
||||
{"fsck", []string{"-a", "/dev/foo"}, "", nil},
|
||||
{"blkid", []string{"-p", "-s", "TYPE", "-s", "PTTYPE", "-o", "export", "/dev/foo"}, "", &fakeexec.FakeExitError{Status: 4}},
|
||||
{"mkfs.xfs", []string{"/dev/foo"}, "", nil},
|
||||
},
|
||||
expectedError: fmt.Errorf("exit 4"),
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
execCallCount := 0
|
||||
execCallback := func(cmd string, args ...string) ([]byte, error) {
|
||||
if len(test.execScripts) <= execCallCount {
|
||||
t.Errorf("Unexpected command: %s %v", cmd, args)
|
||||
return nil, nil
|
||||
}
|
||||
script := test.execScripts[execCallCount]
|
||||
execCallCount++
|
||||
if script.command != cmd {
|
||||
t.Errorf("Unexpected command %s. Expecting %s", cmd, script.command)
|
||||
}
|
||||
for j := range args {
|
||||
if args[j] != script.args[j] {
|
||||
t.Errorf("Unexpected args %v. Expecting %v", args, script.args)
|
||||
}
|
||||
}
|
||||
return []byte(script.output), script.err
|
||||
}
|
||||
|
||||
fakeMounter := ErrorMounter{&FakeMounter{}, 0, test.mountErrs}
|
||||
fakeExec := NewFakeExec(execCallback)
|
||||
mounter := SafeFormatAndMount{
|
||||
Interface: &fakeMounter,
|
||||
Exec: fakeExec,
|
||||
}
|
||||
|
||||
device := "/dev/foo"
|
||||
dest := mntDir
|
||||
err := mounter.FormatAndMount(device, dest, test.fstype, test.mountOptions)
|
||||
if test.expectedError == nil {
|
||||
if err != nil {
|
||||
t.Errorf("test \"%s\" unexpected non-error: %v", test.description, err)
|
||||
}
|
||||
|
||||
// Check that something was mounted on the directory
|
||||
isNotMountPoint, err := fakeMounter.IsLikelyNotMountPoint(dest)
|
||||
if err != nil || isNotMountPoint {
|
||||
t.Errorf("test \"%s\" the directory was not mounted", test.description)
|
||||
}
|
||||
|
||||
//check that the correct device was mounted
|
||||
mountedDevice, _, err := GetDeviceNameFromMount(fakeMounter.FakeMounter, dest)
|
||||
if err != nil || mountedDevice != device {
|
||||
t.Errorf("test \"%s\" the correct device was not mounted", test.description)
|
||||
}
|
||||
} else {
|
||||
if err == nil || test.expectedError.Error() != err.Error() {
|
||||
t.Errorf("test \"%s\" unexpected error: \n [%v]. \nExpecting [%v]", test.description, err, test.expectedError)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
286
vendor/k8s.io/kubernetes/pkg/util/net/net_test.go
generated
vendored
286
vendor/k8s.io/kubernetes/pkg/util/net/net_test.go
generated
vendored
|
|
@ -1,286 +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 net
|
||||
|
||||
import (
|
||||
"net"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestIsIPv6String(t *testing.T) {
|
||||
testCases := []struct {
|
||||
ip string
|
||||
expectIPv6 bool
|
||||
}{
|
||||
{
|
||||
ip: "127.0.0.1",
|
||||
expectIPv6: false,
|
||||
},
|
||||
{
|
||||
ip: "192.168.0.0",
|
||||
expectIPv6: false,
|
||||
},
|
||||
{
|
||||
ip: "1.2.3.4",
|
||||
expectIPv6: false,
|
||||
},
|
||||
{
|
||||
ip: "bad ip",
|
||||
expectIPv6: false,
|
||||
},
|
||||
{
|
||||
ip: "::1",
|
||||
expectIPv6: true,
|
||||
},
|
||||
{
|
||||
ip: "fd00::600d:f00d",
|
||||
expectIPv6: true,
|
||||
},
|
||||
{
|
||||
ip: "2001:db8::5",
|
||||
expectIPv6: true,
|
||||
},
|
||||
}
|
||||
for i := range testCases {
|
||||
isIPv6 := IsIPv6String(testCases[i].ip)
|
||||
if isIPv6 != testCases[i].expectIPv6 {
|
||||
t.Errorf("[%d] Expect ipv6 %v, got %v", i+1, testCases[i].expectIPv6, isIPv6)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsIPv6(t *testing.T) {
|
||||
testCases := []struct {
|
||||
ip net.IP
|
||||
expectIPv6 bool
|
||||
}{
|
||||
{
|
||||
ip: net.IPv4zero,
|
||||
expectIPv6: false,
|
||||
},
|
||||
{
|
||||
ip: net.IPv4bcast,
|
||||
expectIPv6: false,
|
||||
},
|
||||
{
|
||||
ip: net.ParseIP("127.0.0.1"),
|
||||
expectIPv6: false,
|
||||
},
|
||||
{
|
||||
ip: net.ParseIP("10.20.40.40"),
|
||||
expectIPv6: false,
|
||||
},
|
||||
{
|
||||
ip: net.ParseIP("172.17.3.0"),
|
||||
expectIPv6: false,
|
||||
},
|
||||
{
|
||||
ip: nil,
|
||||
expectIPv6: false,
|
||||
},
|
||||
{
|
||||
ip: net.IPv6loopback,
|
||||
expectIPv6: true,
|
||||
},
|
||||
{
|
||||
ip: net.IPv6zero,
|
||||
expectIPv6: true,
|
||||
},
|
||||
{
|
||||
ip: net.ParseIP("fd00::600d:f00d"),
|
||||
expectIPv6: true,
|
||||
},
|
||||
{
|
||||
ip: net.ParseIP("2001:db8::5"),
|
||||
expectIPv6: true,
|
||||
},
|
||||
}
|
||||
for i := range testCases {
|
||||
isIPv6 := IsIPv6(testCases[i].ip)
|
||||
if isIPv6 != testCases[i].expectIPv6 {
|
||||
t.Errorf("[%d] Expect ipv6 %v, got %v", i+1, testCases[i].expectIPv6, isIPv6)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsIPv6CIDR(t *testing.T) {
|
||||
testCases := []struct {
|
||||
desc string
|
||||
cidr string
|
||||
expectResult bool
|
||||
}{
|
||||
{
|
||||
desc: "ipv4 CIDR 1",
|
||||
cidr: "10.0.0.0/8",
|
||||
expectResult: false,
|
||||
},
|
||||
{
|
||||
desc: "ipv4 CIDR 2",
|
||||
cidr: "192.168.0.0/16",
|
||||
expectResult: false,
|
||||
},
|
||||
{
|
||||
desc: "ipv6 CIDR 1",
|
||||
cidr: "::/1",
|
||||
expectResult: true,
|
||||
},
|
||||
{
|
||||
desc: "ipv6 CIDR 2",
|
||||
cidr: "2000::/10",
|
||||
expectResult: true,
|
||||
},
|
||||
{
|
||||
desc: "ipv6 CIDR 3",
|
||||
cidr: "2001:db8::/32",
|
||||
expectResult: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
res := IsIPv6CIDR(tc.cidr)
|
||||
if res != tc.expectResult {
|
||||
t.Errorf("%v: want IsIPv6CIDR=%v, got %v", tc.desc, tc.expectResult, res)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestFilterIncorrectIPVersion(t *testing.T) {
|
||||
testCases := []struct {
|
||||
desc string
|
||||
isIPv6 bool
|
||||
ipStrings []string
|
||||
expectCorrects []string
|
||||
expectIncorrects []string
|
||||
}{
|
||||
{
|
||||
desc: "all ipv4 strings in ipv4 mode",
|
||||
isIPv6: false,
|
||||
ipStrings: []string{"10.0.0.1", "192.168.0.1", "127.0.0.1"},
|
||||
expectCorrects: []string{"10.0.0.1", "192.168.0.1", "127.0.0.1"},
|
||||
expectIncorrects: nil,
|
||||
},
|
||||
{
|
||||
desc: "all ipv6 strings in ipv4 mode",
|
||||
isIPv6: false,
|
||||
ipStrings: []string{"::1", "fd00::600d:f00d", "2001:db8::5"},
|
||||
expectCorrects: nil,
|
||||
expectIncorrects: []string{"::1", "fd00::600d:f00d", "2001:db8::5"},
|
||||
},
|
||||
{
|
||||
desc: "mixed versions in ipv4 mode",
|
||||
isIPv6: false,
|
||||
ipStrings: []string{"10.0.0.1", "192.168.0.1", "127.0.0.1", "::1", "fd00::600d:f00d", "2001:db8::5"},
|
||||
expectCorrects: []string{"10.0.0.1", "192.168.0.1", "127.0.0.1"},
|
||||
expectIncorrects: []string{"::1", "fd00::600d:f00d", "2001:db8::5"},
|
||||
},
|
||||
{
|
||||
desc: "all ipv4 strings in ipv6 mode",
|
||||
isIPv6: true,
|
||||
ipStrings: []string{"10.0.0.1", "192.168.0.1", "127.0.0.1"},
|
||||
expectCorrects: nil,
|
||||
expectIncorrects: []string{"10.0.0.1", "192.168.0.1", "127.0.0.1"},
|
||||
},
|
||||
{
|
||||
desc: "all ipv6 strings in ipv6 mode",
|
||||
isIPv6: true,
|
||||
ipStrings: []string{"::1", "fd00::600d:f00d", "2001:db8::5"},
|
||||
expectCorrects: []string{"::1", "fd00::600d:f00d", "2001:db8::5"},
|
||||
expectIncorrects: nil,
|
||||
},
|
||||
{
|
||||
desc: "mixed versions in ipv6 mode",
|
||||
isIPv6: true,
|
||||
ipStrings: []string{"10.0.0.1", "192.168.0.1", "127.0.0.1", "::1", "fd00::600d:f00d", "2001:db8::5"},
|
||||
expectCorrects: []string{"::1", "fd00::600d:f00d", "2001:db8::5"},
|
||||
expectIncorrects: []string{"10.0.0.1", "192.168.0.1", "127.0.0.1"},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
corrects, incorrects := FilterIncorrectIPVersion(tc.ipStrings, tc.isIPv6)
|
||||
if !reflect.DeepEqual(tc.expectCorrects, corrects) {
|
||||
t.Errorf("%v: want corrects=%v, got %v", tc.desc, tc.expectCorrects, corrects)
|
||||
}
|
||||
if !reflect.DeepEqual(tc.expectIncorrects, incorrects) {
|
||||
t.Errorf("%v: want incorrects=%v, got %v", tc.desc, tc.expectIncorrects, incorrects)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestFilterIncorrectCIDRVersion(t *testing.T) {
|
||||
testCases := []struct {
|
||||
desc string
|
||||
isIPv6 bool
|
||||
cidrStrings []string
|
||||
expectCorrects []string
|
||||
expectIncorrects []string
|
||||
}{
|
||||
{
|
||||
desc: "all ipv4 strings in ipv4 mode",
|
||||
isIPv6: false,
|
||||
cidrStrings: []string{"0.0.0.0/1", "1.0.0.0/1"},
|
||||
expectCorrects: []string{"0.0.0.0/1", "1.0.0.0/1"},
|
||||
expectIncorrects: nil,
|
||||
},
|
||||
{
|
||||
desc: "all ipv6 strings in ipv4 mode",
|
||||
isIPv6: false,
|
||||
cidrStrings: []string{"2001:db8::/32", "2001:0db8:0123:4567::/64"},
|
||||
expectCorrects: nil,
|
||||
expectIncorrects: []string{"2001:db8::/32", "2001:0db8:0123:4567::/64"},
|
||||
},
|
||||
{
|
||||
desc: "mixed versions in ipv4 mode",
|
||||
isIPv6: false,
|
||||
cidrStrings: []string{"0.0.0.0/1", "1.0.0.0/1", "2001:db8::/32", "2001:0db8:0123:4567::/64"},
|
||||
expectCorrects: []string{"0.0.0.0/1", "1.0.0.0/1"},
|
||||
expectIncorrects: []string{"2001:db8::/32", "2001:0db8:0123:4567::/64"},
|
||||
},
|
||||
{
|
||||
desc: "all ipv4 strings in ipv6 mode",
|
||||
isIPv6: true,
|
||||
cidrStrings: []string{"0.0.0.0/1", "1.0.0.0/1"},
|
||||
expectCorrects: nil,
|
||||
expectIncorrects: []string{"0.0.0.0/1", "1.0.0.0/1"},
|
||||
},
|
||||
{
|
||||
desc: "all ipv6 strings in ipv6 mode",
|
||||
isIPv6: true,
|
||||
cidrStrings: []string{"2001:db8::/32", "2001:0db8:0123:4567::/64"},
|
||||
expectCorrects: []string{"2001:db8::/32", "2001:0db8:0123:4567::/64"},
|
||||
expectIncorrects: nil,
|
||||
},
|
||||
{
|
||||
desc: "mixed versions in ipv6 mode",
|
||||
isIPv6: true,
|
||||
cidrStrings: []string{"0.0.0.0/1", "1.0.0.0/1", "2001:db8::/32", "2001:0db8:0123:4567::/64"},
|
||||
expectCorrects: []string{"2001:db8::/32", "2001:0db8:0123:4567::/64"},
|
||||
expectIncorrects: []string{"0.0.0.0/1", "1.0.0.0/1"},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
corrects, incorrects := FilterIncorrectCIDRVersion(tc.cidrStrings, tc.isIPv6)
|
||||
if !reflect.DeepEqual(tc.expectCorrects, corrects) {
|
||||
t.Errorf("%v: want corrects=%v, got %v", tc.desc, tc.expectCorrects, corrects)
|
||||
}
|
||||
if !reflect.DeepEqual(tc.expectIncorrects, incorrects) {
|
||||
t.Errorf("%v: want incorrects=%v, got %v", tc.desc, tc.expectIncorrects, incorrects)
|
||||
}
|
||||
}
|
||||
}
|
||||
155
vendor/k8s.io/kubernetes/pkg/util/net/sets/ipnet_test.go
generated
vendored
155
vendor/k8s.io/kubernetes/pkg/util/net/sets/ipnet_test.go
generated
vendored
|
|
@ -1,155 +0,0 @@
|
|||
/*
|
||||
Copyright 2014 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 sets
|
||||
|
||||
import (
|
||||
"net"
|
||||
"reflect"
|
||||
"sort"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func parseIPNet(s string) *net.IPNet {
|
||||
_, net, err := net.ParseCIDR(s)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return net
|
||||
}
|
||||
|
||||
func TestIPNets(t *testing.T) {
|
||||
s := IPNet{}
|
||||
s2 := IPNet{}
|
||||
if len(s) != 0 {
|
||||
t.Errorf("Expected len=0: %d", len(s))
|
||||
}
|
||||
a := parseIPNet("1.0.0.0/8")
|
||||
b := parseIPNet("2.0.0.0/8")
|
||||
c := parseIPNet("3.0.0.0/8")
|
||||
d := parseIPNet("4.0.0.0/8")
|
||||
|
||||
s.Insert(a, b)
|
||||
if len(s) != 2 {
|
||||
t.Errorf("Expected len=2: %d", len(s))
|
||||
}
|
||||
s.Insert(c)
|
||||
if s.Has(d) {
|
||||
t.Errorf("Unexpected contents: %#v", s)
|
||||
}
|
||||
if !s.Has(a) {
|
||||
t.Errorf("Missing contents: %#v", s)
|
||||
}
|
||||
s.Delete(a)
|
||||
if s.Has(a) {
|
||||
t.Errorf("Unexpected contents: %#v", s)
|
||||
}
|
||||
s.Insert(a)
|
||||
if s.HasAll(a, b, d) {
|
||||
t.Errorf("Unexpected contents: %#v", s)
|
||||
}
|
||||
if !s.HasAll(a, b) {
|
||||
t.Errorf("Missing contents: %#v", s)
|
||||
}
|
||||
s2.Insert(a, b, d)
|
||||
if s.IsSuperset(s2) {
|
||||
t.Errorf("Unexpected contents: %#v", s)
|
||||
}
|
||||
s2.Delete(d)
|
||||
if !s.IsSuperset(s2) {
|
||||
t.Errorf("Missing contents: %#v", s)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIPNetSetDeleteMultiples(t *testing.T) {
|
||||
s := IPNet{}
|
||||
a := parseIPNet("1.0.0.0/8")
|
||||
b := parseIPNet("2.0.0.0/8")
|
||||
c := parseIPNet("3.0.0.0/8")
|
||||
|
||||
s.Insert(a, b, c)
|
||||
if len(s) != 3 {
|
||||
t.Errorf("Expected len=3: %d", len(s))
|
||||
}
|
||||
|
||||
s.Delete(a, c)
|
||||
if len(s) != 1 {
|
||||
t.Errorf("Expected len=1: %d", len(s))
|
||||
}
|
||||
if s.Has(a) {
|
||||
t.Errorf("Unexpected contents: %#v", s)
|
||||
}
|
||||
if s.Has(c) {
|
||||
t.Errorf("Unexpected contents: %#v", s)
|
||||
}
|
||||
if !s.Has(b) {
|
||||
t.Errorf("Missing contents: %#v", s)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewIPSet(t *testing.T) {
|
||||
s, err := ParseIPNets("1.0.0.0/8", "2.0.0.0/8", "3.0.0.0/8")
|
||||
if err != nil {
|
||||
t.Errorf("error parsing IPNets: %v", err)
|
||||
}
|
||||
if len(s) != 3 {
|
||||
t.Errorf("Expected len=3: %d", len(s))
|
||||
}
|
||||
a := parseIPNet("1.0.0.0/8")
|
||||
b := parseIPNet("2.0.0.0/8")
|
||||
c := parseIPNet("3.0.0.0/8")
|
||||
|
||||
if !s.Has(a) || !s.Has(b) || !s.Has(c) {
|
||||
t.Errorf("Unexpected contents: %#v", s)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIPNetSetDifference(t *testing.T) {
|
||||
l, err := ParseIPNets("1.0.0.0/8", "2.0.0.0/8", "3.0.0.0/8")
|
||||
if err != nil {
|
||||
t.Errorf("error parsing IPNets: %v", err)
|
||||
}
|
||||
r, err := ParseIPNets("1.0.0.0/8", "2.0.0.0/8", "4.0.0.0/8", "5.0.0.0/8")
|
||||
if err != nil {
|
||||
t.Errorf("error parsing IPNets: %v", err)
|
||||
}
|
||||
c := l.Difference(r)
|
||||
d := r.Difference(l)
|
||||
if len(c) != 1 {
|
||||
t.Errorf("Expected len=1: %d", len(c))
|
||||
}
|
||||
if !c.Has(parseIPNet("3.0.0.0/8")) {
|
||||
t.Errorf("Unexpected contents: %#v", c)
|
||||
}
|
||||
if len(d) != 2 {
|
||||
t.Errorf("Expected len=2: %d", len(d))
|
||||
}
|
||||
if !d.Has(parseIPNet("4.0.0.0/8")) || !d.Has(parseIPNet("5.0.0.0/8")) {
|
||||
t.Errorf("Unexpected contents: %#v", d)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIPNetSetList(t *testing.T) {
|
||||
s, err := ParseIPNets("3.0.0.0/8", "1.0.0.0/8", "2.0.0.0/8")
|
||||
if err != nil {
|
||||
t.Errorf("error parsing IPNets: %v", err)
|
||||
}
|
||||
l := s.StringSlice()
|
||||
sort.Strings(l)
|
||||
if !reflect.DeepEqual(l, []string{"1.0.0.0/8", "2.0.0.0/8", "3.0.0.0/8"}) {
|
||||
t.Errorf("List gave unexpected result: %#v", l)
|
||||
}
|
||||
}
|
||||
51
vendor/k8s.io/kubernetes/pkg/util/parsers/parsers_test.go
generated
vendored
51
vendor/k8s.io/kubernetes/pkg/util/parsers/parsers_test.go
generated
vendored
|
|
@ -1,51 +0,0 @@
|
|||
/*
|
||||
Copyright 2016 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 parsers
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
// Based on Docker test case removed in:
|
||||
// https://github.com/docker/docker/commit/4352da7803d182a6013a5238ce20a7c749db979a
|
||||
func TestParseImageName(t *testing.T) {
|
||||
testCases := []struct {
|
||||
Input string
|
||||
Repo string
|
||||
Tag string
|
||||
Digest string
|
||||
}{
|
||||
{Input: "root", Repo: "docker.io/library/root", Tag: "latest"},
|
||||
{Input: "root:tag", Repo: "docker.io/library/root", Tag: "tag"},
|
||||
{Input: "root@sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", Repo: "docker.io/library/root", Digest: "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"},
|
||||
{Input: "user/repo", Repo: "docker.io/user/repo", Tag: "latest"},
|
||||
{Input: "user/repo:tag", Repo: "docker.io/user/repo", Tag: "tag"},
|
||||
{Input: "user/repo@sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", Repo: "docker.io/user/repo", Digest: "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"},
|
||||
{Input: "url:5000/repo", Repo: "url:5000/repo", Tag: "latest"},
|
||||
{Input: "url:5000/repo:tag", Repo: "url:5000/repo", Tag: "tag"},
|
||||
{Input: "url:5000/repo@sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", Repo: "url:5000/repo", Digest: "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"},
|
||||
}
|
||||
for _, testCase := range testCases {
|
||||
repo, tag, digest, err := ParseImageName(testCase.Input)
|
||||
if err != nil {
|
||||
t.Errorf("ParseImageName(%s) failed: %v", testCase.Input, err)
|
||||
} else if repo != testCase.Repo || tag != testCase.Tag || digest != testCase.Digest {
|
||||
t.Errorf("Expected repo: %q, tag: %q and digest: %q, got %q, %q and %q", testCase.Repo, testCase.Tag, testCase.Digest,
|
||||
repo, tag, digest)
|
||||
}
|
||||
}
|
||||
}
|
||||
66
vendor/k8s.io/kubernetes/pkg/util/pointer/pointer_test.go
generated
vendored
66
vendor/k8s.io/kubernetes/pkg/util/pointer/pointer_test.go
generated
vendored
|
|
@ -1,66 +0,0 @@
|
|||
/*
|
||||
Copyright 2017 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 pointer
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestAllPtrFieldsNil(t *testing.T) {
|
||||
testCases := []struct {
|
||||
obj interface{}
|
||||
expected bool
|
||||
}{
|
||||
{struct{}{}, true},
|
||||
{struct{ Foo int }{12345}, true},
|
||||
{&struct{ Foo int }{12345}, true},
|
||||
{struct{ Foo *int }{nil}, true},
|
||||
{&struct{ Foo *int }{nil}, true},
|
||||
{struct {
|
||||
Foo int
|
||||
Bar *int
|
||||
}{12345, nil}, true},
|
||||
{&struct {
|
||||
Foo int
|
||||
Bar *int
|
||||
}{12345, nil}, true},
|
||||
{struct {
|
||||
Foo *int
|
||||
Bar *int
|
||||
}{nil, nil}, true},
|
||||
{&struct {
|
||||
Foo *int
|
||||
Bar *int
|
||||
}{nil, nil}, true},
|
||||
{struct{ Foo *int }{new(int)}, false},
|
||||
{&struct{ Foo *int }{new(int)}, false},
|
||||
{struct {
|
||||
Foo *int
|
||||
Bar *int
|
||||
}{nil, new(int)}, false},
|
||||
{&struct {
|
||||
Foo *int
|
||||
Bar *int
|
||||
}{nil, new(int)}, false},
|
||||
{(*struct{})(nil), true},
|
||||
}
|
||||
for i, tc := range testCases {
|
||||
if AllPtrFieldsNil(tc.obj) != tc.expected {
|
||||
t.Errorf("case[%d]: expected %t, got %t", i, tc.expected, !tc.expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
687
vendor/k8s.io/kubernetes/pkg/util/taints/taints_test.go
generated
vendored
687
vendor/k8s.io/kubernetes/pkg/util/taints/taints_test.go
generated
vendored
|
|
@ -1,687 +0,0 @@
|
|||
/*
|
||||
Copyright 2016 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 taints
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
func TestTaintsVar(t *testing.T) {
|
||||
cases := []struct {
|
||||
f string
|
||||
err bool
|
||||
t []api.Taint
|
||||
}{
|
||||
{
|
||||
f: "",
|
||||
t: []api.Taint(nil),
|
||||
},
|
||||
{
|
||||
f: "--t=foo=bar:NoSchedule",
|
||||
t: []api.Taint{{Key: "foo", Value: "bar", Effect: "NoSchedule"}},
|
||||
},
|
||||
{
|
||||
f: "--t=foo=bar:NoSchedule,bing=bang:PreferNoSchedule",
|
||||
t: []api.Taint{
|
||||
{Key: "foo", Value: "bar", Effect: api.TaintEffectNoSchedule},
|
||||
{Key: "bing", Value: "bang", Effect: api.TaintEffectPreferNoSchedule},
|
||||
},
|
||||
},
|
||||
{
|
||||
f: "--t=dedicated-for=user1:NoExecute",
|
||||
t: []api.Taint{{Key: "dedicated-for", Value: "user1", Effect: "NoExecute"}},
|
||||
},
|
||||
}
|
||||
|
||||
for i, c := range cases {
|
||||
args := append([]string{"test"}, strings.Fields(c.f)...)
|
||||
cli := pflag.NewFlagSet("test", pflag.ContinueOnError)
|
||||
var taints []api.Taint
|
||||
cli.Var(NewTaintsVar(&taints), "t", "bar")
|
||||
|
||||
err := cli.Parse(args)
|
||||
if err == nil && c.err {
|
||||
t.Errorf("[%v] expected error", i)
|
||||
continue
|
||||
}
|
||||
if err != nil && !c.err {
|
||||
t.Errorf("[%v] unexpected error: %v", i, err)
|
||||
continue
|
||||
}
|
||||
if !reflect.DeepEqual(c.t, taints) {
|
||||
t.Errorf("[%v] unexpected taints:\n\texpected:\n\t\t%#v\n\tgot:\n\t\t%#v", i, c.t, taints)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestAddOrUpdateTaint(t *testing.T) {
|
||||
node := &v1.Node{}
|
||||
|
||||
taint := &v1.Taint{
|
||||
Key: "foo",
|
||||
Value: "bar",
|
||||
Effect: v1.TaintEffectNoSchedule,
|
||||
}
|
||||
|
||||
checkResult := func(testCaseName string, newNode *v1.Node, expectedTaint *v1.Taint, result, expectedResult bool, err error) {
|
||||
if err != nil {
|
||||
t.Errorf("[%s] should not raise error but got %v", testCaseName, err)
|
||||
}
|
||||
if result != expectedResult {
|
||||
t.Errorf("[%s] should return %t, but got: %t", testCaseName, expectedResult, result)
|
||||
}
|
||||
if len(newNode.Spec.Taints) != 1 || !reflect.DeepEqual(newNode.Spec.Taints[0], *expectedTaint) {
|
||||
t.Errorf("[%s] node should only have one taint: %v, but got: %v", testCaseName, *expectedTaint, newNode.Spec.Taints)
|
||||
}
|
||||
}
|
||||
|
||||
// Add a new Taint.
|
||||
newNode, result, err := AddOrUpdateTaint(node, taint)
|
||||
checkResult("Add New Taint", newNode, taint, result, true, err)
|
||||
|
||||
// Update a Taint.
|
||||
taint.Value = "bar_1"
|
||||
newNode, result, err = AddOrUpdateTaint(node, taint)
|
||||
checkResult("Update Taint", newNode, taint, result, true, err)
|
||||
|
||||
// Add a duplicate Taint.
|
||||
node = newNode
|
||||
newNode, result, err = AddOrUpdateTaint(node, taint)
|
||||
checkResult("Add Duplicate Taint", newNode, taint, result, false, err)
|
||||
}
|
||||
|
||||
func TestTaintExists(t *testing.T) {
|
||||
testingTaints := []v1.Taint{
|
||||
{
|
||||
Key: "foo_1",
|
||||
Value: "bar_1",
|
||||
Effect: v1.TaintEffectNoExecute,
|
||||
},
|
||||
{
|
||||
Key: "foo_2",
|
||||
Value: "bar_2",
|
||||
Effect: v1.TaintEffectNoSchedule,
|
||||
},
|
||||
}
|
||||
|
||||
cases := []struct {
|
||||
name string
|
||||
taintToFind *v1.Taint
|
||||
expectedResult bool
|
||||
}{
|
||||
{
|
||||
name: "taint exists",
|
||||
taintToFind: &v1.Taint{Key: "foo_1", Value: "bar_1", Effect: v1.TaintEffectNoExecute},
|
||||
expectedResult: true,
|
||||
},
|
||||
{
|
||||
name: "different key",
|
||||
taintToFind: &v1.Taint{Key: "no_such_key", Value: "bar_1", Effect: v1.TaintEffectNoExecute},
|
||||
expectedResult: false,
|
||||
},
|
||||
{
|
||||
name: "different effect",
|
||||
taintToFind: &v1.Taint{Key: "foo_1", Value: "bar_1", Effect: v1.TaintEffectNoSchedule},
|
||||
expectedResult: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
result := TaintExists(testingTaints, c.taintToFind)
|
||||
|
||||
if result != c.expectedResult {
|
||||
t.Errorf("[%s] unexpected results: %v", c.name, result)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRemoveTaint(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
node *v1.Node
|
||||
taintToRemove *v1.Taint
|
||||
expectedTaints []v1.Taint
|
||||
expectedResult bool
|
||||
}{
|
||||
{
|
||||
name: "remove taint unsuccessfully",
|
||||
node: &v1.Node{
|
||||
Spec: v1.NodeSpec{
|
||||
Taints: []v1.Taint{
|
||||
{
|
||||
Key: "foo",
|
||||
Effect: v1.TaintEffectNoSchedule,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
taintToRemove: &v1.Taint{
|
||||
Key: "foo_1",
|
||||
Effect: v1.TaintEffectNoSchedule,
|
||||
},
|
||||
expectedTaints: []v1.Taint{
|
||||
{
|
||||
Key: "foo",
|
||||
Effect: v1.TaintEffectNoSchedule,
|
||||
},
|
||||
},
|
||||
expectedResult: false,
|
||||
},
|
||||
{
|
||||
name: "remove taint successfully",
|
||||
node: &v1.Node{
|
||||
Spec: v1.NodeSpec{
|
||||
Taints: []v1.Taint{
|
||||
{
|
||||
Key: "foo",
|
||||
Effect: v1.TaintEffectNoSchedule,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
taintToRemove: &v1.Taint{
|
||||
Key: "foo",
|
||||
Effect: v1.TaintEffectNoSchedule,
|
||||
},
|
||||
expectedTaints: []v1.Taint{},
|
||||
expectedResult: true,
|
||||
},
|
||||
{
|
||||
name: "remove taint from node with no taint",
|
||||
node: &v1.Node{
|
||||
Spec: v1.NodeSpec{
|
||||
Taints: []v1.Taint{},
|
||||
},
|
||||
},
|
||||
taintToRemove: &v1.Taint{
|
||||
Key: "foo",
|
||||
Effect: v1.TaintEffectNoSchedule,
|
||||
},
|
||||
expectedTaints: []v1.Taint{},
|
||||
expectedResult: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
newNode, result, err := RemoveTaint(c.node, c.taintToRemove)
|
||||
if err != nil {
|
||||
t.Errorf("[%s] should not raise error but got: %v", c.name, err)
|
||||
}
|
||||
if result != c.expectedResult {
|
||||
t.Errorf("[%s] should return %t, but got: %t", c.name, c.expectedResult, result)
|
||||
}
|
||||
if !reflect.DeepEqual(newNode.Spec.Taints, c.expectedTaints) {
|
||||
t.Errorf("[%s] the new node object should have taints %v, but got: %v", c.name, c.expectedTaints, newNode.Spec.Taints)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeleteTaint(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
taints []v1.Taint
|
||||
taintToDelete *v1.Taint
|
||||
expectedTaints []v1.Taint
|
||||
expectedResult bool
|
||||
}{
|
||||
{
|
||||
name: "delete taint with different name",
|
||||
taints: []v1.Taint{
|
||||
{
|
||||
Key: "foo",
|
||||
Effect: v1.TaintEffectNoSchedule,
|
||||
},
|
||||
},
|
||||
taintToDelete: &v1.Taint{Key: "foo_1", Effect: v1.TaintEffectNoSchedule},
|
||||
expectedTaints: []v1.Taint{
|
||||
{
|
||||
Key: "foo",
|
||||
Effect: v1.TaintEffectNoSchedule,
|
||||
},
|
||||
},
|
||||
expectedResult: false,
|
||||
},
|
||||
{
|
||||
name: "delete taint with different effect",
|
||||
taints: []v1.Taint{
|
||||
{
|
||||
Key: "foo",
|
||||
Effect: v1.TaintEffectNoSchedule,
|
||||
},
|
||||
},
|
||||
taintToDelete: &v1.Taint{Key: "foo", Effect: v1.TaintEffectNoExecute},
|
||||
expectedTaints: []v1.Taint{
|
||||
{
|
||||
Key: "foo",
|
||||
Effect: v1.TaintEffectNoSchedule,
|
||||
},
|
||||
},
|
||||
expectedResult: false,
|
||||
},
|
||||
{
|
||||
name: "delete taint successfully",
|
||||
taints: []v1.Taint{
|
||||
{
|
||||
Key: "foo",
|
||||
Effect: v1.TaintEffectNoSchedule,
|
||||
},
|
||||
},
|
||||
taintToDelete: &v1.Taint{Key: "foo", Effect: v1.TaintEffectNoSchedule},
|
||||
expectedTaints: []v1.Taint{},
|
||||
expectedResult: true,
|
||||
},
|
||||
{
|
||||
name: "delete taint from empty taint array",
|
||||
taints: []v1.Taint{},
|
||||
taintToDelete: &v1.Taint{Key: "foo", Effect: v1.TaintEffectNoSchedule},
|
||||
expectedTaints: []v1.Taint{},
|
||||
expectedResult: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
taints, result := DeleteTaint(c.taints, c.taintToDelete)
|
||||
if result != c.expectedResult {
|
||||
t.Errorf("[%s] should return %t, but got: %t", c.name, c.expectedResult, result)
|
||||
}
|
||||
if !reflect.DeepEqual(taints, c.expectedTaints) {
|
||||
t.Errorf("[%s] the result taints should be %v, but got: %v", c.name, c.expectedTaints, taints)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeleteTaintByKey(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
taints []v1.Taint
|
||||
taintKey string
|
||||
expectedTaints []v1.Taint
|
||||
expectedResult bool
|
||||
}{
|
||||
{
|
||||
name: "delete taint unsuccessfully",
|
||||
taints: []v1.Taint{
|
||||
{
|
||||
Key: "foo",
|
||||
Value: "bar",
|
||||
Effect: v1.TaintEffectNoSchedule,
|
||||
},
|
||||
},
|
||||
taintKey: "foo_1",
|
||||
expectedTaints: []v1.Taint{
|
||||
{
|
||||
Key: "foo",
|
||||
Value: "bar",
|
||||
Effect: v1.TaintEffectNoSchedule,
|
||||
},
|
||||
},
|
||||
expectedResult: false,
|
||||
},
|
||||
{
|
||||
name: "delete taint successfully",
|
||||
taints: []v1.Taint{
|
||||
{
|
||||
Key: "foo",
|
||||
Value: "bar",
|
||||
Effect: v1.TaintEffectNoSchedule,
|
||||
},
|
||||
},
|
||||
taintKey: "foo",
|
||||
expectedTaints: []v1.Taint{},
|
||||
expectedResult: true,
|
||||
},
|
||||
{
|
||||
name: "delete taint from empty taint array",
|
||||
taints: []v1.Taint{},
|
||||
taintKey: "foo",
|
||||
expectedTaints: []v1.Taint{},
|
||||
expectedResult: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
taints, result := DeleteTaintsByKey(c.taints, c.taintKey)
|
||||
if result != c.expectedResult {
|
||||
t.Errorf("[%s] should return %t, but got: %t", c.name, c.expectedResult, result)
|
||||
}
|
||||
if !reflect.DeepEqual(c.expectedTaints, taints) {
|
||||
t.Errorf("[%s] the result taints should be %v, but got: %v", c.name, c.expectedTaints, taints)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCheckIfTaintsAlreadyExists(t *testing.T) {
|
||||
oldTaints := []v1.Taint{
|
||||
{
|
||||
Key: "foo_1",
|
||||
Value: "bar",
|
||||
Effect: v1.TaintEffectNoSchedule,
|
||||
},
|
||||
{
|
||||
Key: "foo_2",
|
||||
Value: "bar",
|
||||
Effect: v1.TaintEffectNoSchedule,
|
||||
},
|
||||
{
|
||||
Key: "foo_3",
|
||||
Value: "bar",
|
||||
Effect: v1.TaintEffectNoSchedule,
|
||||
},
|
||||
}
|
||||
|
||||
cases := []struct {
|
||||
name string
|
||||
taintsToCheck []v1.Taint
|
||||
expectedResult string
|
||||
}{
|
||||
{
|
||||
name: "empty array",
|
||||
taintsToCheck: []v1.Taint{},
|
||||
expectedResult: "",
|
||||
},
|
||||
{
|
||||
name: "no match",
|
||||
taintsToCheck: []v1.Taint{
|
||||
{
|
||||
Key: "foo_1",
|
||||
Effect: v1.TaintEffectNoExecute,
|
||||
},
|
||||
},
|
||||
expectedResult: "",
|
||||
},
|
||||
{
|
||||
name: "match one taint",
|
||||
taintsToCheck: []v1.Taint{
|
||||
{
|
||||
Key: "foo_2",
|
||||
Effect: v1.TaintEffectNoSchedule,
|
||||
},
|
||||
},
|
||||
expectedResult: "foo_2",
|
||||
},
|
||||
{
|
||||
name: "match two taints",
|
||||
taintsToCheck: []v1.Taint{
|
||||
{
|
||||
Key: "foo_2",
|
||||
Effect: v1.TaintEffectNoSchedule,
|
||||
},
|
||||
{
|
||||
Key: "foo_3",
|
||||
Effect: v1.TaintEffectNoSchedule,
|
||||
},
|
||||
},
|
||||
expectedResult: "foo_2,foo_3",
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
result := CheckIfTaintsAlreadyExists(oldTaints, c.taintsToCheck)
|
||||
if result != c.expectedResult {
|
||||
t.Errorf("[%s] should return '%s', but got: '%s'", c.name, c.expectedResult, result)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestReorganizeTaints(t *testing.T) {
|
||||
node := &v1.Node{
|
||||
Spec: v1.NodeSpec{
|
||||
Taints: []v1.Taint{
|
||||
{
|
||||
Key: "foo",
|
||||
Value: "bar",
|
||||
Effect: v1.TaintEffectNoSchedule,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
cases := []struct {
|
||||
name string
|
||||
overwrite bool
|
||||
taintsToAdd []v1.Taint
|
||||
taintsToDelete []v1.Taint
|
||||
expectedTaints []v1.Taint
|
||||
expectedOperation string
|
||||
expectedErr bool
|
||||
}{
|
||||
{
|
||||
name: "no changes with overwrite is true",
|
||||
overwrite: true,
|
||||
taintsToAdd: []v1.Taint{},
|
||||
taintsToDelete: []v1.Taint{},
|
||||
expectedTaints: node.Spec.Taints,
|
||||
expectedOperation: MODIFIED,
|
||||
expectedErr: false,
|
||||
},
|
||||
{
|
||||
name: "no changes with overwrite is false",
|
||||
overwrite: false,
|
||||
taintsToAdd: []v1.Taint{},
|
||||
taintsToDelete: []v1.Taint{},
|
||||
expectedTaints: node.Spec.Taints,
|
||||
expectedOperation: UNTAINTED,
|
||||
expectedErr: false,
|
||||
},
|
||||
{
|
||||
name: "add new taint",
|
||||
overwrite: false,
|
||||
taintsToAdd: []v1.Taint{
|
||||
{
|
||||
Key: "foo_1",
|
||||
Effect: v1.TaintEffectNoExecute,
|
||||
},
|
||||
},
|
||||
taintsToDelete: []v1.Taint{},
|
||||
expectedTaints: append([]v1.Taint{{Key: "foo_1", Effect: v1.TaintEffectNoExecute}}, node.Spec.Taints...),
|
||||
expectedOperation: TAINTED,
|
||||
expectedErr: false,
|
||||
},
|
||||
{
|
||||
name: "delete taint with effect",
|
||||
overwrite: false,
|
||||
taintsToAdd: []v1.Taint{},
|
||||
taintsToDelete: []v1.Taint{
|
||||
{
|
||||
Key: "foo",
|
||||
Effect: v1.TaintEffectNoSchedule,
|
||||
},
|
||||
},
|
||||
expectedTaints: []v1.Taint{},
|
||||
expectedOperation: UNTAINTED,
|
||||
expectedErr: false,
|
||||
},
|
||||
{
|
||||
name: "delete taint with no effect",
|
||||
overwrite: false,
|
||||
taintsToAdd: []v1.Taint{},
|
||||
taintsToDelete: []v1.Taint{
|
||||
{
|
||||
Key: "foo",
|
||||
},
|
||||
},
|
||||
expectedTaints: []v1.Taint{},
|
||||
expectedOperation: UNTAINTED,
|
||||
expectedErr: false,
|
||||
},
|
||||
{
|
||||
name: "delete non-exist taint",
|
||||
overwrite: false,
|
||||
taintsToAdd: []v1.Taint{},
|
||||
taintsToDelete: []v1.Taint{
|
||||
{
|
||||
Key: "foo_1",
|
||||
Effect: v1.TaintEffectNoSchedule,
|
||||
},
|
||||
},
|
||||
expectedTaints: node.Spec.Taints,
|
||||
expectedOperation: UNTAINTED,
|
||||
expectedErr: true,
|
||||
},
|
||||
{
|
||||
name: "add new taint and delete old one",
|
||||
overwrite: false,
|
||||
taintsToAdd: []v1.Taint{
|
||||
{
|
||||
Key: "foo_1",
|
||||
Effect: v1.TaintEffectNoSchedule,
|
||||
},
|
||||
},
|
||||
taintsToDelete: []v1.Taint{
|
||||
{
|
||||
Key: "foo",
|
||||
Effect: v1.TaintEffectNoSchedule,
|
||||
},
|
||||
},
|
||||
expectedTaints: []v1.Taint{
|
||||
{
|
||||
Key: "foo_1",
|
||||
Effect: v1.TaintEffectNoSchedule,
|
||||
},
|
||||
},
|
||||
expectedOperation: MODIFIED,
|
||||
expectedErr: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
operation, taints, err := ReorganizeTaints(node, c.overwrite, c.taintsToAdd, c.taintsToDelete)
|
||||
if c.expectedErr && err == nil {
|
||||
t.Errorf("[%s] expect to see an error, but did not get one", c.name)
|
||||
} else if !c.expectedErr && err != nil {
|
||||
t.Errorf("[%s] expect not to see an error, but got one: %v", c.name, err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(c.expectedTaints, taints) {
|
||||
t.Errorf("[%s] expect to see taint list %#v, but got: %#v", c.name, c.expectedTaints, taints)
|
||||
}
|
||||
|
||||
if c.expectedOperation != operation {
|
||||
t.Errorf("[%s] expect to see operation %s, but got: %s", c.name, c.expectedOperation, operation)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseTaints(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
spec []string
|
||||
expectedTaints []v1.Taint
|
||||
expectedTaintsToRemove []v1.Taint
|
||||
expectedErr bool
|
||||
}{
|
||||
{
|
||||
name: "invalid spec format",
|
||||
spec: []string{"foo=abc"},
|
||||
expectedErr: true,
|
||||
},
|
||||
{
|
||||
name: "invalid spec effect for adding taint",
|
||||
spec: []string{"foo=abc:invalid_effect"},
|
||||
expectedErr: true,
|
||||
},
|
||||
{
|
||||
name: "invalid spec effect for deleting taint",
|
||||
spec: []string{"foo:invalid_effect-"},
|
||||
expectedErr: true,
|
||||
},
|
||||
{
|
||||
name: "add new taints",
|
||||
spec: []string{"foo=abc:NoSchedule", "bar=abc:NoSchedule"},
|
||||
expectedTaints: []v1.Taint{
|
||||
{
|
||||
Key: "foo",
|
||||
Value: "abc",
|
||||
Effect: v1.TaintEffectNoSchedule,
|
||||
},
|
||||
{
|
||||
Key: "bar",
|
||||
Value: "abc",
|
||||
Effect: v1.TaintEffectNoSchedule,
|
||||
},
|
||||
},
|
||||
expectedErr: false,
|
||||
},
|
||||
{
|
||||
name: "delete taints",
|
||||
spec: []string{"foo:NoSchedule-", "bar:NoSchedule-"},
|
||||
expectedTaintsToRemove: []v1.Taint{
|
||||
{
|
||||
Key: "foo",
|
||||
Effect: v1.TaintEffectNoSchedule,
|
||||
},
|
||||
{
|
||||
Key: "bar",
|
||||
Effect: v1.TaintEffectNoSchedule,
|
||||
},
|
||||
},
|
||||
expectedErr: false,
|
||||
},
|
||||
{
|
||||
name: "add taints and delete taints",
|
||||
spec: []string{"foo=abc:NoSchedule", "bar=abc:NoSchedule", "foo:NoSchedule-", "bar:NoSchedule-"},
|
||||
expectedTaints: []v1.Taint{
|
||||
{
|
||||
Key: "foo",
|
||||
Value: "abc",
|
||||
Effect: v1.TaintEffectNoSchedule,
|
||||
},
|
||||
{
|
||||
Key: "bar",
|
||||
Value: "abc",
|
||||
Effect: v1.TaintEffectNoSchedule,
|
||||
},
|
||||
},
|
||||
expectedTaintsToRemove: []v1.Taint{
|
||||
{
|
||||
Key: "foo",
|
||||
Effect: v1.TaintEffectNoSchedule,
|
||||
},
|
||||
{
|
||||
Key: "bar",
|
||||
Effect: v1.TaintEffectNoSchedule,
|
||||
},
|
||||
},
|
||||
expectedErr: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
taints, taintsToRemove, err := ParseTaints(c.spec)
|
||||
if c.expectedErr && err == nil {
|
||||
t.Errorf("[%s] expected error, but got nothing", c.name)
|
||||
}
|
||||
if !c.expectedErr && err != nil {
|
||||
t.Errorf("[%s] expected no error, but got: %v", c.name, err)
|
||||
}
|
||||
if !reflect.DeepEqual(c.expectedTaints, taints) {
|
||||
t.Errorf("[%s] expected returen taints as %v, but got: %v", c.name, c.expectedTaints, taints)
|
||||
}
|
||||
if !reflect.DeepEqual(c.expectedTaintsToRemove, taintsToRemove) {
|
||||
t.Errorf("[%s] expected return taints to be removed as %v, but got: %v", c.name, c.expectedTaintsToRemove, taintsToRemove)
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue