mirror of
				https://github.com/moby/moby.git
				synced 2022-11-09 12:21:53 -05:00 
			
		
		
		
	This moves the platform specific stuff in a separate package and keeps the `volume` package and the defined interfaces light to import. Signed-off-by: Brian Goff <cpuguy83@gmail.com>
		
			
				
	
	
		
			256 lines
		
	
	
	
		
			7.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			256 lines
		
	
	
	
		
			7.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// +build !windows
 | 
						|
 | 
						|
package daemon // import "github.com/docker/docker/daemon"
 | 
						|
 | 
						|
import (
 | 
						|
	"encoding/json"
 | 
						|
	"fmt"
 | 
						|
	"reflect"
 | 
						|
	"testing"
 | 
						|
 | 
						|
	containertypes "github.com/docker/docker/api/types/container"
 | 
						|
	mounttypes "github.com/docker/docker/api/types/mount"
 | 
						|
	"github.com/docker/docker/container"
 | 
						|
	volumemounts "github.com/docker/docker/volume/mounts"
 | 
						|
)
 | 
						|
 | 
						|
func TestBackportMountSpec(t *testing.T) {
 | 
						|
	d := Daemon{containers: container.NewMemoryStore()}
 | 
						|
 | 
						|
	c := &container.Container{
 | 
						|
		State: &container.State{},
 | 
						|
		MountPoints: map[string]*volumemounts.MountPoint{
 | 
						|
			"/apple":      {Destination: "/apple", Source: "/var/lib/docker/volumes/12345678", Name: "12345678", RW: true, CopyData: true}, // anonymous volume
 | 
						|
			"/banana":     {Destination: "/banana", Source: "/var/lib/docker/volumes/data", Name: "data", RW: true, CopyData: true},        // named volume
 | 
						|
			"/cherry":     {Destination: "/cherry", Source: "/var/lib/docker/volumes/data", Name: "data", CopyData: true},                  // RO named volume
 | 
						|
			"/dates":      {Destination: "/dates", Source: "/var/lib/docker/volumes/data", Name: "data"},                                   // named volume nocopy
 | 
						|
			"/elderberry": {Destination: "/elderberry", Source: "/var/lib/docker/volumes/data", Name: "data"},                              // masks anon vol
 | 
						|
			"/fig":        {Destination: "/fig", Source: "/data", RW: true},                                                                // RW bind
 | 
						|
			"/guava":      {Destination: "/guava", Source: "/data", RW: false, Propagation: "shared"},                                      // RO bind + propagation
 | 
						|
			"/kumquat":    {Destination: "/kumquat", Name: "data", RW: false, CopyData: true},                                              // volumes-from
 | 
						|
 | 
						|
			// partially configured mountpoint due to #32613
 | 
						|
			// specifically, `mp.Spec.Source` is not set
 | 
						|
			"/honeydew": {
 | 
						|
				Type:        mounttypes.TypeVolume,
 | 
						|
				Destination: "/honeydew",
 | 
						|
				Name:        "data",
 | 
						|
				Source:      "/var/lib/docker/volumes/data",
 | 
						|
				Spec:        mounttypes.Mount{Type: mounttypes.TypeVolume, Target: "/honeydew", VolumeOptions: &mounttypes.VolumeOptions{NoCopy: true}},
 | 
						|
			},
 | 
						|
 | 
						|
			// from hostconfig.Mounts
 | 
						|
			"/jambolan": {
 | 
						|
				Type:        mounttypes.TypeVolume,
 | 
						|
				Destination: "/jambolan",
 | 
						|
				Source:      "/var/lib/docker/volumes/data",
 | 
						|
				RW:          true,
 | 
						|
				Name:        "data",
 | 
						|
				Spec:        mounttypes.Mount{Type: mounttypes.TypeVolume, Target: "/jambolan", Source: "data"},
 | 
						|
			},
 | 
						|
		},
 | 
						|
		HostConfig: &containertypes.HostConfig{
 | 
						|
			Binds: []string{
 | 
						|
				"data:/banana",
 | 
						|
				"data:/cherry:ro",
 | 
						|
				"data:/dates:ro,nocopy",
 | 
						|
				"data:/elderberry:ro,nocopy",
 | 
						|
				"/data:/fig",
 | 
						|
				"/data:/guava:ro,shared",
 | 
						|
				"data:/honeydew:nocopy",
 | 
						|
			},
 | 
						|
			VolumesFrom: []string{"1:ro"},
 | 
						|
			Mounts: []mounttypes.Mount{
 | 
						|
				{Type: mounttypes.TypeVolume, Target: "/jambolan"},
 | 
						|
			},
 | 
						|
		},
 | 
						|
		Config: &containertypes.Config{Volumes: map[string]struct{}{
 | 
						|
			"/apple":      {},
 | 
						|
			"/elderberry": {},
 | 
						|
		}},
 | 
						|
	}
 | 
						|
 | 
						|
	d.containers.Add("1", &container.Container{
 | 
						|
		State: &container.State{},
 | 
						|
		ID:    "1",
 | 
						|
		MountPoints: map[string]*volumemounts.MountPoint{
 | 
						|
			"/kumquat": {Destination: "/kumquat", Name: "data", RW: false, CopyData: true},
 | 
						|
		},
 | 
						|
		HostConfig: &containertypes.HostConfig{
 | 
						|
			Binds: []string{
 | 
						|
				"data:/kumquat:ro",
 | 
						|
			},
 | 
						|
		},
 | 
						|
	})
 | 
						|
 | 
						|
	type expected struct {
 | 
						|
		mp      *volumemounts.MountPoint
 | 
						|
		comment string
 | 
						|
	}
 | 
						|
 | 
						|
	pretty := func(mp *volumemounts.MountPoint) string {
 | 
						|
		b, err := json.MarshalIndent(mp, "\t", "    ")
 | 
						|
		if err != nil {
 | 
						|
			return fmt.Sprintf("%#v", mp)
 | 
						|
		}
 | 
						|
		return string(b)
 | 
						|
	}
 | 
						|
 | 
						|
	for _, x := range []expected{
 | 
						|
		{
 | 
						|
			mp: &volumemounts.MountPoint{
 | 
						|
				Type:        mounttypes.TypeVolume,
 | 
						|
				Destination: "/apple",
 | 
						|
				RW:          true,
 | 
						|
				Name:        "12345678",
 | 
						|
				Source:      "/var/lib/docker/volumes/12345678",
 | 
						|
				CopyData:    true,
 | 
						|
				Spec: mounttypes.Mount{
 | 
						|
					Type:   mounttypes.TypeVolume,
 | 
						|
					Source: "",
 | 
						|
					Target: "/apple",
 | 
						|
				},
 | 
						|
			},
 | 
						|
			comment: "anonymous volume",
 | 
						|
		},
 | 
						|
		{
 | 
						|
			mp: &volumemounts.MountPoint{
 | 
						|
				Type:        mounttypes.TypeVolume,
 | 
						|
				Destination: "/banana",
 | 
						|
				RW:          true,
 | 
						|
				Name:        "data",
 | 
						|
				Source:      "/var/lib/docker/volumes/data",
 | 
						|
				CopyData:    true,
 | 
						|
				Spec: mounttypes.Mount{
 | 
						|
					Type:   mounttypes.TypeVolume,
 | 
						|
					Source: "data",
 | 
						|
					Target: "/banana",
 | 
						|
				},
 | 
						|
			},
 | 
						|
			comment: "named volume",
 | 
						|
		},
 | 
						|
		{
 | 
						|
			mp: &volumemounts.MountPoint{
 | 
						|
				Type:        mounttypes.TypeVolume,
 | 
						|
				Destination: "/cherry",
 | 
						|
				Name:        "data",
 | 
						|
				Source:      "/var/lib/docker/volumes/data",
 | 
						|
				CopyData:    true,
 | 
						|
				Spec: mounttypes.Mount{
 | 
						|
					Type:     mounttypes.TypeVolume,
 | 
						|
					Source:   "data",
 | 
						|
					Target:   "/cherry",
 | 
						|
					ReadOnly: true,
 | 
						|
				},
 | 
						|
			},
 | 
						|
			comment: "read-only named volume",
 | 
						|
		},
 | 
						|
		{
 | 
						|
			mp: &volumemounts.MountPoint{
 | 
						|
				Type:        mounttypes.TypeVolume,
 | 
						|
				Destination: "/dates",
 | 
						|
				Name:        "data",
 | 
						|
				Source:      "/var/lib/docker/volumes/data",
 | 
						|
				Spec: mounttypes.Mount{
 | 
						|
					Type:          mounttypes.TypeVolume,
 | 
						|
					Source:        "data",
 | 
						|
					Target:        "/dates",
 | 
						|
					ReadOnly:      true,
 | 
						|
					VolumeOptions: &mounttypes.VolumeOptions{NoCopy: true},
 | 
						|
				},
 | 
						|
			},
 | 
						|
			comment: "named volume with nocopy",
 | 
						|
		},
 | 
						|
		{
 | 
						|
			mp: &volumemounts.MountPoint{
 | 
						|
				Type:        mounttypes.TypeVolume,
 | 
						|
				Destination: "/elderberry",
 | 
						|
				Name:        "data",
 | 
						|
				Source:      "/var/lib/docker/volumes/data",
 | 
						|
				Spec: mounttypes.Mount{
 | 
						|
					Type:          mounttypes.TypeVolume,
 | 
						|
					Source:        "data",
 | 
						|
					Target:        "/elderberry",
 | 
						|
					ReadOnly:      true,
 | 
						|
					VolumeOptions: &mounttypes.VolumeOptions{NoCopy: true},
 | 
						|
				},
 | 
						|
			},
 | 
						|
			comment: "masks an anonymous volume",
 | 
						|
		},
 | 
						|
		{
 | 
						|
			mp: &volumemounts.MountPoint{
 | 
						|
				Type:        mounttypes.TypeBind,
 | 
						|
				Destination: "/fig",
 | 
						|
				Source:      "/data",
 | 
						|
				RW:          true,
 | 
						|
				Spec: mounttypes.Mount{
 | 
						|
					Type:   mounttypes.TypeBind,
 | 
						|
					Source: "/data",
 | 
						|
					Target: "/fig",
 | 
						|
				},
 | 
						|
			},
 | 
						|
			comment: "bind mount with read/write",
 | 
						|
		},
 | 
						|
		{
 | 
						|
			mp: &volumemounts.MountPoint{
 | 
						|
				Type:        mounttypes.TypeBind,
 | 
						|
				Destination: "/guava",
 | 
						|
				Source:      "/data",
 | 
						|
				RW:          false,
 | 
						|
				Propagation: "shared",
 | 
						|
				Spec: mounttypes.Mount{
 | 
						|
					Type:        mounttypes.TypeBind,
 | 
						|
					Source:      "/data",
 | 
						|
					Target:      "/guava",
 | 
						|
					ReadOnly:    true,
 | 
						|
					BindOptions: &mounttypes.BindOptions{Propagation: "shared"},
 | 
						|
				},
 | 
						|
			},
 | 
						|
			comment: "bind mount with read/write + shared propagation",
 | 
						|
		},
 | 
						|
		{
 | 
						|
			mp: &volumemounts.MountPoint{
 | 
						|
				Type:        mounttypes.TypeVolume,
 | 
						|
				Destination: "/honeydew",
 | 
						|
				Source:      "/var/lib/docker/volumes/data",
 | 
						|
				RW:          true,
 | 
						|
				Propagation: "shared",
 | 
						|
				Spec: mounttypes.Mount{
 | 
						|
					Type:          mounttypes.TypeVolume,
 | 
						|
					Source:        "data",
 | 
						|
					Target:        "/honeydew",
 | 
						|
					VolumeOptions: &mounttypes.VolumeOptions{NoCopy: true},
 | 
						|
				},
 | 
						|
			},
 | 
						|
			comment: "partially configured named volume caused by #32613",
 | 
						|
		},
 | 
						|
		{
 | 
						|
			mp:      &(*c.MountPoints["/jambolan"]), // copy the mountpoint, expect no changes
 | 
						|
			comment: "volume defined in mounts API",
 | 
						|
		},
 | 
						|
		{
 | 
						|
			mp: &volumemounts.MountPoint{
 | 
						|
				Type:        mounttypes.TypeVolume,
 | 
						|
				Destination: "/kumquat",
 | 
						|
				Source:      "/var/lib/docker/volumes/data",
 | 
						|
				RW:          false,
 | 
						|
				Name:        "data",
 | 
						|
				Spec: mounttypes.Mount{
 | 
						|
					Type:     mounttypes.TypeVolume,
 | 
						|
					Source:   "data",
 | 
						|
					Target:   "/kumquat",
 | 
						|
					ReadOnly: true,
 | 
						|
				},
 | 
						|
			},
 | 
						|
			comment: "partially configured named volume caused by #32613",
 | 
						|
		},
 | 
						|
	} {
 | 
						|
 | 
						|
		mp := c.MountPoints[x.mp.Destination]
 | 
						|
		d.backportMountSpec(c)
 | 
						|
 | 
						|
		if !reflect.DeepEqual(mp.Spec, x.mp.Spec) {
 | 
						|
			t.Fatalf("%s\nexpected:\n\t%s\n\ngot:\n\t%s", x.comment, pretty(x.mp), pretty(mp))
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 |