Browse code

Fix vfs unit test and port VFS to the new IDMappings

The test was failing because TarOptions was using a non-pointer for
ChownOpts, which meant the check for nil was never true, and
createTarFile was never using the hdr.UID/GID

Signed-off-by: Daniel Nephin <dnephin@docker.com>

Daniel Nephin authored on 2017/05/25 05:25:13
Showing 6 changed files
... ...
@@ -20,6 +20,6 @@ func (daemon *Daemon) tarCopyOptions(container *container.Container, noOverwrite
20 20
 
21 21
 	return &archive.TarOptions{
22 22
 		NoOverwriteDirNonDir: noOverwriteDirNonDir,
23
-		ChownOpts:            idtools.IDPair{UID: user.Uid, GID: user.Gid},
23
+		ChownOpts:            &idtools.IDPair{UID: user.Uid, GID: user.Gid},
24 24
 	}, nil
25 25
 }
... ...
@@ -4,6 +4,8 @@ package devmapper
4 4
 
5 5
 import (
6 6
 	"fmt"
7
+	"os"
8
+	"syscall"
7 9
 	"testing"
8 10
 	"time"
9 11
 
... ...
@@ -17,11 +19,51 @@ func init() {
17 17
 	defaultMetaDataLoopbackSize = 200 * 1024 * 1024
18 18
 	defaultBaseFsSize = 300 * 1024 * 1024
19 19
 	defaultUdevSyncOverride = true
20
-	if err := graphtest.InitLoopbacks(); err != nil {
20
+	if err := initLoopbacks(); err != nil {
21 21
 		panic(err)
22 22
 	}
23 23
 }
24 24
 
25
+// initLoopbacks ensures that the loopback devices are properly created within
26
+// the system running the device mapper tests.
27
+func initLoopbacks() error {
28
+	statT, err := getBaseLoopStats()
29
+	if err != nil {
30
+		return err
31
+	}
32
+	// create at least 8 loopback files, ya, that is a good number
33
+	for i := 0; i < 8; i++ {
34
+		loopPath := fmt.Sprintf("/dev/loop%d", i)
35
+		// only create new loopback files if they don't exist
36
+		if _, err := os.Stat(loopPath); err != nil {
37
+			if mkerr := syscall.Mknod(loopPath,
38
+				uint32(statT.Mode|syscall.S_IFBLK), int((7<<8)|(i&0xff)|((i&0xfff00)<<12))); mkerr != nil {
39
+				return mkerr
40
+			}
41
+			os.Chown(loopPath, int(statT.Uid), int(statT.Gid))
42
+		}
43
+	}
44
+	return nil
45
+}
46
+
47
+// getBaseLoopStats inspects /dev/loop0 to collect uid,gid, and mode for the
48
+// loop0 device on the system.  If it does not exist we assume 0,0,0660 for the
49
+// stat data
50
+func getBaseLoopStats() (*syscall.Stat_t, error) {
51
+	loop0, err := os.Stat("/dev/loop0")
52
+	if err != nil {
53
+		if os.IsNotExist(err) {
54
+			return &syscall.Stat_t{
55
+				Uid:  0,
56
+				Gid:  0,
57
+				Mode: 0660,
58
+			}, nil
59
+		}
60
+		return nil, err
61
+	}
62
+	return loop0.Sys().(*syscall.Stat_t), nil
63
+}
64
+
25 65
 // This avoids creating a new driver for each test if all tests are run
26 66
 // Make sure to put new tests between TestDevmapperSetup and TestDevmapperTeardown
27 67
 func TestDevmapperSetup(t *testing.T) {
... ...
@@ -16,6 +16,8 @@ import (
16 16
 	"github.com/docker/docker/daemon/graphdriver"
17 17
 	"github.com/docker/docker/pkg/stringid"
18 18
 	"github.com/docker/go-units"
19
+	"github.com/stretchr/testify/assert"
20
+	"github.com/stretchr/testify/require"
19 21
 )
20 22
 
21 23
 var (
... ...
@@ -33,14 +35,9 @@ type Driver struct {
33 33
 
34 34
 func newDriver(t testing.TB, name string, options []string) *Driver {
35 35
 	root, err := ioutil.TempDir("", "docker-graphtest-")
36
-	if err != nil {
37
-		t.Fatal(err)
38
-	}
39
-
40
-	if err := os.MkdirAll(root, 0755); err != nil {
41
-		t.Fatal(err)
42
-	}
36
+	require.NoError(t, err)
43 37
 
38
+	require.NoError(t, os.MkdirAll(root, 0755))
44 39
 	d, err := graphdriver.GetDriver(name, nil, graphdriver.Options{DriverOptions: options, Root: root})
45 40
 	if err != nil {
46 41
 		t.Logf("graphdriver: %v\n", err)
... ...
@@ -86,14 +83,11 @@ func DriverTestCreateEmpty(t testing.TB, drivername string, driverOptions ...str
86 86
 	driver := GetDriver(t, drivername, driverOptions...)
87 87
 	defer PutDriver(t)
88 88
 
89
-	if err := driver.Create("empty", "", nil); err != nil {
90
-		t.Fatal(err)
91
-	}
89
+	err := driver.Create("empty", "", nil)
90
+	require.NoError(t, err)
92 91
 
93 92
 	defer func() {
94
-		if err := driver.Remove("empty"); err != nil {
95
-			t.Fatal(err)
96
-		}
93
+		require.NoError(t, driver.Remove("empty"))
97 94
 	}()
98 95
 
99 96
 	if !driver.Exists("empty") {
... ...
@@ -101,21 +95,14 @@ func DriverTestCreateEmpty(t testing.TB, drivername string, driverOptions ...str
101 101
 	}
102 102
 
103 103
 	dir, err := driver.Get("empty", "")
104
-	if err != nil {
105
-		t.Fatal(err)
106
-	}
104
+	require.NoError(t, err)
107 105
 
108 106
 	verifyFile(t, dir, 0755|os.ModeDir, 0, 0)
109 107
 
110 108
 	// Verify that the directory is empty
111 109
 	fis, err := readDir(dir)
112
-	if err != nil {
113
-		t.Fatal(err)
114
-	}
115
-
116
-	if len(fis) != 0 {
117
-		t.Fatal("New directory not empty")
118
-	}
110
+	require.NoError(t, err)
111
+	assert.Len(t, fis, 0)
119 112
 
120 113
 	driver.Put("empty")
121 114
 }
... ...
@@ -127,9 +114,7 @@ func DriverTestCreateBase(t testing.TB, drivername string, driverOptions ...stri
127 127
 
128 128
 	createBase(t, driver, "Base")
129 129
 	defer func() {
130
-		if err := driver.Remove("Base"); err != nil {
131
-			t.Fatal(err)
132
-		}
130
+		require.NoError(t, driver.Remove("Base"))
133 131
 	}()
134 132
 	verifyBase(t, driver, "Base")
135 133
 }
... ...
@@ -140,21 +125,14 @@ func DriverTestCreateSnap(t testing.TB, drivername string, driverOptions ...stri
140 140
 	defer PutDriver(t)
141 141
 
142 142
 	createBase(t, driver, "Base")
143
-
144 143
 	defer func() {
145
-		if err := driver.Remove("Base"); err != nil {
146
-			t.Fatal(err)
147
-		}
144
+		require.NoError(t, driver.Remove("Base"))
148 145
 	}()
149 146
 
150
-	if err := driver.Create("Snap", "Base", nil); err != nil {
151
-		t.Fatal(err)
152
-	}
153
-
147
+	err := driver.Create("Snap", "Base", nil)
148
+	require.NoError(t, err)
154 149
 	defer func() {
155
-		if err := driver.Remove("Snap"); err != nil {
156
-			t.Fatal(err)
157
-		}
150
+		require.NoError(t, driver.Remove("Snap"))
158 151
 	}()
159 152
 
160 153
 	verifyBase(t, driver, "Snap")
... ...
@@ -3,7 +3,6 @@
3 3
 package graphtest
4 4
 
5 5
 import (
6
-	"fmt"
7 6
 	"io/ioutil"
8 7
 	"os"
9 8
 	"path"
... ...
@@ -11,81 +10,24 @@ import (
11 11
 	"testing"
12 12
 
13 13
 	"github.com/docker/docker/daemon/graphdriver"
14
+	"github.com/stretchr/testify/assert"
15
+	"github.com/stretchr/testify/require"
14 16
 )
15 17
 
16
-// InitLoopbacks ensures that the loopback devices are properly created within
17
-// the system running the device mapper tests.
18
-func InitLoopbacks() error {
19
-	statT, err := getBaseLoopStats()
20
-	if err != nil {
21
-		return err
22
-	}
23
-	// create at least 8 loopback files, ya, that is a good number
24
-	for i := 0; i < 8; i++ {
25
-		loopPath := fmt.Sprintf("/dev/loop%d", i)
26
-		// only create new loopback files if they don't exist
27
-		if _, err := os.Stat(loopPath); err != nil {
28
-			if mkerr := syscall.Mknod(loopPath,
29
-				uint32(statT.Mode|syscall.S_IFBLK), int((7<<8)|(i&0xff)|((i&0xfff00)<<12))); mkerr != nil {
30
-				return mkerr
31
-			}
32
-			os.Chown(loopPath, int(statT.Uid), int(statT.Gid))
33
-		}
34
-	}
35
-	return nil
36
-}
37
-
38
-// getBaseLoopStats inspects /dev/loop0 to collect uid,gid, and mode for the
39
-// loop0 device on the system.  If it does not exist we assume 0,0,0660 for the
40
-// stat data
41
-func getBaseLoopStats() (*syscall.Stat_t, error) {
42
-	loop0, err := os.Stat("/dev/loop0")
43
-	if err != nil {
44
-		if os.IsNotExist(err) {
45
-			return &syscall.Stat_t{
46
-				Uid:  0,
47
-				Gid:  0,
48
-				Mode: 0660,
49
-			}, nil
50
-		}
51
-		return nil, err
52
-	}
53
-	return loop0.Sys().(*syscall.Stat_t), nil
54
-}
55
-
56 18
 func verifyFile(t testing.TB, path string, mode os.FileMode, uid, gid uint32) {
57 19
 	fi, err := os.Stat(path)
58
-	if err != nil {
59
-		t.Fatal(err)
60
-	}
61
-
62
-	if fi.Mode()&os.ModeType != mode&os.ModeType {
63
-		t.Fatalf("Expected %s type 0x%x, got 0x%x", path, mode&os.ModeType, fi.Mode()&os.ModeType)
64
-	}
20
+	require.NoError(t, err)
65 21
 
66
-	if fi.Mode()&os.ModePerm != mode&os.ModePerm {
67
-		t.Fatalf("Expected %s mode %o, got %o", path, mode&os.ModePerm, fi.Mode()&os.ModePerm)
68
-	}
69
-
70
-	if fi.Mode()&os.ModeSticky != mode&os.ModeSticky {
71
-		t.Fatalf("Expected %s sticky 0x%x, got 0x%x", path, mode&os.ModeSticky, fi.Mode()&os.ModeSticky)
72
-	}
73
-
74
-	if fi.Mode()&os.ModeSetuid != mode&os.ModeSetuid {
75
-		t.Fatalf("Expected %s setuid 0x%x, got 0x%x", path, mode&os.ModeSetuid, fi.Mode()&os.ModeSetuid)
76
-	}
77
-
78
-	if fi.Mode()&os.ModeSetgid != mode&os.ModeSetgid {
79
-		t.Fatalf("Expected %s setgid 0x%x, got 0x%x", path, mode&os.ModeSetgid, fi.Mode()&os.ModeSetgid)
80
-	}
22
+	actual := fi.Mode()
23
+	assert.Equal(t, mode&os.ModeType, actual&os.ModeType, path)
24
+	assert.Equal(t, mode&os.ModePerm, actual&os.ModePerm, path)
25
+	assert.Equal(t, mode&os.ModeSticky, actual&os.ModeSticky, path)
26
+	assert.Equal(t, mode&os.ModeSetuid, actual&os.ModeSetuid, path)
27
+	assert.Equal(t, mode&os.ModeSetgid, actual&os.ModeSetgid, path)
81 28
 
82 29
 	if stat, ok := fi.Sys().(*syscall.Stat_t); ok {
83
-		if stat.Uid != uid {
84
-			t.Fatalf("%s no owned by uid %d", path, uid)
85
-		}
86
-		if stat.Gid != gid {
87
-			t.Fatalf("%s not owned by gid %d", path, gid)
88
-		}
30
+		assert.Equal(t, uid, stat.Uid, path)
31
+		assert.Equal(t, gid, stat.Gid, path)
89 32
 	}
90 33
 }
91 34
 
... ...
@@ -94,35 +36,25 @@ func createBase(t testing.TB, driver graphdriver.Driver, name string) {
94 94
 	oldmask := syscall.Umask(0)
95 95
 	defer syscall.Umask(oldmask)
96 96
 
97
-	if err := driver.CreateReadWrite(name, "", nil); err != nil {
98
-		t.Fatal(err)
99
-	}
97
+	err := driver.CreateReadWrite(name, "", nil)
98
+	require.NoError(t, err)
100 99
 
101 100
 	dir, err := driver.Get(name, "")
102
-	if err != nil {
103
-		t.Fatal(err)
104
-	}
101
+	require.NoError(t, err)
105 102
 	defer driver.Put(name)
106 103
 
107 104
 	subdir := path.Join(dir, "a subdir")
108
-	if err := os.Mkdir(subdir, 0705|os.ModeSticky); err != nil {
109
-		t.Fatal(err)
110
-	}
111
-	if err := os.Chown(subdir, 1, 2); err != nil {
112
-		t.Fatal(err)
113
-	}
105
+	require.NoError(t, os.Mkdir(subdir, 0705|os.ModeSticky))
106
+	require.NoError(t, os.Chown(subdir, 1, 2))
114 107
 
115 108
 	file := path.Join(dir, "a file")
116
-	if err := ioutil.WriteFile(file, []byte("Some data"), 0222|os.ModeSetuid); err != nil {
117
-		t.Fatal(err)
118
-	}
109
+	err = ioutil.WriteFile(file, []byte("Some data"), 0222|os.ModeSetuid)
110
+	require.NoError(t, err)
119 111
 }
120 112
 
121 113
 func verifyBase(t testing.TB, driver graphdriver.Driver, name string) {
122 114
 	dir, err := driver.Get(name, "")
123
-	if err != nil {
124
-		t.Fatal(err)
125
-	}
115
+	require.NoError(t, err)
126 116
 	defer driver.Put(name)
127 117
 
128 118
 	subdir := path.Join(dir, "a subdir")
... ...
@@ -131,13 +63,7 @@ func verifyBase(t testing.TB, driver graphdriver.Driver, name string) {
131 131
 	file := path.Join(dir, "a file")
132 132
 	verifyFile(t, file, 0222|os.ModeSetuid, 0, 0)
133 133
 
134
-	fis, err := readDir(dir)
135
-	if err != nil {
136
-		t.Fatal(err)
137
-	}
138
-
139
-	if len(fis) != 2 {
140
-		t.Fatal("Unexpected files in base image")
141
-	}
142
-
134
+	files, err := readDir(dir)
135
+	require.NoError(t, err)
136
+	assert.Len(t, files, 2)
143 137
 }
... ...
@@ -9,7 +9,6 @@ import (
9 9
 	"github.com/docker/docker/pkg/chrootarchive"
10 10
 	"github.com/docker/docker/pkg/idtools"
11 11
 	"github.com/docker/docker/pkg/system"
12
-
13 12
 	"github.com/opencontainers/selinux/go-selinux/label"
14 13
 )
15 14
 
... ...
@@ -26,15 +25,14 @@ func init() {
26 26
 // This sets the home directory for the driver and returns NaiveDiffDriver.
27 27
 func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (graphdriver.Driver, error) {
28 28
 	d := &Driver{
29
-		home:    home,
30
-		uidMaps: uidMaps,
31
-		gidMaps: gidMaps,
29
+		home:       home,
30
+		idMappings: idtools.NewIDMappingsFromMaps(uidMaps, gidMaps),
32 31
 	}
33
-	rootUID, rootGID, err := idtools.GetRootUIDGID(uidMaps, gidMaps)
32
+	rootIDs, err := d.idMappings.RootPair()
34 33
 	if err != nil {
35 34
 		return nil, err
36 35
 	}
37
-	if err := idtools.MkdirAllAs(home, 0700, rootUID, rootGID); err != nil {
36
+	if err := idtools.MkdirAllAndChown(home, 0700, rootIDs); err != nil {
38 37
 		return nil, err
39 38
 	}
40 39
 	return graphdriver.NewNaiveDiffDriver(d, uidMaps, gidMaps), nil
... ...
@@ -45,9 +43,8 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap
45 45
 // In order to support layering, files are copied from the parent layer into the new layer. There is no copy-on-write support.
46 46
 // Driver must be wrapped in NaiveDiffDriver to be used as a graphdriver.Driver
47 47
 type Driver struct {
48
-	home    string
49
-	uidMaps []idtools.IDMap
50
-	gidMaps []idtools.IDMap
48
+	home       string
49
+	idMappings *idtools.IDMappings
51 50
 }
52 51
 
53 52
 func (d *Driver) String() string {
... ...
@@ -82,14 +79,14 @@ func (d *Driver) Create(id, parent string, opts *graphdriver.CreateOpts) error {
82 82
 	}
83 83
 
84 84
 	dir := d.dir(id)
85
-	rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps)
85
+	rootIDs, err := d.idMappings.RootPair()
86 86
 	if err != nil {
87 87
 		return err
88 88
 	}
89
-	if err := idtools.MkdirAllAs(filepath.Dir(dir), 0700, rootUID, rootGID); err != nil {
89
+	if err := idtools.MkdirAllAndChown(filepath.Dir(dir), 0700, rootIDs); err != nil {
90 90
 		return err
91 91
 	}
92
-	if err := idtools.MkdirAs(dir, 0755, rootUID, rootGID); err != nil {
92
+	if err := idtools.MkdirAndChown(dir, 0755, rootIDs); err != nil {
93 93
 		return err
94 94
 	}
95 95
 	labelOpts := []string{"level:s0"}
... ...
@@ -103,10 +100,7 @@ func (d *Driver) Create(id, parent string, opts *graphdriver.CreateOpts) error {
103 103
 	if err != nil {
104 104
 		return fmt.Errorf("%s: %s", parent, err)
105 105
 	}
106
-	if err := CopyWithTar(parentDir, dir); err != nil {
107
-		return err
108
-	}
109
-	return nil
106
+	return CopyWithTar(parentDir, dir)
110 107
 }
111 108
 
112 109
 func (d *Driver) dir(id string) string {
... ...
@@ -39,7 +39,7 @@ type (
39 39
 		NoLchown         bool
40 40
 		UIDMaps          []idtools.IDMap
41 41
 		GIDMaps          []idtools.IDMap
42
-		ChownOpts        idtools.IDPair
42
+		ChownOpts        *idtools.IDPair
43 43
 		IncludeSourceDir bool
44 44
 		// WhiteoutFormat is the expected on disk format for whiteout files.
45 45
 		// This format will be converted to the standard format on pack
... ...
@@ -920,7 +920,7 @@ loop:
920 920
 			}
921 921
 		}
922 922
 
923
-		if err := createTarFile(path, dest, hdr, trBuf, !options.NoLchown, &options.ChownOpts, options.InUserNS); err != nil {
923
+		if err := createTarFile(path, dest, hdr, trBuf, !options.NoLchown, options.ChownOpts, options.InUserNS); err != nil {
924 924
 			return err
925 925
 		}
926 926