Allow mount to work when the uid/gid of docker changes

pull/3989/head
Thomas Stromberg 2019-03-26 14:27:50 -07:00
parent 1e8bd6f060
commit 7233a2d50d
4 changed files with 53 additions and 12 deletions

View File

@ -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")

View File

@ -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)

View File

@ -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",
}},

View File

@ -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)
}
}