daemon_test.go 21 KB

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