diff --git a/cmd/minikube/cmd/mount.go b/cmd/minikube/cmd/mount.go index 4260178135af..81c6474e4330 100644 --- a/cmd/minikube/cmd/mount.go +++ b/cmd/minikube/cmd/mount.go @@ -45,8 +45,8 @@ var mountIP string var mountVersion string var mountType string var isKill bool -var uid int -var gid int +var uid string +var gid string var mSize int var options []string var mode uint @@ -144,8 +144,8 @@ var mountCmd = &cobra.Command{ console.OutStyle("mounting", "Mounting host path %s into VM as %s ...", hostPath, vmPath) console.OutStyle("mount-options", "Mount options:") console.OutStyle("option", "Type: %s", cfg.Type) - console.OutStyle("option", "UID: %d", cfg.UID) - console.OutStyle("option", "GID: %d", cfg.GID) + console.OutStyle("option", "UID: %s", cfg.UID) + console.OutStyle("option", "GID: %s", cfg.GID) console.OutStyle("option", "Version: %s", cfg.Version) console.OutStyle("option", "MSize: %d", cfg.MSize) console.OutStyle("option", "Mode: %o (%s)", cfg.Mode, cfg.Mode) @@ -194,8 +194,8 @@ func init() { mountCmd.Flags().StringVar(&mountType, "type", nineP, "Specify the mount filesystem type (supported types: 9p)") mountCmd.Flags().StringVar(&mountVersion, "9p-version", constants.DefaultMountVersion, "Specify the 9p version that the mount should use") mountCmd.Flags().BoolVar(&isKill, "kill", false, "Kill the mount process spawned by minikube start") - mountCmd.Flags().IntVar(&uid, "uid", 1001, "Default user id used for the mount") - mountCmd.Flags().IntVar(&gid, "gid", 1001, "Default group id used for the mount") + mountCmd.Flags().StringVar(&uid, "uid", "docker", "Default user id used for the mount") + mountCmd.Flags().StringVar(&gid, "gid", "docker", "Default group id used for the mount") mountCmd.Flags().UintVar(&mode, "mode", 0755, "File permissions used for the mount") mountCmd.Flags().StringSliceVar(&options, "options", []string{}, "Additional mount options, such as cache=fscache") mountCmd.Flags().IntVar(&mSize, "msize", constants.DefaultMsize, "The number of bytes to use for 9p packet payload") diff --git a/pkg/minikube/cluster/mount.go b/pkg/minikube/cluster/mount.go index 41181330b880..95ad69a1233a 100644 --- a/pkg/minikube/cluster/mount.go +++ b/pkg/minikube/cluster/mount.go @@ -31,9 +31,9 @@ type MountConfig struct { // Type is the filesystem type (Typically 9p) Type string // UID is the User ID which this path will be mounted as - UID int + UID string // GID is the Group ID which this path will be mounted as - GID int + GID string // Version is the 9P protocol version. Valid options: 9p2000, 9p200.u, 9p2000.L Version string // MSize is the number of bytes to use for 9p packet payload @@ -65,11 +65,38 @@ func Mount(h hostRunner, source string, target string, c *MountConfig) error { return nil } +// returns either a raw UID number, or the subshell to resolve it. +func resolveUID(id string) string { + _, err := strconv.ParseInt(id, 10, 64) + if err == nil { + return id + } + // Preserve behavior where unset ID == 0 + if id == "" { + return "0" + } + return fmt.Sprintf(`$(id -u %s)`, id) +} + +// returns either a raw GID number, or the subshell to resolve it. +func resolveGID(id string) string { + _, err := strconv.ParseInt(id, 10, 64) + if err == nil { + return id + } + // Preserve behavior where unset ID == 0 + if id == "" { + return "0" + } + // Because `getent` isn't part of our ISO + return fmt.Sprintf(`$(grep ^%s: /etc/group | cut -d: -f3)`, id) +} + // mntCmd returns a mount command based on a config. func mntCmd(source string, target string, c *MountConfig) string { options := map[string]string{ - "dfltgid": strconv.Itoa(c.GID), - "dfltuid": strconv.Itoa(c.UID), + "dfltgid": resolveGID(c.GID), + "dfltuid": resolveUID(c.UID), } if c.Port != 0 { options["port"] = strconv.Itoa(c.Port) diff --git a/pkg/minikube/cluster/mount_test.go b/pkg/minikube/cluster/mount_test.go index 98f1f6ed297e..71b6cac01c6c 100644 --- a/pkg/minikube/cluster/mount_test.go +++ b/pkg/minikube/cluster/mount_test.go @@ -58,11 +58,21 @@ func TestMount(t *testing.T) { "sudo mkdir -m 700 -p target && sudo mount -t 9p -o dfltgid=0,dfltuid=0 src target", }, }, + { + name: "named uid", + source: "src", + target: "target", + cfg: &MountConfig{Type: "9p", Mode: os.FileMode(0700), UID: "docker", GID: "docker"}, + want: []string{ + "findmnt -T target && sudo umount target || true", + "sudo mkdir -m 700 -p target && sudo mount -t 9p -o dfltgid=$(grep ^docker: /etc/group | cut -d: -f3),dfltuid=$(id -u docker) src target", + }, + }, { name: "everything", source: "10.0.0.1", target: "/target", - cfg: &MountConfig{Type: "9p", Mode: os.FileMode(0777), UID: 82, GID: 72, Version: "9p2000.u", Options: map[string]string{ + cfg: &MountConfig{Type: "9p", Mode: os.FileMode(0777), UID: "82", GID: "72", Version: "9p2000.u", Options: map[string]string{ "noextend": "", "cache": "fscache", }}, diff --git a/test/integration/mount_test.go b/test/integration/mount_test.go index 08dd127a131d..6e426a223fc9 100644 --- a/test/integration/mount_test.go +++ b/test/integration/mount_test.go @@ -56,6 +56,8 @@ func testMounting(t *testing.T) { } else { mountCmd = fmt.Sprintf("mount %s:/mount-9p", tempDir) } + + t.Logf("Starting mount: %s", mountCmd) cmd, _, _ := minikubeRunner.RunDaemon2(mountCmd) defer func() { err := cmd.Process.Kill() @@ -81,12 +83,14 @@ func testMounting(t *testing.T) { // Create the pods we need outside the main test loop. setupTest := func() error { + t.Logf("Deploying pod from: %s", podPath) if _, err := kubectlRunner.RunCommand([]string{"create", "-f", podPath}); err != nil { return err } return nil } defer func() { + t.Logf("Deleting pod from: %s", podPath) if out, err := kubectlRunner.RunCommand([]string{"delete", "-f", podPath}); err != nil { t.Logf("delete -f %s failed: %v\noutput: %s\n", podPath, err, out) } @@ -104,6 +108,7 @@ func testMounting(t *testing.T) { if err := pkgutil.WaitForPodsWithLabelRunning(client, "default", selector); err != nil { t.Fatalf("Error waiting for busybox mount pod to be up: %v", err) } + t.Logf("Pods appear to be running") mountTest := func() error { path := filepath.Join(tempDir, "frompod") @@ -161,5 +166,4 @@ func testMounting(t *testing.T) { if err := util.Retry(t, mountTest, 5*time.Second, 40); err != nil { t.Fatalf("mountTest failed with error: %v", err) } - }