Skip to content

Commit

Permalink
Move resolveSymbolicLink to OS package and stub out for tests
Browse files Browse the repository at this point in the history
Signed-off-by: Ian Campbell <ijc@docker.com>
  • Loading branch information
ijc committed Sep 15, 2017
1 parent 56539bd commit e007912
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 27 deletions.
14 changes: 14 additions & 0 deletions pkg/os/os.go
Expand Up @@ -20,6 +20,7 @@ import (
"io"
"io/ioutil"
"os"
"path/filepath"

"github.com/containerd/fifo"
"github.com/docker/docker/pkg/mount"
Expand All @@ -34,6 +35,7 @@ type OS interface {
RemoveAll(path string) error
OpenFifo(ctx context.Context, fn string, flag int, perm os.FileMode) (io.ReadWriteCloser, error)
Stat(name string) (os.FileInfo, error)
ResolveSymbolicLink(name string) (string, error)
CopyFile(src, dest string, 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
Expand Down Expand Up @@ -63,6 +65,18 @@ func (RealOS) Stat(name string) (os.FileInfo, error) {
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
func (RealOS) CopyFile(src, dest string, perm os.FileMode) error {
in, err := os.Open(src)
Expand Down
34 changes: 24 additions & 10 deletions pkg/os/testing/fake_os.go
Expand Up @@ -39,16 +39,17 @@ type CalledDetail struct {
// of the real call.
type FakeOS struct {
sync.Mutex
MkdirAllFn func(string, os.FileMode) error
RemoveAllFn func(string) error
OpenFifoFn func(context.Context, string, int, os.FileMode) (io.ReadWriteCloser, error)
StatFn func(string) (os.FileInfo, error)
CopyFileFn func(string, string, os.FileMode) error
WriteFileFn func(string, []byte, os.FileMode) error
MountFn func(source string, target string, fstype string, flags uintptr, data string) error
UnmountFn func(target string, flags int) error
calls []CalledDetail
errors map[string]error
MkdirAllFn func(string, os.FileMode) error
RemoveAllFn func(string) error
OpenFifoFn func(context.Context, string, int, os.FileMode) (io.ReadWriteCloser, error)
StatFn func(string) (os.FileInfo, error)
ResolveSymbolicLinkFn func(string) (string, error)
CopyFileFn func(string, string, os.FileMode) error
WriteFileFn func(string, []byte, os.FileMode) error
MountFn func(source string, target string, fstype string, flags uintptr, data string) error
UnmountFn func(target string, flags int) error
calls []CalledDetail
errors map[string]error
}

var _ osInterface.OS = &FakeOS{}
Expand Down Expand Up @@ -160,6 +161,19 @@ func (f *FakeOS) Stat(name string) (os.FileInfo, error) {
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.
func (f *FakeOS) CopyFile(src, dest string, perm os.FileMode) error {
f.appendCalls("CopyFile", src, dest, perm)
Expand Down
8 changes: 4 additions & 4 deletions pkg/server/container_create.go
Expand Up @@ -289,7 +289,7 @@ func (c *criContainerdService) generateContainerSpec(id string, sandboxPid uint3
return nil, err
}
} 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)
}

Expand Down Expand Up @@ -414,10 +414,10 @@ func clearReadOnly(m *runtimespec.Mount) {
}

// 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()
for _, device := range devs {
path, err := resolveSymbolicLink(device.HostPath)
path, err := c.os.ResolveSymbolicLink(device.HostPath)
if err != nil {
return err
}
Expand Down Expand Up @@ -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
// for this.
src, err := resolveSymbolicLink(src)
src, err := c.os.ResolveSymbolicLink(src)
if err != nil {
return fmt.Errorf("failed to resolve symlink %q: %v", src, err)
}
Expand Down
13 changes: 0 additions & 13 deletions pkg/server/helpers.go
Expand Up @@ -297,19 +297,6 @@ func (c *criContainerdService) ensureImageExists(ctx context.Context, ref string
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
// is not created it is created and returned.
func loadCgroup(cgroupPath string) (cgroups.Cgroup, error) {
Expand Down

0 comments on commit e007912

Please sign in to comment.