github.com/psychoss/docker@v1.9.0/daemon/daemon_test.go (about)

     1  package daemon
     2  
     3  import (
     4  	"fmt"
     5  	"io/ioutil"
     6  	"os"
     7  	"path"
     8  	"path/filepath"
     9  	"testing"
    10  
    11  	"github.com/docker/docker/pkg/graphdb"
    12  	"github.com/docker/docker/pkg/stringid"
    13  	"github.com/docker/docker/pkg/truncindex"
    14  	"github.com/docker/docker/runconfig"
    15  	"github.com/docker/docker/volume"
    16  	volumedrivers "github.com/docker/docker/volume/drivers"
    17  	"github.com/docker/docker/volume/local"
    18  	"github.com/docker/docker/volume/store"
    19  )
    20  
    21  //
    22  // https://github.com/docker/docker/issues/8069
    23  //
    24  
    25  func TestGet(t *testing.T) {
    26  	c1 := &Container{
    27  		CommonContainer: CommonContainer{
    28  			ID:   "5a4ff6a163ad4533d22d69a2b8960bf7fafdcba06e72d2febdba229008b0bf57",
    29  			Name: "tender_bardeen",
    30  		},
    31  	}
    32  
    33  	c2 := &Container{
    34  		CommonContainer: CommonContainer{
    35  			ID:   "3cdbd1aa394fd68559fd1441d6eff2ab7c1e6363582c82febfaa8045df3bd8de",
    36  			Name: "drunk_hawking",
    37  		},
    38  	}
    39  
    40  	c3 := &Container{
    41  		CommonContainer: CommonContainer{
    42  			ID:   "3cdbd1aa394fd68559fd1441d6eff2abfafdcba06e72d2febdba229008b0bf57",
    43  			Name: "3cdbd1aa",
    44  		},
    45  	}
    46  
    47  	c4 := &Container{
    48  		CommonContainer: CommonContainer{
    49  			ID:   "75fb0b800922abdbef2d27e60abcdfaf7fb0698b2a96d22d3354da361a6ff4a5",
    50  			Name: "5a4ff6a163ad4533d22d69a2b8960bf7fafdcba06e72d2febdba229008b0bf57",
    51  		},
    52  	}
    53  
    54  	c5 := &Container{
    55  		CommonContainer: CommonContainer{
    56  			ID:   "d22d69a2b8960bf7fafdcba06e72d2febdba960bf7fafdcba06e72d2f9008b060b",
    57  			Name: "d22d69a2b896",
    58  		},
    59  	}
    60  
    61  	store := &contStore{
    62  		s: map[string]*Container{
    63  			c1.ID: c1,
    64  			c2.ID: c2,
    65  			c3.ID: c3,
    66  			c4.ID: c4,
    67  			c5.ID: c5,
    68  		},
    69  	}
    70  
    71  	index := truncindex.NewTruncIndex([]string{})
    72  	index.Add(c1.ID)
    73  	index.Add(c2.ID)
    74  	index.Add(c3.ID)
    75  	index.Add(c4.ID)
    76  	index.Add(c5.ID)
    77  
    78  	daemonTestDbPath := path.Join(os.TempDir(), "daemon_test.db")
    79  	graph, err := graphdb.NewSqliteConn(daemonTestDbPath)
    80  	if err != nil {
    81  		t.Fatalf("Failed to create daemon test sqlite database at %s", daemonTestDbPath)
    82  	}
    83  	graph.Set(c1.Name, c1.ID)
    84  	graph.Set(c2.Name, c2.ID)
    85  	graph.Set(c3.Name, c3.ID)
    86  	graph.Set(c4.Name, c4.ID)
    87  	graph.Set(c5.Name, c5.ID)
    88  
    89  	daemon := &Daemon{
    90  		containers:       store,
    91  		idIndex:          index,
    92  		containerGraphDB: graph,
    93  	}
    94  
    95  	if container, _ := daemon.Get("3cdbd1aa394fd68559fd1441d6eff2ab7c1e6363582c82febfaa8045df3bd8de"); container != c2 {
    96  		t.Fatal("Should explicitly match full container IDs")
    97  	}
    98  
    99  	if container, _ := daemon.Get("75fb0b8009"); container != c4 {
   100  		t.Fatal("Should match a partial ID")
   101  	}
   102  
   103  	if container, _ := daemon.Get("drunk_hawking"); container != c2 {
   104  		t.Fatal("Should match a full name")
   105  	}
   106  
   107  	// c3.Name is a partial match for both c3.ID and c2.ID
   108  	if c, _ := daemon.Get("3cdbd1aa"); c != c3 {
   109  		t.Fatal("Should match a full name even though it collides with another container's ID")
   110  	}
   111  
   112  	if container, _ := daemon.Get("d22d69a2b896"); container != c5 {
   113  		t.Fatal("Should match a container where the provided prefix is an exact match to the it's name, and is also a prefix for it's ID")
   114  	}
   115  
   116  	if _, err := daemon.Get("3cdbd1"); err == nil {
   117  		t.Fatal("Should return an error when provided a prefix that partially matches multiple container ID's")
   118  	}
   119  
   120  	if _, err := daemon.Get("nothing"); err == nil {
   121  		t.Fatal("Should return an error when provided a prefix that is neither a name or a partial match to an ID")
   122  	}
   123  
   124  	os.Remove(daemonTestDbPath)
   125  }
   126  
   127  func TestLoadWithVolume(t *testing.T) {
   128  	tmp, err := ioutil.TempDir("", "docker-daemon-test-")
   129  	if err != nil {
   130  		t.Fatal(err)
   131  	}
   132  	defer os.RemoveAll(tmp)
   133  
   134  	containerID := "d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e"
   135  	containerPath := filepath.Join(tmp, containerID)
   136  	if err := os.MkdirAll(containerPath, 0755); err != nil {
   137  		t.Fatal(err)
   138  	}
   139  
   140  	hostVolumeID := stringid.GenerateNonCryptoID()
   141  	vfsPath := filepath.Join(tmp, "vfs", "dir", hostVolumeID)
   142  	volumePath := filepath.Join(tmp, "volumes", hostVolumeID)
   143  
   144  	if err := os.MkdirAll(vfsPath, 0755); err != nil {
   145  		t.Fatal(err)
   146  	}
   147  	if err := os.MkdirAll(volumePath, 0755); err != nil {
   148  		t.Fatal(err)
   149  	}
   150  
   151  	content := filepath.Join(vfsPath, "helo")
   152  	if err := ioutil.WriteFile(content, []byte("HELO"), 0644); err != nil {
   153  		t.Fatal(err)
   154  	}
   155  
   156  	config := `{"State":{"Running":true,"Paused":false,"Restarting":false,"OOMKilled":false,"Dead":false,"Pid":2464,"ExitCode":0,
   157  "Error":"","StartedAt":"2015-05-26T16:48:53.869308965Z","FinishedAt":"0001-01-01T00:00:00Z"},
   158  "ID":"d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e","Created":"2015-05-26T16:48:53.7987917Z","Path":"top",
   159  "Args":[],"Config":{"Hostname":"d59df5276e7b","Domainname":"","User":"","Memory":0,"MemorySwap":0,"CpuShares":0,"Cpuset":"",
   160  "AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"PortSpecs":null,"ExposedPorts":null,"Tty":true,"OpenStdin":true,
   161  "StdinOnce":false,"Env":null,"Cmd":["top"],"Image":"ubuntu:latest","Volumes":null,"WorkingDir":"","Entrypoint":null,
   162  "NetworkDisabled":false,"MacAddress":"","OnBuild":null,"Labels":{}},"Image":"07f8e8c5e66084bef8f848877857537ffe1c47edd01a93af27e7161672ad0e95",
   163  "NetworkSettings":{"IPAddress":"172.17.0.1","IPPrefixLen":16,"MacAddress":"02:42:ac:11:00:01","LinkLocalIPv6Address":"fe80::42:acff:fe11:1",
   164  "LinkLocalIPv6PrefixLen":64,"GlobalIPv6Address":"","GlobalIPv6PrefixLen":0,"Gateway":"172.17.42.1","IPv6Gateway":"","Bridge":"docker0","Ports":{}},
   165  "ResolvConfPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/resolv.conf",
   166  "HostnamePath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/hostname",
   167  "HostsPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/hosts",
   168  "LogPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e-json.log",
   169  "Name":"/ubuntu","Driver":"aufs","ExecDriver":"native-0.2","MountLabel":"","ProcessLabel":"","AppArmorProfile":"","RestartCount":0,
   170  "UpdateDns":false,"Volumes":{"/vol1":"%s"},"VolumesRW":{"/vol1":true},"AppliedVolumesFrom":null}`
   171  
   172  	cfg := fmt.Sprintf(config, vfsPath)
   173  	if err = ioutil.WriteFile(filepath.Join(containerPath, "config.json"), []byte(cfg), 0644); err != nil {
   174  		t.Fatal(err)
   175  	}
   176  
   177  	hostConfig := `{"Binds":[],"ContainerIDFile":"","LxcConf":[],"Memory":0,"MemorySwap":0,"CpuShares":0,"CpusetCpus":"",
   178  "Privileged":false,"PortBindings":{},"Links":null,"PublishAllPorts":false,"Dns":null,"DnsOptions":null,"DnsSearch":null,"ExtraHosts":null,"VolumesFrom":null,
   179  "Devices":[],"NetworkMode":"bridge","IpcMode":"","PidMode":"","CapAdd":null,"CapDrop":null,"RestartPolicy":{"Name":"no","MaximumRetryCount":0},
   180  "SecurityOpt":null,"ReadonlyRootfs":false,"Ulimits":null,"LogConfig":{"Type":"","Config":null},"CgroupParent":""}`
   181  	if err = ioutil.WriteFile(filepath.Join(containerPath, "hostconfig.json"), []byte(hostConfig), 0644); err != nil {
   182  		t.Fatal(err)
   183  	}
   184  
   185  	daemon, err := initDaemonForVolumesTest(tmp)
   186  	if err != nil {
   187  		t.Fatal(err)
   188  	}
   189  	defer volumedrivers.Unregister(volume.DefaultDriverName)
   190  
   191  	c, err := daemon.load(containerID)
   192  	if err != nil {
   193  		t.Fatal(err)
   194  	}
   195  
   196  	err = daemon.verifyVolumesInfo(c)
   197  	if err != nil {
   198  		t.Fatal(err)
   199  	}
   200  
   201  	if len(c.MountPoints) != 1 {
   202  		t.Fatalf("Expected 1 volume mounted, was 0\n")
   203  	}
   204  
   205  	m := c.MountPoints["/vol1"]
   206  	if m.Name != hostVolumeID {
   207  		t.Fatalf("Expected mount name to be %s, was %s\n", hostVolumeID, m.Name)
   208  	}
   209  
   210  	if m.Destination != "/vol1" {
   211  		t.Fatalf("Expected mount destination /vol1, was %s\n", m.Destination)
   212  	}
   213  
   214  	if !m.RW {
   215  		t.Fatalf("Expected mount point to be RW but it was not\n")
   216  	}
   217  
   218  	if m.Driver != volume.DefaultDriverName {
   219  		t.Fatalf("Expected mount driver local, was %s\n", m.Driver)
   220  	}
   221  
   222  	newVolumeContent := filepath.Join(volumePath, local.VolumeDataPathName, "helo")
   223  	b, err := ioutil.ReadFile(newVolumeContent)
   224  	if err != nil {
   225  		t.Fatal(err)
   226  	}
   227  	if string(b) != "HELO" {
   228  		t.Fatalf("Expected HELO, was %s\n", string(b))
   229  	}
   230  }
   231  
   232  func TestLoadWithBindMount(t *testing.T) {
   233  	tmp, err := ioutil.TempDir("", "docker-daemon-test-")
   234  	if err != nil {
   235  		t.Fatal(err)
   236  	}
   237  	defer os.RemoveAll(tmp)
   238  
   239  	containerID := "d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e"
   240  	containerPath := filepath.Join(tmp, containerID)
   241  	if err = os.MkdirAll(containerPath, 0755); err != nil {
   242  		t.Fatal(err)
   243  	}
   244  
   245  	config := `{"State":{"Running":true,"Paused":false,"Restarting":false,"OOMKilled":false,"Dead":false,"Pid":2464,"ExitCode":0,
   246  "Error":"","StartedAt":"2015-05-26T16:48:53.869308965Z","FinishedAt":"0001-01-01T00:00:00Z"},
   247  "ID":"d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e","Created":"2015-05-26T16:48:53.7987917Z","Path":"top",
   248  "Args":[],"Config":{"Hostname":"d59df5276e7b","Domainname":"","User":"","Memory":0,"MemorySwap":0,"CpuShares":0,"Cpuset":"",
   249  "AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"PortSpecs":null,"ExposedPorts":null,"Tty":true,"OpenStdin":true,
   250  "StdinOnce":false,"Env":null,"Cmd":["top"],"Image":"ubuntu:latest","Volumes":null,"WorkingDir":"","Entrypoint":null,
   251  "NetworkDisabled":false,"MacAddress":"","OnBuild":null,"Labels":{}},"Image":"07f8e8c5e66084bef8f848877857537ffe1c47edd01a93af27e7161672ad0e95",
   252  "NetworkSettings":{"IPAddress":"172.17.0.1","IPPrefixLen":16,"MacAddress":"02:42:ac:11:00:01","LinkLocalIPv6Address":"fe80::42:acff:fe11:1",
   253  "LinkLocalIPv6PrefixLen":64,"GlobalIPv6Address":"","GlobalIPv6PrefixLen":0,"Gateway":"172.17.42.1","IPv6Gateway":"","Bridge":"docker0","Ports":{}},
   254  "ResolvConfPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/resolv.conf",
   255  "HostnamePath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/hostname",
   256  "HostsPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/hosts",
   257  "LogPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e-json.log",
   258  "Name":"/ubuntu","Driver":"aufs","ExecDriver":"native-0.2","MountLabel":"","ProcessLabel":"","AppArmorProfile":"","RestartCount":0,
   259  "UpdateDns":false,"Volumes":{"/vol1": "/vol1"},"VolumesRW":{"/vol1":true},"AppliedVolumesFrom":null}`
   260  
   261  	if err = ioutil.WriteFile(filepath.Join(containerPath, "config.json"), []byte(config), 0644); err != nil {
   262  		t.Fatal(err)
   263  	}
   264  
   265  	hostConfig := `{"Binds":["/vol1:/vol1"],"ContainerIDFile":"","LxcConf":[],"Memory":0,"MemorySwap":0,"CpuShares":0,"CpusetCpus":"",
   266  "Privileged":false,"PortBindings":{},"Links":null,"PublishAllPorts":false,"Dns":null,"DnsOptions":null,"DnsSearch":null,"ExtraHosts":null,"VolumesFrom":null,
   267  "Devices":[],"NetworkMode":"bridge","IpcMode":"","PidMode":"","CapAdd":null,"CapDrop":null,"RestartPolicy":{"Name":"no","MaximumRetryCount":0},
   268  "SecurityOpt":null,"ReadonlyRootfs":false,"Ulimits":null,"LogConfig":{"Type":"","Config":null},"CgroupParent":""}`
   269  	if err = ioutil.WriteFile(filepath.Join(containerPath, "hostconfig.json"), []byte(hostConfig), 0644); err != nil {
   270  		t.Fatal(err)
   271  	}
   272  
   273  	daemon, err := initDaemonForVolumesTest(tmp)
   274  	if err != nil {
   275  		t.Fatal(err)
   276  	}
   277  	defer volumedrivers.Unregister(volume.DefaultDriverName)
   278  
   279  	c, err := daemon.load(containerID)
   280  	if err != nil {
   281  		t.Fatal(err)
   282  	}
   283  
   284  	err = daemon.verifyVolumesInfo(c)
   285  	if err != nil {
   286  		t.Fatal(err)
   287  	}
   288  
   289  	if len(c.MountPoints) != 1 {
   290  		t.Fatalf("Expected 1 volume mounted, was 0\n")
   291  	}
   292  
   293  	m := c.MountPoints["/vol1"]
   294  	if m.Name != "" {
   295  		t.Fatalf("Expected empty mount name, was %s\n", m.Name)
   296  	}
   297  
   298  	if m.Source != "/vol1" {
   299  		t.Fatalf("Expected mount source /vol1, was %s\n", m.Source)
   300  	}
   301  
   302  	if m.Destination != "/vol1" {
   303  		t.Fatalf("Expected mount destination /vol1, was %s\n", m.Destination)
   304  	}
   305  
   306  	if !m.RW {
   307  		t.Fatalf("Expected mount point to be RW but it was not\n")
   308  	}
   309  }
   310  
   311  func TestLoadWithVolume17RC(t *testing.T) {
   312  	tmp, err := ioutil.TempDir("", "docker-daemon-test-")
   313  	if err != nil {
   314  		t.Fatal(err)
   315  	}
   316  	defer os.RemoveAll(tmp)
   317  
   318  	containerID := "d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e"
   319  	containerPath := filepath.Join(tmp, containerID)
   320  	if err := os.MkdirAll(containerPath, 0755); err != nil {
   321  		t.Fatal(err)
   322  	}
   323  
   324  	hostVolumeID := "6a3c03fc4a4e588561a543cc3bdd50089e27bd11bbb0e551e19bf735e2514101"
   325  	volumePath := filepath.Join(tmp, "volumes", hostVolumeID)
   326  
   327  	if err := os.MkdirAll(volumePath, 0755); err != nil {
   328  		t.Fatal(err)
   329  	}
   330  
   331  	content := filepath.Join(volumePath, "helo")
   332  	if err := ioutil.WriteFile(content, []byte("HELO"), 0644); err != nil {
   333  		t.Fatal(err)
   334  	}
   335  
   336  	config := `{"State":{"Running":true,"Paused":false,"Restarting":false,"OOMKilled":false,"Dead":false,"Pid":2464,"ExitCode":0,
   337  "Error":"","StartedAt":"2015-05-26T16:48:53.869308965Z","FinishedAt":"0001-01-01T00:00:00Z"},
   338  "ID":"d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e","Created":"2015-05-26T16:48:53.7987917Z","Path":"top",
   339  "Args":[],"Config":{"Hostname":"d59df5276e7b","Domainname":"","User":"","Memory":0,"MemorySwap":0,"CpuShares":0,"Cpuset":"",
   340  "AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"PortSpecs":null,"ExposedPorts":null,"Tty":true,"OpenStdin":true,
   341  "StdinOnce":false,"Env":null,"Cmd":["top"],"Image":"ubuntu:latest","Volumes":null,"WorkingDir":"","Entrypoint":null,
   342  "NetworkDisabled":false,"MacAddress":"","OnBuild":null,"Labels":{}},"Image":"07f8e8c5e66084bef8f848877857537ffe1c47edd01a93af27e7161672ad0e95",
   343  "NetworkSettings":{"IPAddress":"172.17.0.1","IPPrefixLen":16,"MacAddress":"02:42:ac:11:00:01","LinkLocalIPv6Address":"fe80::42:acff:fe11:1",
   344  "LinkLocalIPv6PrefixLen":64,"GlobalIPv6Address":"","GlobalIPv6PrefixLen":0,"Gateway":"172.17.42.1","IPv6Gateway":"","Bridge":"docker0","Ports":{}},
   345  "ResolvConfPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/resolv.conf",
   346  "HostnamePath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/hostname",
   347  "HostsPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/hosts",
   348  "LogPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e-json.log",
   349  "Name":"/ubuntu","Driver":"aufs","ExecDriver":"native-0.2","MountLabel":"","ProcessLabel":"","AppArmorProfile":"","RestartCount":0,
   350  "UpdateDns":false,"MountPoints":{"/vol1":{"Name":"6a3c03fc4a4e588561a543cc3bdd50089e27bd11bbb0e551e19bf735e2514101","Destination":"/vol1","Driver":"local","RW":true,"Source":"","Relabel":""}},"AppliedVolumesFrom":null}`
   351  
   352  	if err = ioutil.WriteFile(filepath.Join(containerPath, "config.json"), []byte(config), 0644); err != nil {
   353  		t.Fatal(err)
   354  	}
   355  
   356  	hostConfig := `{"Binds":[],"ContainerIDFile":"","LxcConf":[],"Memory":0,"MemorySwap":0,"CpuShares":0,"CpusetCpus":"",
   357  "Privileged":false,"PortBindings":{},"Links":null,"PublishAllPorts":false,"Dns":null,"DnsOptions":null,"DnsSearch":null,"ExtraHosts":null,"VolumesFrom":null,
   358  "Devices":[],"NetworkMode":"bridge","IpcMode":"","PidMode":"","CapAdd":null,"CapDrop":null,"RestartPolicy":{"Name":"no","MaximumRetryCount":0},
   359  "SecurityOpt":null,"ReadonlyRootfs":false,"Ulimits":null,"LogConfig":{"Type":"","Config":null},"CgroupParent":""}`
   360  	if err = ioutil.WriteFile(filepath.Join(containerPath, "hostconfig.json"), []byte(hostConfig), 0644); err != nil {
   361  		t.Fatal(err)
   362  	}
   363  
   364  	daemon, err := initDaemonForVolumesTest(tmp)
   365  	if err != nil {
   366  		t.Fatal(err)
   367  	}
   368  	defer volumedrivers.Unregister(volume.DefaultDriverName)
   369  
   370  	c, err := daemon.load(containerID)
   371  	if err != nil {
   372  		t.Fatal(err)
   373  	}
   374  
   375  	err = daemon.verifyVolumesInfo(c)
   376  	if err != nil {
   377  		t.Fatal(err)
   378  	}
   379  
   380  	if len(c.MountPoints) != 1 {
   381  		t.Fatalf("Expected 1 volume mounted, was 0\n")
   382  	}
   383  
   384  	m := c.MountPoints["/vol1"]
   385  	if m.Name != hostVolumeID {
   386  		t.Fatalf("Expected mount name to be %s, was %s\n", hostVolumeID, m.Name)
   387  	}
   388  
   389  	if m.Destination != "/vol1" {
   390  		t.Fatalf("Expected mount destination /vol1, was %s\n", m.Destination)
   391  	}
   392  
   393  	if !m.RW {
   394  		t.Fatalf("Expected mount point to be RW but it was not\n")
   395  	}
   396  
   397  	if m.Driver != volume.DefaultDriverName {
   398  		t.Fatalf("Expected mount driver local, was %s\n", m.Driver)
   399  	}
   400  
   401  	newVolumeContent := filepath.Join(volumePath, local.VolumeDataPathName, "helo")
   402  	b, err := ioutil.ReadFile(newVolumeContent)
   403  	if err != nil {
   404  		t.Fatal(err)
   405  	}
   406  	if string(b) != "HELO" {
   407  		t.Fatalf("Expected HELO, was %s\n", string(b))
   408  	}
   409  }
   410  
   411  func TestRemoveLocalVolumesFollowingSymlinks(t *testing.T) {
   412  	tmp, err := ioutil.TempDir("", "docker-daemon-test-")
   413  	if err != nil {
   414  		t.Fatal(err)
   415  	}
   416  	defer os.RemoveAll(tmp)
   417  
   418  	containerID := "d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e"
   419  	containerPath := filepath.Join(tmp, containerID)
   420  	if err := os.MkdirAll(containerPath, 0755); err != nil {
   421  		t.Fatal(err)
   422  	}
   423  
   424  	hostVolumeID := stringid.GenerateNonCryptoID()
   425  	vfsPath := filepath.Join(tmp, "vfs", "dir", hostVolumeID)
   426  	volumePath := filepath.Join(tmp, "volumes", hostVolumeID)
   427  
   428  	if err := os.MkdirAll(vfsPath, 0755); err != nil {
   429  		t.Fatal(err)
   430  	}
   431  	if err := os.MkdirAll(volumePath, 0755); err != nil {
   432  		t.Fatal(err)
   433  	}
   434  
   435  	content := filepath.Join(vfsPath, "helo")
   436  	if err := ioutil.WriteFile(content, []byte("HELO"), 0644); err != nil {
   437  		t.Fatal(err)
   438  	}
   439  
   440  	config := `{"State":{"Running":true,"Paused":false,"Restarting":false,"OOMKilled":false,"Dead":false,"Pid":2464,"ExitCode":0,
   441  "Error":"","StartedAt":"2015-05-26T16:48:53.869308965Z","FinishedAt":"0001-01-01T00:00:00Z"},
   442  "ID":"d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e","Created":"2015-05-26T16:48:53.7987917Z","Path":"top",
   443  "Args":[],"Config":{"Hostname":"d59df5276e7b","Domainname":"","User":"","Memory":0,"MemorySwap":0,"CpuShares":0,"Cpuset":"",
   444  "AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"PortSpecs":null,"ExposedPorts":null,"Tty":true,"OpenStdin":true,
   445  "StdinOnce":false,"Env":null,"Cmd":["top"],"Image":"ubuntu:latest","Volumes":null,"WorkingDir":"","Entrypoint":null,
   446  "NetworkDisabled":false,"MacAddress":"","OnBuild":null,"Labels":{}},"Image":"07f8e8c5e66084bef8f848877857537ffe1c47edd01a93af27e7161672ad0e95",
   447  "NetworkSettings":{"IPAddress":"172.17.0.1","IPPrefixLen":16,"MacAddress":"02:42:ac:11:00:01","LinkLocalIPv6Address":"fe80::42:acff:fe11:1",
   448  "LinkLocalIPv6PrefixLen":64,"GlobalIPv6Address":"","GlobalIPv6PrefixLen":0,"Gateway":"172.17.42.1","IPv6Gateway":"","Bridge":"docker0","Ports":{}},
   449  "ResolvConfPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/resolv.conf",
   450  "HostnamePath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/hostname",
   451  "HostsPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/hosts",
   452  "LogPath":"/var/lib/docker/containers/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e/d59df5276e7b219d510fe70565e0404bc06350e0d4b43fe961f22f339980170e-json.log",
   453  "Name":"/ubuntu","Driver":"aufs","ExecDriver":"native-0.2","MountLabel":"","ProcessLabel":"","AppArmorProfile":"","RestartCount":0,
   454  "UpdateDns":false,"Volumes":{"/vol1":"%s"},"VolumesRW":{"/vol1":true},"AppliedVolumesFrom":null}`
   455  
   456  	cfg := fmt.Sprintf(config, vfsPath)
   457  	if err = ioutil.WriteFile(filepath.Join(containerPath, "config.json"), []byte(cfg), 0644); err != nil {
   458  		t.Fatal(err)
   459  	}
   460  
   461  	hostConfig := `{"Binds":[],"ContainerIDFile":"","LxcConf":[],"Memory":0,"MemorySwap":0,"CpuShares":0,"CpusetCpus":"",
   462  "Privileged":false,"PortBindings":{},"Links":null,"PublishAllPorts":false,"Dns":null,"DnsOptions":null,"DnsSearch":null,"ExtraHosts":null,"VolumesFrom":null,
   463  "Devices":[],"NetworkMode":"bridge","IpcMode":"","PidMode":"","CapAdd":null,"CapDrop":null,"RestartPolicy":{"Name":"no","MaximumRetryCount":0},
   464  "SecurityOpt":null,"ReadonlyRootfs":false,"Ulimits":null,"LogConfig":{"Type":"","Config":null},"CgroupParent":""}`
   465  	if err = ioutil.WriteFile(filepath.Join(containerPath, "hostconfig.json"), []byte(hostConfig), 0644); err != nil {
   466  		t.Fatal(err)
   467  	}
   468  
   469  	daemon, err := initDaemonForVolumesTest(tmp)
   470  	if err != nil {
   471  		t.Fatal(err)
   472  	}
   473  	defer volumedrivers.Unregister(volume.DefaultDriverName)
   474  
   475  	c, err := daemon.load(containerID)
   476  	if err != nil {
   477  		t.Fatal(err)
   478  	}
   479  
   480  	err = daemon.verifyVolumesInfo(c)
   481  	if err != nil {
   482  		t.Fatal(err)
   483  	}
   484  
   485  	if len(c.MountPoints) != 1 {
   486  		t.Fatalf("Expected 1 volume mounted, was 0\n")
   487  	}
   488  
   489  	m := c.MountPoints["/vol1"]
   490  	_, err = daemon.VolumeCreate(m.Name, m.Driver, nil)
   491  	if err != nil {
   492  		t.Fatal(err)
   493  	}
   494  
   495  	if err := daemon.VolumeRm(m.Name); err != nil {
   496  		t.Fatal(err)
   497  	}
   498  
   499  	fi, err := os.Stat(vfsPath)
   500  	if err == nil || !os.IsNotExist(err) {
   501  		t.Fatalf("Expected vfs path to not exist: %v - %v\n", fi, err)
   502  	}
   503  }
   504  
   505  func initDaemonForVolumesTest(tmp string) (*Daemon, error) {
   506  	daemon := &Daemon{
   507  		repository: tmp,
   508  		root:       tmp,
   509  		volumes:    store.New(),
   510  	}
   511  
   512  	volumesDriver, err := local.New(tmp, 0, 0)
   513  	if err != nil {
   514  		return nil, err
   515  	}
   516  	volumedrivers.Register(volumesDriver, volumesDriver.Name())
   517  
   518  	return daemon, nil
   519  }
   520  
   521  func TestParseSecurityOpt(t *testing.T) {
   522  	container := &Container{}
   523  	config := &runconfig.HostConfig{}
   524  
   525  	// test apparmor
   526  	config.SecurityOpt = []string{"apparmor:test_profile"}
   527  	if err := parseSecurityOpt(container, config); err != nil {
   528  		t.Fatalf("Unexpected parseSecurityOpt error: %v", err)
   529  	}
   530  	if container.AppArmorProfile != "test_profile" {
   531  		t.Fatalf("Unexpected AppArmorProfile, expected: \"test_profile\", got %q", container.AppArmorProfile)
   532  	}
   533  
   534  	// test valid label
   535  	config.SecurityOpt = []string{"label:user:USER"}
   536  	if err := parseSecurityOpt(container, config); err != nil {
   537  		t.Fatalf("Unexpected parseSecurityOpt error: %v", err)
   538  	}
   539  
   540  	// test invalid label
   541  	config.SecurityOpt = []string{"label"}
   542  	if err := parseSecurityOpt(container, config); err == nil {
   543  		t.Fatal("Expected parseSecurityOpt error, got nil")
   544  	}
   545  
   546  	// test invalid opt
   547  	config.SecurityOpt = []string{"test"}
   548  	if err := parseSecurityOpt(container, config); err == nil {
   549  		t.Fatal("Expected parseSecurityOpt error, got nil")
   550  	}
   551  }