vendor: remove dep and use vndr

Signed-off-by: Antonio Murdaca <runcom@redhat.com>
This commit is contained in:
Antonio Murdaca 2017-06-06 09:19:04 +02:00
parent 16f44674a4
commit 148e72d81e
No known key found for this signature in database
GPG key ID: B2BEAD150DE936B9
16131 changed files with 73815 additions and 4235138 deletions

View file

@ -1,50 +0,0 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_library(
name = "go_default_library",
srcs = [
"doc.go",
"fake.go",
"mount.go",
"mount_linux.go",
"nsenter_mount.go",
],
tags = ["automanaged"],
deps = [
"//pkg/util/exec:go_default_library",
"//vendor:github.com/golang/glog",
"//vendor:k8s.io/apimachinery/pkg/util/sets",
],
)
go_test(
name = "go_default_test",
srcs = [
"mount_linux_test.go",
"safe_format_and_mount_test.go",
],
library = ":go_default_library",
tags = ["automanaged"],
deps = ["//pkg/util/exec:go_default_library"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)

View file

@ -17,6 +17,7 @@ limitations under the License.
package mount
import (
"path/filepath"
"sync"
"github.com/golang/glog"
@ -80,9 +81,15 @@ func (f *FakeMounter) Mount(source string, target string, fstype string, options
}
}
f.MountPoints = append(f.MountPoints, MountPoint{Device: source, Path: target, Type: fstype})
glog.V(5).Infof("Fake mounter: mounted %s to %s", source, target)
f.Log = append(f.Log, FakeAction{Action: FakeActionMount, Target: target, Source: source, FSType: fstype})
// If target is a symlink, get its absolute path
absTarget, err := filepath.EvalSymlinks(target)
if err != nil {
absTarget = target
}
f.MountPoints = append(f.MountPoints, MountPoint{Device: source, Path: absTarget, Type: fstype})
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
}
@ -90,17 +97,23 @@ func (f *FakeMounter) Unmount(target string) error {
f.mutex.Lock()
defer f.mutex.Unlock()
// If target is a symlink, get its absolute path
absTarget, err := filepath.EvalSymlinks(target)
if err != nil {
absTarget = target
}
newMountpoints := []MountPoint{}
for _, mp := range f.MountPoints {
if mp.Path == target {
glog.V(5).Infof("Fake mounter: unmounted %s from %s", mp.Device, target)
if mp.Path == absTarget {
glog.V(5).Infof("Fake mounter: unmounted %s from %s", mp.Device, absTarget)
// Don't copy it to newMountpoints
continue
}
newMountpoints = append(newMountpoints, MountPoint{Device: mp.Device, Path: mp.Path, Type: mp.Type})
}
f.MountPoints = newMountpoints
f.Log = append(f.Log, FakeAction{Action: FakeActionUnmount, Target: target})
f.Log = append(f.Log, FakeAction{Action: FakeActionUnmount, Target: absTarget})
return nil
}
@ -115,13 +128,19 @@ func (f *FakeMounter) IsLikelyNotMountPoint(file string) (bool, error) {
f.mutex.Lock()
defer f.mutex.Unlock()
// If file is a symlink, get its absolute path
absFile, err := filepath.EvalSymlinks(file)
if err != nil {
absFile = file
}
for _, mp := range f.MountPoints {
if mp.Path == file {
glog.V(5).Infof("isLikelyMountPoint for %s: mounted %s, false", file, mp.Path)
if mp.Path == absFile {
glog.V(5).Infof("isLikelyNotMountPoint for %s: mounted %s, false", file, mp.Path)
return false, nil
}
}
glog.V(5).Infof("isLikelyMountPoint for %s: true", file)
glog.V(5).Infof("isLikelyNotMountPoint for %s: true", file)
return true, nil
}

View file

@ -98,11 +98,6 @@ func (mounter *SafeFormatAndMount) FormatAndMount(source string, target string,
// It provides options to override the default mounter behavior.
// mounterPath allows using an alternative to `/bin/mount` for mounting.
func New(mounterPath string) Interface {
// If mounter-path flag is not set, use default mount path
if mounterPath == "" {
mounterPath = defaultMountCommand
}
return &Mounter{
mounterPath: mounterPath,
}

View file

@ -21,7 +21,7 @@ package mount
import (
"bufio"
"fmt"
"hash/adler32"
"hash/fnv"
"io"
"os"
"os/exec"
@ -63,23 +63,23 @@ type Mounter struct {
// currently come from mount(8), e.g. "ro", "remount", "bind", etc. If no more option is
// required, call Mount with an empty string list or nil.
func (mounter *Mounter) Mount(source string, target string, fstype string, options []string) error {
// Path to mounter binary. Set to mount accessible via $PATH by default.
// Path to mounter binary if containerized mounter is needed. Otherwise, it is set to empty.
// All Linux distros are expected to be shipped with a mount utility that an support bind mounts.
mounterPath := defaultMountCommand
mounterPath := ""
bind, bindRemountOpts := isBind(options)
if bind {
err := doMount(mounterPath, source, target, fstype, []string{"bind"})
err := doMount(mounterPath, defaultMountCommand, source, target, fstype, []string{"bind"})
if err != nil {
return err
}
return doMount(mounterPath, source, target, fstype, bindRemountOpts)
return doMount(mounterPath, defaultMountCommand, source, target, fstype, bindRemountOpts)
}
// The list of filesystems that require containerized mounter on GCI image cluster
fsTypesNeedMounter := sets.NewString("nfs", "glusterfs")
fsTypesNeedMounter := sets.NewString("nfs", "glusterfs", "ceph", "cifs")
if fsTypesNeedMounter.Has(fstype) {
mounterPath = mounter.mounterPath
}
return doMount(mounterPath, source, target, fstype, options)
return doMount(mounterPath, defaultMountCommand, source, target, fstype, options)
}
// isBind detects whether a bind mount is being requested and makes the remount options to
@ -107,10 +107,13 @@ func isBind(options []string) (bool, []string) {
return bind, bindRemountOpts
}
// doMount runs the mount command.
func doMount(mountCmd string, source string, target string, fstype string, options []string) error {
glog.V(4).Infof("Mounting %s %s %s %v with command: %q", source, target, fstype, options, mountCmd)
// doMount runs the mount command. mounterPath is the path to mounter binary if containerized mounter is used.
func doMount(mounterPath string, mountCmd string, source string, target string, fstype string, options []string) error {
mountArgs := makeMountArgs(source, target, fstype, options)
if len(mounterPath) > 0 {
mountArgs = append([]string{mountCmd}, mountArgs...)
mountCmd = mounterPath
}
glog.V(4).Infof("Mounting cmd (%s) with arguments (%s)", mountCmd, mountArgs)
command := exec.Command(mountCmd, mountArgs...)
@ -282,7 +285,7 @@ func readProcMounts(mountFilePath string, out *[]MountPoint) (uint32, error) {
}
func readProcMountsFrom(file io.Reader, out *[]MountPoint) (uint32, error) {
hash := adler32.New()
hash := fnv.New32a()
scanner := bufio.NewReader(file)
for {
line, err := scanner.ReadString('\n')
@ -347,17 +350,22 @@ func (mounter *SafeFormatAndMount) formatAndMount(source string, target string,
// Try to mount the disk
glog.V(4).Infof("Attempting to mount disk: %s %s %s", fstype, source, target)
err = mounter.Interface.Mount(source, target, fstype, options)
if err != nil {
// It is possible that this disk is not formatted. Double check using diskLooksUnformatted
notFormatted, err := mounter.diskLooksUnformatted(source)
if err == nil && notFormatted {
args = []string{source}
mountErr := mounter.Interface.Mount(source, target, fstype, options)
if mountErr != nil {
// Mount failed. This indicates either that the disk is unformatted or
// it contains an unexpected filesystem.
existingFormat, err := mounter.getDiskFormat(source)
if err != nil {
return err
}
if existingFormat == "" {
// Disk is unformatted so format it.
args = []string{source}
// Use 'ext4' as the default
if len(fstype) == 0 {
fstype = "ext4"
}
if fstype == "ext4" || fstype == "ext3" {
args = []string{"-F", source}
}
@ -371,13 +379,22 @@ func (mounter *SafeFormatAndMount) formatAndMount(source string, target string,
}
glog.Errorf("format of disk %q failed: type:(%q) target:(%q) options:(%q)error:(%v)", source, fstype, target, options, err)
return err
} else {
// Disk is already formatted and failed to mount
if len(fstype) == 0 || fstype == existingFormat {
// This is mount error
return mountErr
} else {
// Block device is formatted with unexpected filesystem, let the user know
return fmt.Errorf("failed to mount the volume as %q, it's already formatted with %q. Mount error: %v", fstype, existingFormat, mountErr)
}
}
}
return err
return mountErr
}
// diskLooksUnformatted uses 'lsblk' to see if the given disk is unformated
func (mounter *SafeFormatAndMount) diskLooksUnformatted(disk string) (bool, error) {
func (mounter *SafeFormatAndMount) getDiskFormat(disk string) (string, error) {
args := []string{"-nd", "-o", "FSTYPE", disk}
cmd := mounter.Runner.Command("lsblk", args...)
glog.V(4).Infof("Attempting to determine if disk %q is formatted using lsblk with args: (%v)", disk, args)
@ -389,8 +406,8 @@ func (mounter *SafeFormatAndMount) diskLooksUnformatted(disk string) (bool, erro
if err != nil {
glog.Errorf("Could not determine if disk %q is formatted (%v)", disk, err)
return false, err
return "", err
}
return output == "", nil
return strings.TrimSpace(output), nil
}

View file

@ -1,182 +0,0 @@
// +build linux
/*
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 (
"strings"
"testing"
)
func TestReadProcMountsFrom(t *testing.T) {
successCase :=
`/dev/0 /path/to/0 type0 flags 0 0
/dev/1 /path/to/1 type1 flags 1 1
/dev/2 /path/to/2 type2 flags,1,2=3 2 2
`
hash, err := readProcMountsFrom(strings.NewReader(successCase), nil)
if err != nil {
t.Errorf("expected success")
}
if hash != 0xa3522051 {
t.Errorf("expected 0xa3522051, got %#x", hash)
}
mounts := []MountPoint{}
hash, err = readProcMountsFrom(strings.NewReader(successCase), &mounts)
if err != nil {
t.Errorf("expected success")
}
if hash != 0xa3522051 {
t.Errorf("expected 0xa3522051, got %#x", hash)
}
if len(mounts) != 3 {
t.Fatalf("expected 3 mounts, got %d", len(mounts))
}
mp := MountPoint{"/dev/0", "/path/to/0", "type0", []string{"flags"}, 0, 0}
if !mountPointsEqual(&mounts[0], &mp) {
t.Errorf("got unexpected MountPoint[0]: %#v", mounts[0])
}
mp = MountPoint{"/dev/1", "/path/to/1", "type1", []string{"flags"}, 1, 1}
if !mountPointsEqual(&mounts[1], &mp) {
t.Errorf("got unexpected MountPoint[1]: %#v", mounts[1])
}
mp = MountPoint{"/dev/2", "/path/to/2", "type2", []string{"flags", "1", "2=3"}, 2, 2}
if !mountPointsEqual(&mounts[2], &mp) {
t.Errorf("got unexpected MountPoint[2]: %#v", mounts[2])
}
errorCases := []string{
"/dev/0 /path/to/mount\n",
"/dev/1 /path/to/mount type flags a 0\n",
"/dev/2 /path/to/mount type flags 0 b\n",
}
for _, ec := range errorCases {
_, err := readProcMountsFrom(strings.NewReader(ec), &mounts)
if err == nil {
t.Errorf("expected error")
}
}
}
func mountPointsEqual(a, b *MountPoint) bool {
if a.Device != b.Device || a.Path != b.Path || a.Type != b.Type || !slicesEqual(a.Opts, b.Opts) || a.Pass != b.Pass || a.Freq != b.Freq {
return false
}
return true
}
func slicesEqual(a, b []string) bool {
if len(a) != len(b) {
return false
}
for i := range a {
if a[i] != b[i] {
return false
}
}
return true
}
func TestGetMountRefs(t *testing.T) {
fm := &FakeMounter{
MountPoints: []MountPoint{
{Device: "/dev/sdb", Path: "/var/lib/kubelet/plugins/kubernetes.io/gce-pd/mounts/gce-pd"},
{Device: "/dev/sdb", Path: "/var/lib/kubelet/pods/some-pod/volumes/kubernetes.io~gce-pd/gce-pd-in-pod"},
{Device: "/dev/sdc", Path: "/var/lib/kubelet/plugins/kubernetes.io/gce-pd/mounts/gce-pd2"},
{Device: "/dev/sdc", Path: "/var/lib/kubelet/pods/some-pod/volumes/kubernetes.io~gce-pd/gce-pd2-in-pod1"},
{Device: "/dev/sdc", Path: "/var/lib/kubelet/pods/some-pod/volumes/kubernetes.io~gce-pd/gce-pd2-in-pod2"},
},
}
tests := []struct {
mountPath string
expectedRefs []string
}{
{
"/var/lib/kubelet/pods/some-pod/volumes/kubernetes.io~gce-pd/gce-pd-in-pod",
[]string{
"/var/lib/kubelet/plugins/kubernetes.io/gce-pd/mounts/gce-pd",
},
},
{
"/var/lib/kubelet/pods/some-pod/volumes/kubernetes.io~gce-pd/gce-pd2-in-pod1",
[]string{
"/var/lib/kubelet/pods/some-pod/volumes/kubernetes.io~gce-pd/gce-pd2-in-pod2",
"/var/lib/kubelet/plugins/kubernetes.io/gce-pd/mounts/gce-pd2",
},
},
}
for i, test := range tests {
if refs, err := GetMountRefs(fm, test.mountPath); err != nil || !setEquivalent(test.expectedRefs, refs) {
t.Errorf("%d. getMountRefs(%q) = %v, %v; expected %v, nil", i, test.mountPath, refs, err, test.expectedRefs)
}
}
}
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
}
func TestGetDeviceNameFromMount(t *testing.T) {
fm := &FakeMounter{
MountPoints: []MountPoint{
{Device: "/dev/disk/by-path/prefix-lun-1",
Path: "/mnt/111"},
{Device: "/dev/disk/by-path/prefix-lun-1",
Path: "/mnt/222"},
},
}
tests := []struct {
mountPath string
expectedDevice string
expectedRefs int
}{
{
"/mnt/222",
"/dev/disk/by-path/prefix-lun-1",
2,
},
}
for i, test := range tests {
if device, refs, err := GetDeviceNameFromMount(fm, test.mountPath); err != nil || test.expectedRefs != refs || test.expectedDevice != device {
t.Errorf("%d. GetDeviceNameFromMount(%s) = (%s, %d), %v; expected (%s,%d), nil", i, test.mountPath, device, refs, err, test.expectedDevice, test.expectedRefs)
}
}
}

View file

@ -1,224 +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"
"runtime"
"testing"
"k8s.io/kubernetes/pkg/util/exec"
)
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)
}
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"}, "", &exec.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"}, "", &exec.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"}, "", &exec.FakeExitError{Status: 8}},
},
},
{
description: "Test that 'lsblk' is called and fails",
fstype: "ext4",
mountErrs: []error{fmt.Errorf("unknown filesystem type '(null)'")},
execScripts: []ExecArgs{
{"fsck", []string{"-a", "/dev/foo"}, "", nil},
{"lsblk", []string{"-nd", "-o", "FSTYPE", "/dev/foo"}, "ext4", nil},
},
expectedError: fmt.Errorf("unknown filesystem type '(null)'"),
},
{
description: "Test that 'lsblk' 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},
{"lsblk", []string{"-nd", "-o", "FSTYPE", "/dev/foo"}, "", nil},
{"mkfs.ext4", []string{"-F", "/dev/foo"}, "", fmt.Errorf("formatting failed")},
},
expectedError: fmt.Errorf("formatting failed"),
},
{
description: "Test that 'lsblk' 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},
{"lsblk", []string{"-nd", "-o", "FSTYPE", "/dev/foo"}, "", nil},
{"mkfs.ext4", []string{"-F", "/dev/foo"}, "", nil},
},
expectedError: fmt.Errorf("Still cannot mount"),
},
{
description: "Test that 'lsblk' 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},
{"lsblk", []string{"-nd", "-o", "FSTYPE", "/dev/foo"}, "", nil},
{"mkfs.ext4", []string{"-F", "/dev/foo"}, "", nil},
},
expectedError: nil,
},
{
description: "Test that 'lsblk' 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},
{"lsblk", []string{"-nd", "-o", "FSTYPE", "/dev/foo"}, "", nil},
{"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},
{"lsblk", []string{"-nd", "-o", "FSTYPE", "/dev/foo"}, "", nil},
{"mkfs.xfs", []string{"/dev/foo"}, "", nil},
},
expectedError: nil,
},
}
for _, test := range tests {
commandScripts := []exec.FakeCommandAction{}
for _, expected := range test.execScripts {
ecmd := expected.command
eargs := expected.args
output := expected.output
err := expected.err
commandScript := func(cmd string, args ...string) exec.Cmd {
if cmd != ecmd {
t.Errorf("Unexpected command %s. Expecting %s", cmd, ecmd)
}
for j := range args {
if args[j] != eargs[j] {
t.Errorf("Unexpected args %v. Expecting %v", args, eargs)
}
}
fake := exec.FakeCmd{
CombinedOutputScript: []exec.FakeCombinedOutputAction{
func() ([]byte, error) { return []byte(output), err },
},
}
return exec.InitFakeCmd(&fake, cmd, args...)
}
commandScripts = append(commandScripts, commandScript)
}
fake := exec.FakeExec{
CommandScript: commandScripts,
}
fakeMounter := ErrorMounter{&FakeMounter{}, 0, test.mountErrs}
mounter := SafeFormatAndMount{
Interface: &fakeMounter,
Runner: &fake,
}
device := "/dev/foo"
dest := "/mnt/bar"
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)
}
}
}
}