Browse Source

Fixes for libcontainer changes

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>
Sebastiaan van Stijn 7 years ago
parent
commit
d1c34831e9

+ 0 - 79
builder/dockerfile/internals.go

@@ -12,7 +12,6 @@ import (
 	"path"
 	"path/filepath"
 	"runtime"
-	"strconv"
 	"strings"
 
 	"github.com/docker/docker/api/types"
@@ -24,10 +23,8 @@ import (
 	"github.com/docker/docker/pkg/containerfs"
 	"github.com/docker/docker/pkg/idtools"
 	"github.com/docker/docker/pkg/stringid"
-	"github.com/docker/docker/pkg/symlink"
 	"github.com/docker/docker/pkg/system"
 	"github.com/docker/go-connections/nat"
-	lcUser "github.com/opencontainers/runc/libcontainer/user"
 	"github.com/pkg/errors"
 )
 
@@ -217,82 +214,6 @@ func (b *Builder) performCopy(state *dispatchState, inst copyInstruction) error
 	return b.exportImage(state, imageMount, runConfigWithCommentCmd)
 }
 
-func parseChownFlag(chown, ctrRootPath string, idMappings *idtools.IDMappings) (idtools.IDPair, error) {
-	var userStr, grpStr string
-	parts := strings.Split(chown, ":")
-	if len(parts) > 2 {
-		return idtools.IDPair{}, errors.New("invalid chown string format: " + chown)
-	}
-	if len(parts) == 1 {
-		// if no group specified, use the user spec as group as well
-		userStr, grpStr = parts[0], parts[0]
-	} else {
-		userStr, grpStr = parts[0], parts[1]
-	}
-
-	passwdPath, err := symlink.FollowSymlinkInScope(filepath.Join(ctrRootPath, "etc", "passwd"), ctrRootPath)
-	if err != nil {
-		return idtools.IDPair{}, errors.Wrapf(err, "can't resolve /etc/passwd path in container rootfs")
-	}
-	groupPath, err := symlink.FollowSymlinkInScope(filepath.Join(ctrRootPath, "etc", "group"), ctrRootPath)
-	if err != nil {
-		return idtools.IDPair{}, errors.Wrapf(err, "can't resolve /etc/group path in container rootfs")
-	}
-	uid, err := lookupUser(userStr, passwdPath)
-	if err != nil {
-		return idtools.IDPair{}, errors.Wrapf(err, "can't find uid for user "+userStr)
-	}
-	gid, err := lookupGroup(grpStr, groupPath)
-	if err != nil {
-		return idtools.IDPair{}, errors.Wrapf(err, "can't find gid for group "+grpStr)
-	}
-
-	// convert as necessary because of user namespaces
-	chownPair, err := idMappings.ToHost(idtools.IDPair{UID: uid, GID: gid})
-	if err != nil {
-		return idtools.IDPair{}, errors.Wrapf(err, "unable to convert uid/gid to host mapping")
-	}
-	return chownPair, nil
-}
-
-func lookupUser(userStr, filepath string) (int, error) {
-	// if the string is actually a uid integer, parse to int and return
-	// as we don't need to translate with the help of files
-	uid, err := strconv.Atoi(userStr)
-	if err == nil {
-		return uid, nil
-	}
-	users, err := lcUser.ParsePasswdFileFilter(filepath, func(u lcUser.User) bool {
-		return u.Name == userStr
-	})
-	if err != nil {
-		return 0, err
-	}
-	if len(users) == 0 {
-		return 0, errors.New("no such user: " + userStr)
-	}
-	return users[0].Uid, nil
-}
-
-func lookupGroup(groupStr, filepath string) (int, error) {
-	// if the string is actually a gid integer, parse to int and return
-	// as we don't need to translate with the help of files
-	gid, err := strconv.Atoi(groupStr)
-	if err == nil {
-		return gid, nil
-	}
-	groups, err := lcUser.ParseGroupFileFilter(filepath, func(g lcUser.Group) bool {
-		return g.Name == groupStr
-	})
-	if err != nil {
-		return 0, err
-	}
-	if len(groups) == 0 {
-		return 0, errors.New("no such group: " + groupStr)
-	}
-	return groups[0].Gid, nil
-}
-
 func createDestInfo(workingDir string, inst copyInstruction, imageMount *imageMount, platform string) (copyInfo, error) {
 	// Twiddle the destination when it's a relative path - meaning, make it
 	// relative to the WORKINGDIR

+ 88 - 0
builder/dockerfile/internals_linux.go

@@ -0,0 +1,88 @@
+package dockerfile
+
+import (
+	"path/filepath"
+	"strconv"
+	"strings"
+
+	"github.com/docker/docker/pkg/idtools"
+	"github.com/docker/docker/pkg/symlink"
+	lcUser "github.com/opencontainers/runc/libcontainer/user"
+	"github.com/pkg/errors"
+)
+
+func parseChownFlag(chown, ctrRootPath string, idMappings *idtools.IDMappings) (idtools.IDPair, error) {
+	var userStr, grpStr string
+	parts := strings.Split(chown, ":")
+	if len(parts) > 2 {
+		return idtools.IDPair{}, errors.New("invalid chown string format: " + chown)
+	}
+	if len(parts) == 1 {
+		// if no group specified, use the user spec as group as well
+		userStr, grpStr = parts[0], parts[0]
+	} else {
+		userStr, grpStr = parts[0], parts[1]
+	}
+
+	passwdPath, err := symlink.FollowSymlinkInScope(filepath.Join(ctrRootPath, "etc", "passwd"), ctrRootPath)
+	if err != nil {
+		return idtools.IDPair{}, errors.Wrapf(err, "can't resolve /etc/passwd path in container rootfs")
+	}
+	groupPath, err := symlink.FollowSymlinkInScope(filepath.Join(ctrRootPath, "etc", "group"), ctrRootPath)
+	if err != nil {
+		return idtools.IDPair{}, errors.Wrapf(err, "can't resolve /etc/group path in container rootfs")
+	}
+	uid, err := lookupUser(userStr, passwdPath)
+	if err != nil {
+		return idtools.IDPair{}, errors.Wrapf(err, "can't find uid for user "+userStr)
+	}
+	gid, err := lookupGroup(grpStr, groupPath)
+	if err != nil {
+		return idtools.IDPair{}, errors.Wrapf(err, "can't find gid for group "+grpStr)
+	}
+
+	// convert as necessary because of user namespaces
+	chownPair, err := idMappings.ToHost(idtools.IDPair{UID: uid, GID: gid})
+	if err != nil {
+		return idtools.IDPair{}, errors.Wrapf(err, "unable to convert uid/gid to host mapping")
+	}
+	return chownPair, nil
+}
+
+func lookupUser(userStr, filepath string) (int, error) {
+	// if the string is actually a uid integer, parse to int and return
+	// as we don't need to translate with the help of files
+	uid, err := strconv.Atoi(userStr)
+	if err == nil {
+		return uid, nil
+	}
+	users, err := lcUser.ParsePasswdFileFilter(filepath, func(u lcUser.User) bool {
+		return u.Name == userStr
+	})
+	if err != nil {
+		return 0, err
+	}
+	if len(users) == 0 {
+		return 0, errors.New("no such user: " + userStr)
+	}
+	return users[0].Uid, nil
+}
+
+func lookupGroup(groupStr, filepath string) (int, error) {
+	// if the string is actually a gid integer, parse to int and return
+	// as we don't need to translate with the help of files
+	gid, err := strconv.Atoi(groupStr)
+	if err == nil {
+		return gid, nil
+	}
+	groups, err := lcUser.ParseGroupFileFilter(filepath, func(g lcUser.Group) bool {
+		return g.Name == groupStr
+	})
+	if err != nil {
+		return 0, err
+	}
+	if len(groups) == 0 {
+		return 0, errors.New("no such group: " + groupStr)
+	}
+	return groups[0].Gid, nil
+}

+ 138 - 0
builder/dockerfile/internals_linux_test.go

@@ -0,0 +1,138 @@
+package dockerfile
+
+import (
+	"os"
+	"path/filepath"
+	"testing"
+
+	"github.com/docker/docker/pkg/idtools"
+	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
+)
+
+func TestChownFlagParsing(t *testing.T) {
+	testFiles := map[string]string{
+		"passwd": `root:x:0:0::/bin:/bin/false
+bin:x:1:1::/bin:/bin/false
+wwwwww:x:21:33::/bin:/bin/false
+unicorn:x:1001:1002::/bin:/bin/false
+		`,
+		"group": `root:x:0:
+bin:x:1:
+wwwwww:x:33:
+unicorn:x:1002:
+somegrp:x:5555:
+othergrp:x:6666:
+		`,
+	}
+	// test mappings for validating use of maps
+	idMaps := []idtools.IDMap{
+		{
+			ContainerID: 0,
+			HostID:      100000,
+			Size:        65536,
+		},
+	}
+	remapped := idtools.NewIDMappingsFromMaps(idMaps, idMaps)
+	unmapped := &idtools.IDMappings{}
+
+	contextDir, cleanup := createTestTempDir(t, "", "builder-chown-parse-test")
+	defer cleanup()
+
+	if err := os.Mkdir(filepath.Join(contextDir, "etc"), 0755); err != nil {
+		t.Fatalf("error creating test directory: %v", err)
+	}
+
+	for filename, content := range testFiles {
+		createTestTempFile(t, filepath.Join(contextDir, "etc"), filename, content, 0644)
+	}
+
+	// positive tests
+	for _, testcase := range []struct {
+		name      string
+		chownStr  string
+		idMapping *idtools.IDMappings
+		expected  idtools.IDPair
+	}{
+		{
+			name:      "UIDNoMap",
+			chownStr:  "1",
+			idMapping: unmapped,
+			expected:  idtools.IDPair{UID: 1, GID: 1},
+		},
+		{
+			name:      "UIDGIDNoMap",
+			chownStr:  "0:1",
+			idMapping: unmapped,
+			expected:  idtools.IDPair{UID: 0, GID: 1},
+		},
+		{
+			name:      "UIDWithMap",
+			chownStr:  "0",
+			idMapping: remapped,
+			expected:  idtools.IDPair{UID: 100000, GID: 100000},
+		},
+		{
+			name:      "UIDGIDWithMap",
+			chownStr:  "1:33",
+			idMapping: remapped,
+			expected:  idtools.IDPair{UID: 100001, GID: 100033},
+		},
+		{
+			name:      "UserNoMap",
+			chownStr:  "bin:5555",
+			idMapping: unmapped,
+			expected:  idtools.IDPair{UID: 1, GID: 5555},
+		},
+		{
+			name:      "GroupWithMap",
+			chownStr:  "0:unicorn",
+			idMapping: remapped,
+			expected:  idtools.IDPair{UID: 100000, GID: 101002},
+		},
+		{
+			name:      "UserOnlyWithMap",
+			chownStr:  "unicorn",
+			idMapping: remapped,
+			expected:  idtools.IDPair{UID: 101001, GID: 101002},
+		},
+	} {
+		t.Run(testcase.name, func(t *testing.T) {
+			idPair, err := parseChownFlag(testcase.chownStr, contextDir, testcase.idMapping)
+			require.NoError(t, err, "Failed to parse chown flag: %q", testcase.chownStr)
+			assert.Equal(t, testcase.expected, idPair, "chown flag mapping failure")
+		})
+	}
+
+	// error tests
+	for _, testcase := range []struct {
+		name      string
+		chownStr  string
+		idMapping *idtools.IDMappings
+		descr     string
+	}{
+		{
+			name:      "BadChownFlagFormat",
+			chownStr:  "bob:1:555",
+			idMapping: unmapped,
+			descr:     "invalid chown string format: bob:1:555",
+		},
+		{
+			name:      "UserNoExist",
+			chownStr:  "bob",
+			idMapping: unmapped,
+			descr:     "can't find uid for user bob: no such user: bob",
+		},
+		{
+			name:      "GroupNoExist",
+			chownStr:  "root:bob",
+			idMapping: unmapped,
+			descr:     "can't find gid for group bob: no such group: bob",
+		},
+	} {
+		t.Run(testcase.name, func(t *testing.T) {
+			_, err := parseChownFlag(testcase.chownStr, contextDir, testcase.idMapping)
+			assert.EqualError(t, err, testcase.descr, "Expected error string doesn't match")
+		})
+	}
+}

+ 0 - 130
builder/dockerfile/internals_test.go

@@ -2,8 +2,6 @@ package dockerfile
 
 import (
 	"fmt"
-	"os"
-	"path/filepath"
 	"runtime"
 	"testing"
 
@@ -13,7 +11,6 @@ import (
 	"github.com/docker/docker/builder"
 	"github.com/docker/docker/builder/remotecontext"
 	"github.com/docker/docker/pkg/archive"
-	"github.com/docker/docker/pkg/idtools"
 	"github.com/docker/go-connections/nat"
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
@@ -171,130 +168,3 @@ func TestDeepCopyRunConfig(t *testing.T) {
 	copy.Shell[0] = "sh"
 	assert.Equal(t, fullMutableRunConfig(), runConfig)
 }
-
-func TestChownFlagParsing(t *testing.T) {
-	testFiles := map[string]string{
-		"passwd": `root:x:0:0::/bin:/bin/false
-bin:x:1:1::/bin:/bin/false
-wwwwww:x:21:33::/bin:/bin/false
-unicorn:x:1001:1002::/bin:/bin/false
-		`,
-		"group": `root:x:0:
-bin:x:1:
-wwwwww:x:33:
-unicorn:x:1002:
-somegrp:x:5555:
-othergrp:x:6666:
-		`,
-	}
-	// test mappings for validating use of maps
-	idMaps := []idtools.IDMap{
-		{
-			ContainerID: 0,
-			HostID:      100000,
-			Size:        65536,
-		},
-	}
-	remapped := idtools.NewIDMappingsFromMaps(idMaps, idMaps)
-	unmapped := &idtools.IDMappings{}
-
-	contextDir, cleanup := createTestTempDir(t, "", "builder-chown-parse-test")
-	defer cleanup()
-
-	if err := os.Mkdir(filepath.Join(contextDir, "etc"), 0755); err != nil {
-		t.Fatalf("error creating test directory: %v", err)
-	}
-
-	for filename, content := range testFiles {
-		createTestTempFile(t, filepath.Join(contextDir, "etc"), filename, content, 0644)
-	}
-
-	// positive tests
-	for _, testcase := range []struct {
-		name      string
-		chownStr  string
-		idMapping *idtools.IDMappings
-		expected  idtools.IDPair
-	}{
-		{
-			name:      "UIDNoMap",
-			chownStr:  "1",
-			idMapping: unmapped,
-			expected:  idtools.IDPair{UID: 1, GID: 1},
-		},
-		{
-			name:      "UIDGIDNoMap",
-			chownStr:  "0:1",
-			idMapping: unmapped,
-			expected:  idtools.IDPair{UID: 0, GID: 1},
-		},
-		{
-			name:      "UIDWithMap",
-			chownStr:  "0",
-			idMapping: remapped,
-			expected:  idtools.IDPair{UID: 100000, GID: 100000},
-		},
-		{
-			name:      "UIDGIDWithMap",
-			chownStr:  "1:33",
-			idMapping: remapped,
-			expected:  idtools.IDPair{UID: 100001, GID: 100033},
-		},
-		{
-			name:      "UserNoMap",
-			chownStr:  "bin:5555",
-			idMapping: unmapped,
-			expected:  idtools.IDPair{UID: 1, GID: 5555},
-		},
-		{
-			name:      "GroupWithMap",
-			chownStr:  "0:unicorn",
-			idMapping: remapped,
-			expected:  idtools.IDPair{UID: 100000, GID: 101002},
-		},
-		{
-			name:      "UserOnlyWithMap",
-			chownStr:  "unicorn",
-			idMapping: remapped,
-			expected:  idtools.IDPair{UID: 101001, GID: 101002},
-		},
-	} {
-		t.Run(testcase.name, func(t *testing.T) {
-			idPair, err := parseChownFlag(testcase.chownStr, contextDir, testcase.idMapping)
-			require.NoError(t, err, "Failed to parse chown flag: %q", testcase.chownStr)
-			assert.Equal(t, testcase.expected, idPair, "chown flag mapping failure")
-		})
-	}
-
-	// error tests
-	for _, testcase := range []struct {
-		name      string
-		chownStr  string
-		idMapping *idtools.IDMappings
-		descr     string
-	}{
-		{
-			name:      "BadChownFlagFormat",
-			chownStr:  "bob:1:555",
-			idMapping: unmapped,
-			descr:     "invalid chown string format: bob:1:555",
-		},
-		{
-			name:      "UserNoExist",
-			chownStr:  "bob",
-			idMapping: unmapped,
-			descr:     "can't find uid for user bob: no such user: bob",
-		},
-		{
-			name:      "GroupNoExist",
-			chownStr:  "root:bob",
-			idMapping: unmapped,
-			descr:     "can't find gid for group bob: no such group: bob",
-		},
-	} {
-		t.Run(testcase.name, func(t *testing.T) {
-			_, err := parseChownFlag(testcase.chownStr, contextDir, testcase.idMapping)
-			assert.EqualError(t, err, testcase.descr, "Expected error string doesn't match")
-		})
-	}
-}

+ 7 - 0
builder/dockerfile/internals_windows.go

@@ -0,0 +1,7 @@
+package dockerfile
+
+import "github.com/docker/docker/pkg/idtools"
+
+func parseChownFlag(chown, ctrRootPath string, idMappings *idtools.IDMappings) (idtools.IDPair, error) {
+	return idMappings.RootPair(), nil
+}

+ 2 - 3
integration-cli/docker_cli_run_test.go

@@ -36,7 +36,6 @@ import (
 	"github.com/docker/libnetwork/types"
 	"github.com/go-check/check"
 	"github.com/gotestyourself/gotestyourself/icmd"
-	libcontainerUser "github.com/opencontainers/runc/libcontainer/user"
 	"golang.org/x/net/context"
 )
 
@@ -751,7 +750,7 @@ func (s *DockerSuite) TestRunUserByIDBig(c *check.C) {
 	if err == nil {
 		c.Fatal("No error, but must be.", out)
 	}
-	if !strings.Contains(strings.ToUpper(out), strings.ToUpper(libcontainerUser.ErrRange.Error())) {
+	if !strings.Contains(strings.ToLower(out), "uids and gids must be in range") {
 		c.Fatalf("expected error about uids range, got %s", out)
 	}
 }
@@ -764,7 +763,7 @@ func (s *DockerSuite) TestRunUserByIDNegative(c *check.C) {
 	if err == nil {
 		c.Fatal("No error, but must be.", out)
 	}
-	if !strings.Contains(strings.ToUpper(out), strings.ToUpper(libcontainerUser.ErrRange.Error())) {
+	if !strings.Contains(strings.ToLower(out), "uids and gids must be in range") {
 		c.Fatalf("expected error about uids range, got %s", out)
 	}
 }