Move resolveSymbolicLink to OS package and stub out for tests

Signed-off-by: Ian Campbell <ijc@docker.com>
This commit is contained in:
Ian Campbell 2017-09-15 10:53:57 +01:00
parent 56539bd3a4
commit e0079125d2
4 changed files with 42 additions and 27 deletions

View File

@ -20,6 +20,7 @@ import (
"io" "io"
"io/ioutil" "io/ioutil"
"os" "os"
"path/filepath"
"github.com/containerd/fifo" "github.com/containerd/fifo"
"github.com/docker/docker/pkg/mount" "github.com/docker/docker/pkg/mount"
@ -34,6 +35,7 @@ type OS interface {
RemoveAll(path string) error RemoveAll(path string) error
OpenFifo(ctx context.Context, fn string, flag int, perm os.FileMode) (io.ReadWriteCloser, error) OpenFifo(ctx context.Context, fn string, flag int, perm os.FileMode) (io.ReadWriteCloser, error)
Stat(name string) (os.FileInfo, error) Stat(name string) (os.FileInfo, error)
ResolveSymbolicLink(name string) (string, error)
CopyFile(src, dest string, perm os.FileMode) error CopyFile(src, dest string, perm os.FileMode) error
WriteFile(filename string, data []byte, perm os.FileMode) error WriteFile(filename string, data []byte, perm os.FileMode) error
Mount(source string, target string, fstype string, flags uintptr, data string) error Mount(source string, target string, fstype string, flags uintptr, data string) error
@ -63,6 +65,18 @@ func (RealOS) Stat(name string) (os.FileInfo, error) {
return os.Stat(name) return os.Stat(name)
} }
// ResolveSymbolicLink will follow any symbolic links
func (RealOS) ResolveSymbolicLink(path string) (string, error) {
info, err := os.Lstat(path)
if err != nil {
return "", err
}
if info.Mode()&os.ModeSymlink != os.ModeSymlink {
return path, nil
}
return filepath.EvalSymlinks(path)
}
// CopyFile copys src file to dest file // CopyFile copys src file to dest file
func (RealOS) CopyFile(src, dest string, perm os.FileMode) error { func (RealOS) CopyFile(src, dest string, perm os.FileMode) error {
in, err := os.Open(src) in, err := os.Open(src)

View File

@ -43,6 +43,7 @@ type FakeOS struct {
RemoveAllFn func(string) error RemoveAllFn func(string) error
OpenFifoFn func(context.Context, string, int, os.FileMode) (io.ReadWriteCloser, error) OpenFifoFn func(context.Context, string, int, os.FileMode) (io.ReadWriteCloser, error)
StatFn func(string) (os.FileInfo, error) StatFn func(string) (os.FileInfo, error)
ResolveSymbolicLinkFn func(string) (string, error)
CopyFileFn func(string, string, os.FileMode) error CopyFileFn func(string, string, os.FileMode) error
WriteFileFn func(string, []byte, os.FileMode) error WriteFileFn func(string, []byte, os.FileMode) error
MountFn func(source string, target string, fstype string, flags uintptr, data string) error MountFn func(source string, target string, fstype string, flags uintptr, data string) error
@ -160,6 +161,19 @@ func (f *FakeOS) Stat(name string) (os.FileInfo, error) {
return nil, nil return nil, nil
} }
// ResolveSymbolicLink is a fake call that invokes ResolveSymbolicLinkFn or returns its input
func (f *FakeOS) ResolveSymbolicLink(path string) (string, error) {
f.appendCalls("ResolveSymbolicLink", path)
if err := f.getError("ResolveSymbolicLink"); err != nil {
return "", err
}
if f.ResolveSymbolicLinkFn != nil {
return f.ResolveSymbolicLinkFn(path)
}
return path, nil
}
// CopyFile is a fake call that invokes CopyFileFn or just return nil. // CopyFile is a fake call that invokes CopyFileFn or just return nil.
func (f *FakeOS) CopyFile(src, dest string, perm os.FileMode) error { func (f *FakeOS) CopyFile(src, dest string, perm os.FileMode) error {
f.appendCalls("CopyFile", src, dest, perm) f.appendCalls("CopyFile", src, dest, perm)

View File

@ -289,7 +289,7 @@ func (c *criContainerdService) generateContainerSpec(id string, sandboxPid uint3
return nil, err return nil, err
} }
} else { } else {
if err := addOCIDevices(&g, config.GetDevices()); err != nil { if err := c.addOCIDevices(&g, config.GetDevices()); err != nil {
return nil, fmt.Errorf("failed to set devices mapping %+v: %v", config.GetDevices(), err) return nil, fmt.Errorf("failed to set devices mapping %+v: %v", config.GetDevices(), err)
} }
@ -414,10 +414,10 @@ func clearReadOnly(m *runtimespec.Mount) {
} }
// addDevices set device mapping without privilege. // addDevices set device mapping without privilege.
func addOCIDevices(g *generate.Generator, devs []*runtime.Device) error { func (c *criContainerdService) addOCIDevices(g *generate.Generator, devs []*runtime.Device) error {
spec := g.Spec() spec := g.Spec()
for _, device := range devs { for _, device := range devs {
path, err := resolveSymbolicLink(device.HostPath) path, err := c.os.ResolveSymbolicLink(device.HostPath)
if err != nil { if err != nil {
return err return err
} }
@ -497,7 +497,7 @@ func addOCIBindMounts(g *generate.Generator, mounts []*runtime.Mount, mountLabel
} }
// TODO(random-liu): Add cri-containerd integration test or cri validation test // TODO(random-liu): Add cri-containerd integration test or cri validation test
// for this. // for this.
src, err := resolveSymbolicLink(src) src, err := c.os.ResolveSymbolicLink(src)
if err != nil { if err != nil {
return fmt.Errorf("failed to resolve symlink %q: %v", src, err) return fmt.Errorf("failed to resolve symlink %q: %v", src, err)
} }

View File

@ -297,19 +297,6 @@ func (c *criContainerdService) ensureImageExists(ctx context.Context, ref string
return &newImage, nil return &newImage, nil
} }
// resolveSymbolicLink resolves a possbile symlink path. If the path is a symlink, returns resolved
// path; if not, returns the original path.
func resolveSymbolicLink(path string) (string, error) {
info, err := os.Lstat(path)
if err != nil {
return "", err
}
if info.Mode()&os.ModeSymlink != os.ModeSymlink {
return path, nil
}
return filepath.EvalSymlinks(path)
}
// loadCgroup loads the cgroup associated with path if it exists and moves the current process into the cgroup. If the cgroup // loadCgroup loads the cgroup associated with path if it exists and moves the current process into the cgroup. If the cgroup
// is not created it is created and returned. // is not created it is created and returned.
func loadCgroup(cgroupPath string) (cgroups.Cgroup, error) { func loadCgroup(cgroupPath string) (cgroups.Cgroup, error) {