123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259 |
- // +build !windows
- package 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"
- "github.com/docker/docker/volume"
- )
- func TestBackportMountSpec(t *testing.T) {
- d := Daemon{containers: container.NewMemoryStore()}
- c := &container.Container{
- CommonContainer: container.CommonContainer{
- State: &container.State{},
- MountPoints: map[string]*volume.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{
- CommonContainer: container.CommonContainer{
- State: &container.State{},
- ID: "1",
- MountPoints: map[string]*volume.MountPoint{
- "/kumquat": {Destination: "/kumquat", Name: "data", RW: false, CopyData: true},
- },
- HostConfig: &containertypes.HostConfig{
- Binds: []string{
- "data:/kumquat:ro",
- },
- },
- },
- })
- type expected struct {
- mp *volume.MountPoint
- comment string
- }
- pretty := func(mp *volume.MountPoint) string {
- b, err := json.MarshalIndent(mp, "\t", " ")
- if err != nil {
- return fmt.Sprintf("%#v", mp)
- }
- return string(b)
- }
- for _, x := range []expected{
- {
- mp: &volume.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: &volume.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: &volume.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: &volume.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: &volume.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: &volume.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: &volume.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 propgation",
- },
- {
- mp: &volume.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: &volume.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))
- }
- }
- }
|