Libcontainer no longer provides placeholders for
unsupported platforms, which cause the Windows
builds to fail.
This patch moves features that are not supported
to platform-specific files.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
| ... | ... |
@@ -12,7 +12,6 @@ import ( |
| 12 | 12 |
"path" |
| 13 | 13 |
"path/filepath" |
| 14 | 14 |
"runtime" |
| 15 |
- "strconv" |
|
| 16 | 15 |
"strings" |
| 17 | 16 |
|
| 18 | 17 |
"github.com/docker/docker/api/types" |
| ... | ... |
@@ -24,10 +23,8 @@ import ( |
| 24 | 24 |
"github.com/docker/docker/pkg/containerfs" |
| 25 | 25 |
"github.com/docker/docker/pkg/idtools" |
| 26 | 26 |
"github.com/docker/docker/pkg/stringid" |
| 27 |
- "github.com/docker/docker/pkg/symlink" |
|
| 28 | 27 |
"github.com/docker/docker/pkg/system" |
| 29 | 28 |
"github.com/docker/go-connections/nat" |
| 30 |
- lcUser "github.com/opencontainers/runc/libcontainer/user" |
|
| 31 | 29 |
"github.com/pkg/errors" |
| 32 | 30 |
) |
| 33 | 31 |
|
| ... | ... |
@@ -217,82 +214,6 @@ func (b *Builder) performCopy(state *dispatchState, inst copyInstruction) error |
| 217 | 217 |
return b.exportImage(state, imageMount, runConfigWithCommentCmd) |
| 218 | 218 |
} |
| 219 | 219 |
|
| 220 |
-func parseChownFlag(chown, ctrRootPath string, idMappings *idtools.IDMappings) (idtools.IDPair, error) {
|
|
| 221 |
- var userStr, grpStr string |
|
| 222 |
- parts := strings.Split(chown, ":") |
|
| 223 |
- if len(parts) > 2 {
|
|
| 224 |
- return idtools.IDPair{}, errors.New("invalid chown string format: " + chown)
|
|
| 225 |
- } |
|
| 226 |
- if len(parts) == 1 {
|
|
| 227 |
- // if no group specified, use the user spec as group as well |
|
| 228 |
- userStr, grpStr = parts[0], parts[0] |
|
| 229 |
- } else {
|
|
| 230 |
- userStr, grpStr = parts[0], parts[1] |
|
| 231 |
- } |
|
| 232 |
- |
|
| 233 |
- passwdPath, err := symlink.FollowSymlinkInScope(filepath.Join(ctrRootPath, "etc", "passwd"), ctrRootPath) |
|
| 234 |
- if err != nil {
|
|
| 235 |
- return idtools.IDPair{}, errors.Wrapf(err, "can't resolve /etc/passwd path in container rootfs")
|
|
| 236 |
- } |
|
| 237 |
- groupPath, err := symlink.FollowSymlinkInScope(filepath.Join(ctrRootPath, "etc", "group"), ctrRootPath) |
|
| 238 |
- if err != nil {
|
|
| 239 |
- return idtools.IDPair{}, errors.Wrapf(err, "can't resolve /etc/group path in container rootfs")
|
|
| 240 |
- } |
|
| 241 |
- uid, err := lookupUser(userStr, passwdPath) |
|
| 242 |
- if err != nil {
|
|
| 243 |
- return idtools.IDPair{}, errors.Wrapf(err, "can't find uid for user "+userStr)
|
|
| 244 |
- } |
|
| 245 |
- gid, err := lookupGroup(grpStr, groupPath) |
|
| 246 |
- if err != nil {
|
|
| 247 |
- return idtools.IDPair{}, errors.Wrapf(err, "can't find gid for group "+grpStr)
|
|
| 248 |
- } |
|
| 249 |
- |
|
| 250 |
- // convert as necessary because of user namespaces |
|
| 251 |
- chownPair, err := idMappings.ToHost(idtools.IDPair{UID: uid, GID: gid})
|
|
| 252 |
- if err != nil {
|
|
| 253 |
- return idtools.IDPair{}, errors.Wrapf(err, "unable to convert uid/gid to host mapping")
|
|
| 254 |
- } |
|
| 255 |
- return chownPair, nil |
|
| 256 |
-} |
|
| 257 |
- |
|
| 258 |
-func lookupUser(userStr, filepath string) (int, error) {
|
|
| 259 |
- // if the string is actually a uid integer, parse to int and return |
|
| 260 |
- // as we don't need to translate with the help of files |
|
| 261 |
- uid, err := strconv.Atoi(userStr) |
|
| 262 |
- if err == nil {
|
|
| 263 |
- return uid, nil |
|
| 264 |
- } |
|
| 265 |
- users, err := lcUser.ParsePasswdFileFilter(filepath, func(u lcUser.User) bool {
|
|
| 266 |
- return u.Name == userStr |
|
| 267 |
- }) |
|
| 268 |
- if err != nil {
|
|
| 269 |
- return 0, err |
|
| 270 |
- } |
|
| 271 |
- if len(users) == 0 {
|
|
| 272 |
- return 0, errors.New("no such user: " + userStr)
|
|
| 273 |
- } |
|
| 274 |
- return users[0].Uid, nil |
|
| 275 |
-} |
|
| 276 |
- |
|
| 277 |
-func lookupGroup(groupStr, filepath string) (int, error) {
|
|
| 278 |
- // if the string is actually a gid integer, parse to int and return |
|
| 279 |
- // as we don't need to translate with the help of files |
|
| 280 |
- gid, err := strconv.Atoi(groupStr) |
|
| 281 |
- if err == nil {
|
|
| 282 |
- return gid, nil |
|
| 283 |
- } |
|
| 284 |
- groups, err := lcUser.ParseGroupFileFilter(filepath, func(g lcUser.Group) bool {
|
|
| 285 |
- return g.Name == groupStr |
|
| 286 |
- }) |
|
| 287 |
- if err != nil {
|
|
| 288 |
- return 0, err |
|
| 289 |
- } |
|
| 290 |
- if len(groups) == 0 {
|
|
| 291 |
- return 0, errors.New("no such group: " + groupStr)
|
|
| 292 |
- } |
|
| 293 |
- return groups[0].Gid, nil |
|
| 294 |
-} |
|
| 295 |
- |
|
| 296 | 220 |
func createDestInfo(workingDir string, inst copyInstruction, imageMount *imageMount, platform string) (copyInfo, error) {
|
| 297 | 221 |
// Twiddle the destination when it's a relative path - meaning, make it |
| 298 | 222 |
// relative to the WORKINGDIR |
| 299 | 223 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,88 @@ |
| 0 |
+package dockerfile |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "path/filepath" |
|
| 4 |
+ "strconv" |
|
| 5 |
+ "strings" |
|
| 6 |
+ |
|
| 7 |
+ "github.com/docker/docker/pkg/idtools" |
|
| 8 |
+ "github.com/docker/docker/pkg/symlink" |
|
| 9 |
+ lcUser "github.com/opencontainers/runc/libcontainer/user" |
|
| 10 |
+ "github.com/pkg/errors" |
|
| 11 |
+) |
|
| 12 |
+ |
|
| 13 |
+func parseChownFlag(chown, ctrRootPath string, idMappings *idtools.IDMappings) (idtools.IDPair, error) {
|
|
| 14 |
+ var userStr, grpStr string |
|
| 15 |
+ parts := strings.Split(chown, ":") |
|
| 16 |
+ if len(parts) > 2 {
|
|
| 17 |
+ return idtools.IDPair{}, errors.New("invalid chown string format: " + chown)
|
|
| 18 |
+ } |
|
| 19 |
+ if len(parts) == 1 {
|
|
| 20 |
+ // if no group specified, use the user spec as group as well |
|
| 21 |
+ userStr, grpStr = parts[0], parts[0] |
|
| 22 |
+ } else {
|
|
| 23 |
+ userStr, grpStr = parts[0], parts[1] |
|
| 24 |
+ } |
|
| 25 |
+ |
|
| 26 |
+ passwdPath, err := symlink.FollowSymlinkInScope(filepath.Join(ctrRootPath, "etc", "passwd"), ctrRootPath) |
|
| 27 |
+ if err != nil {
|
|
| 28 |
+ return idtools.IDPair{}, errors.Wrapf(err, "can't resolve /etc/passwd path in container rootfs")
|
|
| 29 |
+ } |
|
| 30 |
+ groupPath, err := symlink.FollowSymlinkInScope(filepath.Join(ctrRootPath, "etc", "group"), ctrRootPath) |
|
| 31 |
+ if err != nil {
|
|
| 32 |
+ return idtools.IDPair{}, errors.Wrapf(err, "can't resolve /etc/group path in container rootfs")
|
|
| 33 |
+ } |
|
| 34 |
+ uid, err := lookupUser(userStr, passwdPath) |
|
| 35 |
+ if err != nil {
|
|
| 36 |
+ return idtools.IDPair{}, errors.Wrapf(err, "can't find uid for user "+userStr)
|
|
| 37 |
+ } |
|
| 38 |
+ gid, err := lookupGroup(grpStr, groupPath) |
|
| 39 |
+ if err != nil {
|
|
| 40 |
+ return idtools.IDPair{}, errors.Wrapf(err, "can't find gid for group "+grpStr)
|
|
| 41 |
+ } |
|
| 42 |
+ |
|
| 43 |
+ // convert as necessary because of user namespaces |
|
| 44 |
+ chownPair, err := idMappings.ToHost(idtools.IDPair{UID: uid, GID: gid})
|
|
| 45 |
+ if err != nil {
|
|
| 46 |
+ return idtools.IDPair{}, errors.Wrapf(err, "unable to convert uid/gid to host mapping")
|
|
| 47 |
+ } |
|
| 48 |
+ return chownPair, nil |
|
| 49 |
+} |
|
| 50 |
+ |
|
| 51 |
+func lookupUser(userStr, filepath string) (int, error) {
|
|
| 52 |
+ // if the string is actually a uid integer, parse to int and return |
|
| 53 |
+ // as we don't need to translate with the help of files |
|
| 54 |
+ uid, err := strconv.Atoi(userStr) |
|
| 55 |
+ if err == nil {
|
|
| 56 |
+ return uid, nil |
|
| 57 |
+ } |
|
| 58 |
+ users, err := lcUser.ParsePasswdFileFilter(filepath, func(u lcUser.User) bool {
|
|
| 59 |
+ return u.Name == userStr |
|
| 60 |
+ }) |
|
| 61 |
+ if err != nil {
|
|
| 62 |
+ return 0, err |
|
| 63 |
+ } |
|
| 64 |
+ if len(users) == 0 {
|
|
| 65 |
+ return 0, errors.New("no such user: " + userStr)
|
|
| 66 |
+ } |
|
| 67 |
+ return users[0].Uid, nil |
|
| 68 |
+} |
|
| 69 |
+ |
|
| 70 |
+func lookupGroup(groupStr, filepath string) (int, error) {
|
|
| 71 |
+ // if the string is actually a gid integer, parse to int and return |
|
| 72 |
+ // as we don't need to translate with the help of files |
|
| 73 |
+ gid, err := strconv.Atoi(groupStr) |
|
| 74 |
+ if err == nil {
|
|
| 75 |
+ return gid, nil |
|
| 76 |
+ } |
|
| 77 |
+ groups, err := lcUser.ParseGroupFileFilter(filepath, func(g lcUser.Group) bool {
|
|
| 78 |
+ return g.Name == groupStr |
|
| 79 |
+ }) |
|
| 80 |
+ if err != nil {
|
|
| 81 |
+ return 0, err |
|
| 82 |
+ } |
|
| 83 |
+ if len(groups) == 0 {
|
|
| 84 |
+ return 0, errors.New("no such group: " + groupStr)
|
|
| 85 |
+ } |
|
| 86 |
+ return groups[0].Gid, nil |
|
| 87 |
+} |
| 0 | 88 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,138 @@ |
| 0 |
+package dockerfile |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "os" |
|
| 4 |
+ "path/filepath" |
|
| 5 |
+ "testing" |
|
| 6 |
+ |
|
| 7 |
+ "github.com/docker/docker/pkg/idtools" |
|
| 8 |
+ "github.com/stretchr/testify/assert" |
|
| 9 |
+ "github.com/stretchr/testify/require" |
|
| 10 |
+) |
|
| 11 |
+ |
|
| 12 |
+func TestChownFlagParsing(t *testing.T) {
|
|
| 13 |
+ testFiles := map[string]string{
|
|
| 14 |
+ "passwd": `root:x:0:0::/bin:/bin/false |
|
| 15 |
+bin:x:1:1::/bin:/bin/false |
|
| 16 |
+wwwwww:x:21:33::/bin:/bin/false |
|
| 17 |
+unicorn:x:1001:1002::/bin:/bin/false |
|
| 18 |
+ `, |
|
| 19 |
+ "group": `root:x:0: |
|
| 20 |
+bin:x:1: |
|
| 21 |
+wwwwww:x:33: |
|
| 22 |
+unicorn:x:1002: |
|
| 23 |
+somegrp:x:5555: |
|
| 24 |
+othergrp:x:6666: |
|
| 25 |
+ `, |
|
| 26 |
+ } |
|
| 27 |
+ // test mappings for validating use of maps |
|
| 28 |
+ idMaps := []idtools.IDMap{
|
|
| 29 |
+ {
|
|
| 30 |
+ ContainerID: 0, |
|
| 31 |
+ HostID: 100000, |
|
| 32 |
+ Size: 65536, |
|
| 33 |
+ }, |
|
| 34 |
+ } |
|
| 35 |
+ remapped := idtools.NewIDMappingsFromMaps(idMaps, idMaps) |
|
| 36 |
+ unmapped := &idtools.IDMappings{}
|
|
| 37 |
+ |
|
| 38 |
+ contextDir, cleanup := createTestTempDir(t, "", "builder-chown-parse-test") |
|
| 39 |
+ defer cleanup() |
|
| 40 |
+ |
|
| 41 |
+ if err := os.Mkdir(filepath.Join(contextDir, "etc"), 0755); err != nil {
|
|
| 42 |
+ t.Fatalf("error creating test directory: %v", err)
|
|
| 43 |
+ } |
|
| 44 |
+ |
|
| 45 |
+ for filename, content := range testFiles {
|
|
| 46 |
+ createTestTempFile(t, filepath.Join(contextDir, "etc"), filename, content, 0644) |
|
| 47 |
+ } |
|
| 48 |
+ |
|
| 49 |
+ // positive tests |
|
| 50 |
+ for _, testcase := range []struct {
|
|
| 51 |
+ name string |
|
| 52 |
+ chownStr string |
|
| 53 |
+ idMapping *idtools.IDMappings |
|
| 54 |
+ expected idtools.IDPair |
|
| 55 |
+ }{
|
|
| 56 |
+ {
|
|
| 57 |
+ name: "UIDNoMap", |
|
| 58 |
+ chownStr: "1", |
|
| 59 |
+ idMapping: unmapped, |
|
| 60 |
+ expected: idtools.IDPair{UID: 1, GID: 1},
|
|
| 61 |
+ }, |
|
| 62 |
+ {
|
|
| 63 |
+ name: "UIDGIDNoMap", |
|
| 64 |
+ chownStr: "0:1", |
|
| 65 |
+ idMapping: unmapped, |
|
| 66 |
+ expected: idtools.IDPair{UID: 0, GID: 1},
|
|
| 67 |
+ }, |
|
| 68 |
+ {
|
|
| 69 |
+ name: "UIDWithMap", |
|
| 70 |
+ chownStr: "0", |
|
| 71 |
+ idMapping: remapped, |
|
| 72 |
+ expected: idtools.IDPair{UID: 100000, GID: 100000},
|
|
| 73 |
+ }, |
|
| 74 |
+ {
|
|
| 75 |
+ name: "UIDGIDWithMap", |
|
| 76 |
+ chownStr: "1:33", |
|
| 77 |
+ idMapping: remapped, |
|
| 78 |
+ expected: idtools.IDPair{UID: 100001, GID: 100033},
|
|
| 79 |
+ }, |
|
| 80 |
+ {
|
|
| 81 |
+ name: "UserNoMap", |
|
| 82 |
+ chownStr: "bin:5555", |
|
| 83 |
+ idMapping: unmapped, |
|
| 84 |
+ expected: idtools.IDPair{UID: 1, GID: 5555},
|
|
| 85 |
+ }, |
|
| 86 |
+ {
|
|
| 87 |
+ name: "GroupWithMap", |
|
| 88 |
+ chownStr: "0:unicorn", |
|
| 89 |
+ idMapping: remapped, |
|
| 90 |
+ expected: idtools.IDPair{UID: 100000, GID: 101002},
|
|
| 91 |
+ }, |
|
| 92 |
+ {
|
|
| 93 |
+ name: "UserOnlyWithMap", |
|
| 94 |
+ chownStr: "unicorn", |
|
| 95 |
+ idMapping: remapped, |
|
| 96 |
+ expected: idtools.IDPair{UID: 101001, GID: 101002},
|
|
| 97 |
+ }, |
|
| 98 |
+ } {
|
|
| 99 |
+ t.Run(testcase.name, func(t *testing.T) {
|
|
| 100 |
+ idPair, err := parseChownFlag(testcase.chownStr, contextDir, testcase.idMapping) |
|
| 101 |
+ require.NoError(t, err, "Failed to parse chown flag: %q", testcase.chownStr) |
|
| 102 |
+ assert.Equal(t, testcase.expected, idPair, "chown flag mapping failure") |
|
| 103 |
+ }) |
|
| 104 |
+ } |
|
| 105 |
+ |
|
| 106 |
+ // error tests |
|
| 107 |
+ for _, testcase := range []struct {
|
|
| 108 |
+ name string |
|
| 109 |
+ chownStr string |
|
| 110 |
+ idMapping *idtools.IDMappings |
|
| 111 |
+ descr string |
|
| 112 |
+ }{
|
|
| 113 |
+ {
|
|
| 114 |
+ name: "BadChownFlagFormat", |
|
| 115 |
+ chownStr: "bob:1:555", |
|
| 116 |
+ idMapping: unmapped, |
|
| 117 |
+ descr: "invalid chown string format: bob:1:555", |
|
| 118 |
+ }, |
|
| 119 |
+ {
|
|
| 120 |
+ name: "UserNoExist", |
|
| 121 |
+ chownStr: "bob", |
|
| 122 |
+ idMapping: unmapped, |
|
| 123 |
+ descr: "can't find uid for user bob: no such user: bob", |
|
| 124 |
+ }, |
|
| 125 |
+ {
|
|
| 126 |
+ name: "GroupNoExist", |
|
| 127 |
+ chownStr: "root:bob", |
|
| 128 |
+ idMapping: unmapped, |
|
| 129 |
+ descr: "can't find gid for group bob: no such group: bob", |
|
| 130 |
+ }, |
|
| 131 |
+ } {
|
|
| 132 |
+ t.Run(testcase.name, func(t *testing.T) {
|
|
| 133 |
+ _, err := parseChownFlag(testcase.chownStr, contextDir, testcase.idMapping) |
|
| 134 |
+ assert.EqualError(t, err, testcase.descr, "Expected error string doesn't match") |
|
| 135 |
+ }) |
|
| 136 |
+ } |
|
| 137 |
+} |
| ... | ... |
@@ -2,8 +2,6 @@ package dockerfile |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 | 4 |
"fmt" |
| 5 |
- "os" |
|
| 6 |
- "path/filepath" |
|
| 7 | 5 |
"runtime" |
| 8 | 6 |
"testing" |
| 9 | 7 |
|
| ... | ... |
@@ -13,7 +11,6 @@ import ( |
| 13 | 13 |
"github.com/docker/docker/builder" |
| 14 | 14 |
"github.com/docker/docker/builder/remotecontext" |
| 15 | 15 |
"github.com/docker/docker/pkg/archive" |
| 16 |
- "github.com/docker/docker/pkg/idtools" |
|
| 17 | 16 |
"github.com/docker/go-connections/nat" |
| 18 | 17 |
"github.com/stretchr/testify/assert" |
| 19 | 18 |
"github.com/stretchr/testify/require" |
| ... | ... |
@@ -171,130 +168,3 @@ func TestDeepCopyRunConfig(t *testing.T) {
|
| 171 | 171 |
copy.Shell[0] = "sh" |
| 172 | 172 |
assert.Equal(t, fullMutableRunConfig(), runConfig) |
| 173 | 173 |
} |
| 174 |
- |
|
| 175 |
-func TestChownFlagParsing(t *testing.T) {
|
|
| 176 |
- testFiles := map[string]string{
|
|
| 177 |
- "passwd": `root:x:0:0::/bin:/bin/false |
|
| 178 |
-bin:x:1:1::/bin:/bin/false |
|
| 179 |
-wwwwww:x:21:33::/bin:/bin/false |
|
| 180 |
-unicorn:x:1001:1002::/bin:/bin/false |
|
| 181 |
- `, |
|
| 182 |
- "group": `root:x:0: |
|
| 183 |
-bin:x:1: |
|
| 184 |
-wwwwww:x:33: |
|
| 185 |
-unicorn:x:1002: |
|
| 186 |
-somegrp:x:5555: |
|
| 187 |
-othergrp:x:6666: |
|
| 188 |
- `, |
|
| 189 |
- } |
|
| 190 |
- // test mappings for validating use of maps |
|
| 191 |
- idMaps := []idtools.IDMap{
|
|
| 192 |
- {
|
|
| 193 |
- ContainerID: 0, |
|
| 194 |
- HostID: 100000, |
|
| 195 |
- Size: 65536, |
|
| 196 |
- }, |
|
| 197 |
- } |
|
| 198 |
- remapped := idtools.NewIDMappingsFromMaps(idMaps, idMaps) |
|
| 199 |
- unmapped := &idtools.IDMappings{}
|
|
| 200 |
- |
|
| 201 |
- contextDir, cleanup := createTestTempDir(t, "", "builder-chown-parse-test") |
|
| 202 |
- defer cleanup() |
|
| 203 |
- |
|
| 204 |
- if err := os.Mkdir(filepath.Join(contextDir, "etc"), 0755); err != nil {
|
|
| 205 |
- t.Fatalf("error creating test directory: %v", err)
|
|
| 206 |
- } |
|
| 207 |
- |
|
| 208 |
- for filename, content := range testFiles {
|
|
| 209 |
- createTestTempFile(t, filepath.Join(contextDir, "etc"), filename, content, 0644) |
|
| 210 |
- } |
|
| 211 |
- |
|
| 212 |
- // positive tests |
|
| 213 |
- for _, testcase := range []struct {
|
|
| 214 |
- name string |
|
| 215 |
- chownStr string |
|
| 216 |
- idMapping *idtools.IDMappings |
|
| 217 |
- expected idtools.IDPair |
|
| 218 |
- }{
|
|
| 219 |
- {
|
|
| 220 |
- name: "UIDNoMap", |
|
| 221 |
- chownStr: "1", |
|
| 222 |
- idMapping: unmapped, |
|
| 223 |
- expected: idtools.IDPair{UID: 1, GID: 1},
|
|
| 224 |
- }, |
|
| 225 |
- {
|
|
| 226 |
- name: "UIDGIDNoMap", |
|
| 227 |
- chownStr: "0:1", |
|
| 228 |
- idMapping: unmapped, |
|
| 229 |
- expected: idtools.IDPair{UID: 0, GID: 1},
|
|
| 230 |
- }, |
|
| 231 |
- {
|
|
| 232 |
- name: "UIDWithMap", |
|
| 233 |
- chownStr: "0", |
|
| 234 |
- idMapping: remapped, |
|
| 235 |
- expected: idtools.IDPair{UID: 100000, GID: 100000},
|
|
| 236 |
- }, |
|
| 237 |
- {
|
|
| 238 |
- name: "UIDGIDWithMap", |
|
| 239 |
- chownStr: "1:33", |
|
| 240 |
- idMapping: remapped, |
|
| 241 |
- expected: idtools.IDPair{UID: 100001, GID: 100033},
|
|
| 242 |
- }, |
|
| 243 |
- {
|
|
| 244 |
- name: "UserNoMap", |
|
| 245 |
- chownStr: "bin:5555", |
|
| 246 |
- idMapping: unmapped, |
|
| 247 |
- expected: idtools.IDPair{UID: 1, GID: 5555},
|
|
| 248 |
- }, |
|
| 249 |
- {
|
|
| 250 |
- name: "GroupWithMap", |
|
| 251 |
- chownStr: "0:unicorn", |
|
| 252 |
- idMapping: remapped, |
|
| 253 |
- expected: idtools.IDPair{UID: 100000, GID: 101002},
|
|
| 254 |
- }, |
|
| 255 |
- {
|
|
| 256 |
- name: "UserOnlyWithMap", |
|
| 257 |
- chownStr: "unicorn", |
|
| 258 |
- idMapping: remapped, |
|
| 259 |
- expected: idtools.IDPair{UID: 101001, GID: 101002},
|
|
| 260 |
- }, |
|
| 261 |
- } {
|
|
| 262 |
- t.Run(testcase.name, func(t *testing.T) {
|
|
| 263 |
- idPair, err := parseChownFlag(testcase.chownStr, contextDir, testcase.idMapping) |
|
| 264 |
- require.NoError(t, err, "Failed to parse chown flag: %q", testcase.chownStr) |
|
| 265 |
- assert.Equal(t, testcase.expected, idPair, "chown flag mapping failure") |
|
| 266 |
- }) |
|
| 267 |
- } |
|
| 268 |
- |
|
| 269 |
- // error tests |
|
| 270 |
- for _, testcase := range []struct {
|
|
| 271 |
- name string |
|
| 272 |
- chownStr string |
|
| 273 |
- idMapping *idtools.IDMappings |
|
| 274 |
- descr string |
|
| 275 |
- }{
|
|
| 276 |
- {
|
|
| 277 |
- name: "BadChownFlagFormat", |
|
| 278 |
- chownStr: "bob:1:555", |
|
| 279 |
- idMapping: unmapped, |
|
| 280 |
- descr: "invalid chown string format: bob:1:555", |
|
| 281 |
- }, |
|
| 282 |
- {
|
|
| 283 |
- name: "UserNoExist", |
|
| 284 |
- chownStr: "bob", |
|
| 285 |
- idMapping: unmapped, |
|
| 286 |
- descr: "can't find uid for user bob: no such user: bob", |
|
| 287 |
- }, |
|
| 288 |
- {
|
|
| 289 |
- name: "GroupNoExist", |
|
| 290 |
- chownStr: "root:bob", |
|
| 291 |
- idMapping: unmapped, |
|
| 292 |
- descr: "can't find gid for group bob: no such group: bob", |
|
| 293 |
- }, |
|
| 294 |
- } {
|
|
| 295 |
- t.Run(testcase.name, func(t *testing.T) {
|
|
| 296 |
- _, err := parseChownFlag(testcase.chownStr, contextDir, testcase.idMapping) |
|
| 297 |
- assert.EqualError(t, err, testcase.descr, "Expected error string doesn't match") |
|
| 298 |
- }) |
|
| 299 |
- } |
|
| 300 |
-} |
| ... | ... |
@@ -36,7 +36,6 @@ import ( |
| 36 | 36 |
"github.com/docker/libnetwork/types" |
| 37 | 37 |
"github.com/go-check/check" |
| 38 | 38 |
"github.com/gotestyourself/gotestyourself/icmd" |
| 39 |
- libcontainerUser "github.com/opencontainers/runc/libcontainer/user" |
|
| 40 | 39 |
"golang.org/x/net/context" |
| 41 | 40 |
) |
| 42 | 41 |
|
| ... | ... |
@@ -751,7 +750,7 @@ func (s *DockerSuite) TestRunUserByIDBig(c *check.C) {
|
| 751 | 751 |
if err == nil {
|
| 752 | 752 |
c.Fatal("No error, but must be.", out)
|
| 753 | 753 |
} |
| 754 |
- if !strings.Contains(strings.ToUpper(out), strings.ToUpper(libcontainerUser.ErrRange.Error())) {
|
|
| 754 |
+ if !strings.Contains(strings.ToLower(out), "uids and gids must be in range") {
|
|
| 755 | 755 |
c.Fatalf("expected error about uids range, got %s", out)
|
| 756 | 756 |
} |
| 757 | 757 |
} |
| ... | ... |
@@ -764,7 +763,7 @@ func (s *DockerSuite) TestRunUserByIDNegative(c *check.C) {
|
| 764 | 764 |
if err == nil {
|
| 765 | 765 |
c.Fatal("No error, but must be.", out)
|
| 766 | 766 |
} |
| 767 |
- if !strings.Contains(strings.ToUpper(out), strings.ToUpper(libcontainerUser.ErrRange.Error())) {
|
|
| 767 |
+ if !strings.Contains(strings.ToLower(out), "uids and gids must be in range") {
|
|
| 768 | 768 |
c.Fatalf("expected error about uids range, got %s", out)
|
| 769 | 769 |
} |
| 770 | 770 |
} |