From b32687def8d2454b479e90f7f216926003d95cf4 Mon Sep 17 00:00:00 2001 From: YaoZengzeng Date: Wed, 5 Sep 2018 14:41:03 +0800 Subject: [PATCH] bugfix: sort mounts according to the depth of destination path Signed-off-by: YaoZengzeng --- daemon/mgr/spec_mount.go | 31 +++++++++++++++++++++++++- daemon/mgr/spec_mount_test.go | 41 +++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 daemon/mgr/spec_mount_test.go diff --git a/daemon/mgr/spec_mount.go b/daemon/mgr/spec_mount.go index 87ab88ae6..033ba09ab 100644 --- a/daemon/mgr/spec_mount.go +++ b/daemon/mgr/spec_mount.go @@ -4,6 +4,8 @@ import ( "context" "fmt" "os" + "path/filepath" + "sort" "strconv" "github.com/alibaba/pouch/apis/types" @@ -108,7 +110,7 @@ func setupMounts(ctx context.Context, c *Container, s *specs.Spec) error { mounts = append(mounts, generateNetworkMounts(c)...) } - s.Mounts = mounts + s.Mounts = sortMounts(mounts) if c.HostConfig.Privileged { if !s.Root.Readonly { @@ -175,3 +177,30 @@ func trySetupNetworkMount(mount *types.MountPoint, c *Container) bool { return false } + +// mounts defines how to sort specs.Mount. +type mounts []specs.Mount + +// Len returns the number of mounts. +func (m mounts) Len() int { + return len(m) +} + +// Less returns true if the destination of mount i < destination of mount j +// in lexicographic order. +func (m mounts) Less(i, j int) bool { + return filepath.Clean(m[i].Destination) < filepath.Clean(m[j].Destination) +} + +// Swap swaps two items in an array of mounts. +func (m mounts) Swap(i, j int) { + m[i], m[j] = m[j], m[i] +} + +// sortMounts sorts an array of mounts in lexicographic order. This ensure that +// the mount like /etc/resolv.conf will not mount before /etc, so /etc will +// not shadow /etc/resolv.conf +func sortMounts(m []specs.Mount) []specs.Mount { + sort.Stable(mounts(m)) + return m +} diff --git a/daemon/mgr/spec_mount_test.go b/daemon/mgr/spec_mount_test.go new file mode 100644 index 000000000..da78ab927 --- /dev/null +++ b/daemon/mgr/spec_mount_test.go @@ -0,0 +1,41 @@ +package mgr + +import ( + "reflect" + "testing" + + specs "github.com/opencontainers/runtime-spec/specs-go" +) + +func Test_sortMounts(t *testing.T) { + tests := []struct { + name string + args []specs.Mount + want []specs.Mount + }{ + { + "Mounts is nil case", + nil, + nil, + }, + { + "Normal Mounts", + []specs.Mount{ + {Destination: "/etc/resolv.conf"}, + {Destination: "/etc"}, + }, + []specs.Mount{ + {Destination: "/etc"}, + {Destination: "/etc/resolv.conf"}, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := sortMounts(tt.args) + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("sortMounts() = %v, want %v", got, tt.want) + } + }) + } +}