container_test.go 34 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432
  1. package docker
  2. import (
  3. "bufio"
  4. "fmt"
  5. "github.com/dotcloud/docker/runconfig"
  6. "github.com/dotcloud/docker/utils"
  7. "io"
  8. "io/ioutil"
  9. "os"
  10. "path"
  11. "regexp"
  12. "sort"
  13. "strings"
  14. "testing"
  15. "time"
  16. )
  17. func TestMultipleAttachRestart(t *testing.T) {
  18. daemon := mkDaemon(t)
  19. defer nuke(daemon)
  20. container, _, _ := mkContainer(
  21. daemon,
  22. []string{"_", "/bin/sh", "-c", "i=1; while [ $i -le 5 ]; do i=`expr $i + 1`; echo hello; done"},
  23. t,
  24. )
  25. defer daemon.Destroy(container)
  26. // Simulate 3 client attaching to the container and stop/restart
  27. stdout1, err := container.StdoutPipe()
  28. if err != nil {
  29. t.Fatal(err)
  30. }
  31. stdout2, err := container.StdoutPipe()
  32. if err != nil {
  33. t.Fatal(err)
  34. }
  35. stdout3, err := container.StdoutPipe()
  36. if err != nil {
  37. t.Fatal(err)
  38. }
  39. if err := container.Start(); err != nil {
  40. t.Fatal(err)
  41. }
  42. l1, err := bufio.NewReader(stdout1).ReadString('\n')
  43. if err != nil {
  44. t.Fatal(err)
  45. }
  46. if strings.Trim(l1, " \r\n") != "hello" {
  47. t.Fatalf("Unexpected output. Expected [%s], received [%s]", "hello", l1)
  48. }
  49. l2, err := bufio.NewReader(stdout2).ReadString('\n')
  50. if err != nil {
  51. t.Fatal(err)
  52. }
  53. if strings.Trim(l2, " \r\n") != "hello" {
  54. t.Fatalf("Unexpected output. Expected [%s], received [%s]", "hello", l2)
  55. }
  56. l3, err := bufio.NewReader(stdout3).ReadString('\n')
  57. if err != nil {
  58. t.Fatal(err)
  59. }
  60. if strings.Trim(l3, " \r\n") != "hello" {
  61. t.Fatalf("Unexpected output. Expected [%s], received [%s]", "hello", l3)
  62. }
  63. if err := container.Stop(10); err != nil {
  64. t.Fatal(err)
  65. }
  66. stdout1, err = container.StdoutPipe()
  67. if err != nil {
  68. t.Fatal(err)
  69. }
  70. stdout2, err = container.StdoutPipe()
  71. if err != nil {
  72. t.Fatal(err)
  73. }
  74. stdout3, err = container.StdoutPipe()
  75. if err != nil {
  76. t.Fatal(err)
  77. }
  78. if err := container.Start(); err != nil {
  79. t.Fatal(err)
  80. }
  81. setTimeout(t, "Timeout reading from the process", 3*time.Second, func() {
  82. l1, err = bufio.NewReader(stdout1).ReadString('\n')
  83. if err != nil {
  84. t.Fatal(err)
  85. }
  86. if strings.Trim(l1, " \r\n") != "hello" {
  87. t.Fatalf("Unexpected output. Expected [%s], received [%s]", "hello", l1)
  88. }
  89. l2, err = bufio.NewReader(stdout2).ReadString('\n')
  90. if err != nil {
  91. t.Fatal(err)
  92. }
  93. if strings.Trim(l2, " \r\n") != "hello" {
  94. t.Fatalf("Unexpected output. Expected [%s], received [%s]", "hello", l2)
  95. }
  96. l3, err = bufio.NewReader(stdout3).ReadString('\n')
  97. if err != nil {
  98. t.Fatal(err)
  99. }
  100. if strings.Trim(l3, " \r\n") != "hello" {
  101. t.Fatalf("Unexpected output. Expected [%s], received [%s]", "hello", l3)
  102. }
  103. })
  104. container.Wait()
  105. }
  106. func TestDiff(t *testing.T) {
  107. eng := NewTestEngine(t)
  108. daemon := mkDaemonFromEngine(eng, t)
  109. defer nuke(daemon)
  110. // Create a container and remove a file
  111. container1, _, _ := mkContainer(daemon, []string{"_", "/bin/rm", "/etc/passwd"}, t)
  112. defer daemon.Destroy(container1)
  113. // The changelog should be empty and not fail before run. See #1705
  114. c, err := container1.Changes()
  115. if err != nil {
  116. t.Fatal(err)
  117. }
  118. if len(c) != 0 {
  119. t.Fatalf("Changelog should be empty before run")
  120. }
  121. if err := container1.Run(); err != nil {
  122. t.Fatal(err)
  123. }
  124. // Check the changelog
  125. c, err = container1.Changes()
  126. if err != nil {
  127. t.Fatal(err)
  128. }
  129. success := false
  130. for _, elem := range c {
  131. if elem.Path == "/etc/passwd" && elem.Kind == 2 {
  132. success = true
  133. }
  134. }
  135. if !success {
  136. t.Fatalf("/etc/passwd as been removed but is not present in the diff")
  137. }
  138. // Commit the container
  139. img, err := daemon.Commit(container1, "", "", "unit test commited image - diff", "", nil)
  140. if err != nil {
  141. t.Fatal(err)
  142. }
  143. // Create a new container from the commited image
  144. container2, _, _ := mkContainer(daemon, []string{img.ID, "cat", "/etc/passwd"}, t)
  145. defer daemon.Destroy(container2)
  146. if err := container2.Run(); err != nil {
  147. t.Fatal(err)
  148. }
  149. // Check the changelog
  150. c, err = container2.Changes()
  151. if err != nil {
  152. t.Fatal(err)
  153. }
  154. for _, elem := range c {
  155. if elem.Path == "/etc/passwd" {
  156. t.Fatalf("/etc/passwd should not be present in the diff after commit.")
  157. }
  158. }
  159. // Create a new container
  160. container3, _, _ := mkContainer(daemon, []string{"_", "rm", "/bin/httpd"}, t)
  161. defer daemon.Destroy(container3)
  162. if err := container3.Run(); err != nil {
  163. t.Fatal(err)
  164. }
  165. // Check the changelog
  166. c, err = container3.Changes()
  167. if err != nil {
  168. t.Fatal(err)
  169. }
  170. success = false
  171. for _, elem := range c {
  172. if elem.Path == "/bin/httpd" && elem.Kind == 2 {
  173. success = true
  174. }
  175. }
  176. if !success {
  177. t.Fatalf("/bin/httpd should be present in the diff after commit.")
  178. }
  179. }
  180. func TestCommitAutoRun(t *testing.T) {
  181. daemon := mkDaemon(t)
  182. defer nuke(daemon)
  183. container1, _, _ := mkContainer(daemon, []string{"_", "/bin/sh", "-c", "echo hello > /world"}, t)
  184. defer daemon.Destroy(container1)
  185. if container1.State.IsRunning() {
  186. t.Errorf("Container shouldn't be running")
  187. }
  188. if err := container1.Run(); err != nil {
  189. t.Fatal(err)
  190. }
  191. if container1.State.IsRunning() {
  192. t.Errorf("Container shouldn't be running")
  193. }
  194. img, err := daemon.Commit(container1, "", "", "unit test commited image", "", &runconfig.Config{Cmd: []string{"cat", "/world"}})
  195. if err != nil {
  196. t.Error(err)
  197. }
  198. // FIXME: Make a TestCommit that stops here and check docker.root/layers/img.id/world
  199. container2, _, _ := mkContainer(daemon, []string{img.ID}, t)
  200. defer daemon.Destroy(container2)
  201. stdout, err := container2.StdoutPipe()
  202. if err != nil {
  203. t.Fatal(err)
  204. }
  205. stderr, err := container2.StderrPipe()
  206. if err != nil {
  207. t.Fatal(err)
  208. }
  209. if err := container2.Start(); err != nil {
  210. t.Fatal(err)
  211. }
  212. container2.Wait()
  213. output, err := ioutil.ReadAll(stdout)
  214. if err != nil {
  215. t.Fatal(err)
  216. }
  217. output2, err := ioutil.ReadAll(stderr)
  218. if err != nil {
  219. t.Fatal(err)
  220. }
  221. if err := stdout.Close(); err != nil {
  222. t.Fatal(err)
  223. }
  224. if err := stderr.Close(); err != nil {
  225. t.Fatal(err)
  226. }
  227. if string(output) != "hello\n" {
  228. t.Fatalf("Unexpected output. Expected %s, received: %s (err: %s)", "hello\n", output, output2)
  229. }
  230. }
  231. func TestCommitRun(t *testing.T) {
  232. daemon := mkDaemon(t)
  233. defer nuke(daemon)
  234. container1, _, _ := mkContainer(daemon, []string{"_", "/bin/sh", "-c", "echo hello > /world"}, t)
  235. defer daemon.Destroy(container1)
  236. if container1.State.IsRunning() {
  237. t.Errorf("Container shouldn't be running")
  238. }
  239. if err := container1.Run(); err != nil {
  240. t.Fatal(err)
  241. }
  242. if container1.State.IsRunning() {
  243. t.Errorf("Container shouldn't be running")
  244. }
  245. img, err := daemon.Commit(container1, "", "", "unit test commited image", "", nil)
  246. if err != nil {
  247. t.Error(err)
  248. }
  249. // FIXME: Make a TestCommit that stops here and check docker.root/layers/img.id/world
  250. container2, _, _ := mkContainer(daemon, []string{img.ID, "cat", "/world"}, t)
  251. defer daemon.Destroy(container2)
  252. stdout, err := container2.StdoutPipe()
  253. if err != nil {
  254. t.Fatal(err)
  255. }
  256. stderr, err := container2.StderrPipe()
  257. if err != nil {
  258. t.Fatal(err)
  259. }
  260. if err := container2.Start(); err != nil {
  261. t.Fatal(err)
  262. }
  263. container2.Wait()
  264. output, err := ioutil.ReadAll(stdout)
  265. if err != nil {
  266. t.Fatal(err)
  267. }
  268. output2, err := ioutil.ReadAll(stderr)
  269. if err != nil {
  270. t.Fatal(err)
  271. }
  272. if err := stdout.Close(); err != nil {
  273. t.Fatal(err)
  274. }
  275. if err := stderr.Close(); err != nil {
  276. t.Fatal(err)
  277. }
  278. if string(output) != "hello\n" {
  279. t.Fatalf("Unexpected output. Expected %s, received: %s (err: %s)", "hello\n", output, output2)
  280. }
  281. }
  282. func TestStart(t *testing.T) {
  283. daemon := mkDaemon(t)
  284. defer nuke(daemon)
  285. container, _, _ := mkContainer(daemon, []string{"-i", "_", "/bin/cat"}, t)
  286. defer daemon.Destroy(container)
  287. cStdin, err := container.StdinPipe()
  288. if err != nil {
  289. t.Fatal(err)
  290. }
  291. if err := container.Start(); err != nil {
  292. t.Fatal(err)
  293. }
  294. // Give some time to the process to start
  295. container.WaitTimeout(500 * time.Millisecond)
  296. if !container.State.IsRunning() {
  297. t.Errorf("Container should be running")
  298. }
  299. if err := container.Start(); err != nil {
  300. t.Fatalf("A running container should be able to be started")
  301. }
  302. // Try to avoid the timeout in destroy. Best effort, don't check error
  303. cStdin.Close()
  304. container.WaitTimeout(2 * time.Second)
  305. }
  306. func TestCpuShares(t *testing.T) {
  307. _, err1 := os.Stat("/sys/fs/cgroup/cpuacct,cpu")
  308. _, err2 := os.Stat("/sys/fs/cgroup/cpu,cpuacct")
  309. if err1 == nil || err2 == nil {
  310. t.Skip("Fixme. Setting cpu cgroup shares doesn't work in dind on a Fedora host. The lxc utils are confused by the cpu,cpuacct mount.")
  311. }
  312. daemon := mkDaemon(t)
  313. defer nuke(daemon)
  314. container, _, _ := mkContainer(daemon, []string{"-m", "33554432", "-c", "1000", "-i", "_", "/bin/cat"}, t)
  315. defer daemon.Destroy(container)
  316. cStdin, err := container.StdinPipe()
  317. if err != nil {
  318. t.Fatal(err)
  319. }
  320. if err := container.Start(); err != nil {
  321. t.Fatal(err)
  322. }
  323. // Give some time to the process to start
  324. container.WaitTimeout(500 * time.Millisecond)
  325. if !container.State.IsRunning() {
  326. t.Errorf("Container should be running")
  327. }
  328. if err := container.Start(); err != nil {
  329. t.Fatalf("A running container should be able to be started")
  330. }
  331. // Try to avoid the timeout in destroy. Best effort, don't check error
  332. cStdin.Close()
  333. container.WaitTimeout(2 * time.Second)
  334. }
  335. func TestRun(t *testing.T) {
  336. daemon := mkDaemon(t)
  337. defer nuke(daemon)
  338. container, _, _ := mkContainer(daemon, []string{"_", "ls", "-al"}, t)
  339. defer daemon.Destroy(container)
  340. if container.State.IsRunning() {
  341. t.Errorf("Container shouldn't be running")
  342. }
  343. if err := container.Run(); err != nil {
  344. t.Fatal(err)
  345. }
  346. if container.State.IsRunning() {
  347. t.Errorf("Container shouldn't be running")
  348. }
  349. }
  350. func TestOutput(t *testing.T) {
  351. daemon := mkDaemon(t)
  352. defer nuke(daemon)
  353. container, _, err := daemon.Create(
  354. &runconfig.Config{
  355. Image: GetTestImage(daemon).ID,
  356. Cmd: []string{"echo", "-n", "foobar"},
  357. },
  358. "",
  359. )
  360. if err != nil {
  361. t.Fatal(err)
  362. }
  363. defer daemon.Destroy(container)
  364. output, err := container.Output()
  365. if err != nil {
  366. t.Fatal(err)
  367. }
  368. if string(output) != "foobar" {
  369. t.Fatalf("%s != %s", string(output), "foobar")
  370. }
  371. }
  372. func TestKillDifferentUser(t *testing.T) {
  373. daemon := mkDaemon(t)
  374. defer nuke(daemon)
  375. container, _, err := daemon.Create(&runconfig.Config{
  376. Image: GetTestImage(daemon).ID,
  377. Cmd: []string{"cat"},
  378. OpenStdin: true,
  379. User: "daemon",
  380. },
  381. "",
  382. )
  383. if err != nil {
  384. t.Fatal(err)
  385. }
  386. defer daemon.Destroy(container)
  387. // FIXME @shykes: this seems redundant, but is very old, I'm leaving it in case
  388. // there is a side effect I'm not seeing.
  389. // defer container.stdin.Close()
  390. if container.State.IsRunning() {
  391. t.Errorf("Container shouldn't be running")
  392. }
  393. if err := container.Start(); err != nil {
  394. t.Fatal(err)
  395. }
  396. setTimeout(t, "Waiting for the container to be started timed out", 2*time.Second, func() {
  397. for !container.State.IsRunning() {
  398. time.Sleep(10 * time.Millisecond)
  399. }
  400. })
  401. setTimeout(t, "read/write assertion timed out", 2*time.Second, func() {
  402. out, _ := container.StdoutPipe()
  403. in, _ := container.StdinPipe()
  404. if err := assertPipe("hello\n", "hello", out, in, 150); err != nil {
  405. t.Fatal(err)
  406. }
  407. })
  408. if err := container.Kill(); err != nil {
  409. t.Fatal(err)
  410. }
  411. if container.State.IsRunning() {
  412. t.Errorf("Container shouldn't be running")
  413. }
  414. container.Wait()
  415. if container.State.IsRunning() {
  416. t.Errorf("Container shouldn't be running")
  417. }
  418. // Try stopping twice
  419. if err := container.Kill(); err != nil {
  420. t.Fatal(err)
  421. }
  422. }
  423. // Test that creating a container with a volume doesn't crash. Regression test for #995.
  424. func TestCreateVolume(t *testing.T) {
  425. eng := NewTestEngine(t)
  426. daemon := mkDaemonFromEngine(eng, t)
  427. defer nuke(daemon)
  428. config, hc, _, err := runconfig.Parse([]string{"-v", "/var/lib/data", unitTestImageID, "echo", "hello", "world"}, nil)
  429. if err != nil {
  430. t.Fatal(err)
  431. }
  432. jobCreate := eng.Job("create")
  433. if err := jobCreate.ImportEnv(config); err != nil {
  434. t.Fatal(err)
  435. }
  436. var id string
  437. jobCreate.Stdout.AddString(&id)
  438. if err := jobCreate.Run(); err != nil {
  439. t.Fatal(err)
  440. }
  441. jobStart := eng.Job("start", id)
  442. if err := jobStart.ImportEnv(hc); err != nil {
  443. t.Fatal(err)
  444. }
  445. if err := jobStart.Run(); err != nil {
  446. t.Fatal(err)
  447. }
  448. // FIXME: this hack can be removed once Wait is a job
  449. c := daemon.Get(id)
  450. if c == nil {
  451. t.Fatalf("Couldn't retrieve container %s from daemon", id)
  452. }
  453. c.WaitTimeout(500 * time.Millisecond)
  454. c.Wait()
  455. }
  456. func TestKill(t *testing.T) {
  457. daemon := mkDaemon(t)
  458. defer nuke(daemon)
  459. container, _, err := daemon.Create(&runconfig.Config{
  460. Image: GetTestImage(daemon).ID,
  461. Cmd: []string{"sleep", "2"},
  462. },
  463. "",
  464. )
  465. if err != nil {
  466. t.Fatal(err)
  467. }
  468. defer daemon.Destroy(container)
  469. if container.State.IsRunning() {
  470. t.Errorf("Container shouldn't be running")
  471. }
  472. if err := container.Start(); err != nil {
  473. t.Fatal(err)
  474. }
  475. // Give some time to lxc to spawn the process
  476. container.WaitTimeout(500 * time.Millisecond)
  477. if !container.State.IsRunning() {
  478. t.Errorf("Container should be running")
  479. }
  480. if err := container.Kill(); err != nil {
  481. t.Fatal(err)
  482. }
  483. if container.State.IsRunning() {
  484. t.Errorf("Container shouldn't be running")
  485. }
  486. container.Wait()
  487. if container.State.IsRunning() {
  488. t.Errorf("Container shouldn't be running")
  489. }
  490. // Try stopping twice
  491. if err := container.Kill(); err != nil {
  492. t.Fatal(err)
  493. }
  494. }
  495. func TestExitCode(t *testing.T) {
  496. daemon := mkDaemon(t)
  497. defer nuke(daemon)
  498. trueContainer, _, err := daemon.Create(&runconfig.Config{
  499. Image: GetTestImage(daemon).ID,
  500. Cmd: []string{"/bin/true"},
  501. }, "")
  502. if err != nil {
  503. t.Fatal(err)
  504. }
  505. defer daemon.Destroy(trueContainer)
  506. if err := trueContainer.Run(); err != nil {
  507. t.Fatal(err)
  508. }
  509. if code := trueContainer.State.GetExitCode(); code != 0 {
  510. t.Fatalf("Unexpected exit code %d (expected 0)", code)
  511. }
  512. falseContainer, _, err := daemon.Create(&runconfig.Config{
  513. Image: GetTestImage(daemon).ID,
  514. Cmd: []string{"/bin/false"},
  515. }, "")
  516. if err != nil {
  517. t.Fatal(err)
  518. }
  519. defer daemon.Destroy(falseContainer)
  520. if err := falseContainer.Run(); err != nil {
  521. t.Fatal(err)
  522. }
  523. if code := falseContainer.State.GetExitCode(); code != 1 {
  524. t.Fatalf("Unexpected exit code %d (expected 1)", code)
  525. }
  526. }
  527. func TestRestart(t *testing.T) {
  528. daemon := mkDaemon(t)
  529. defer nuke(daemon)
  530. container, _, err := daemon.Create(&runconfig.Config{
  531. Image: GetTestImage(daemon).ID,
  532. Cmd: []string{"echo", "-n", "foobar"},
  533. },
  534. "",
  535. )
  536. if err != nil {
  537. t.Fatal(err)
  538. }
  539. defer daemon.Destroy(container)
  540. output, err := container.Output()
  541. if err != nil {
  542. t.Fatal(err)
  543. }
  544. if string(output) != "foobar" {
  545. t.Error(string(output))
  546. }
  547. // Run the container again and check the output
  548. output, err = container.Output()
  549. if err != nil {
  550. t.Fatal(err)
  551. }
  552. if string(output) != "foobar" {
  553. t.Error(string(output))
  554. }
  555. }
  556. func TestRestartStdin(t *testing.T) {
  557. daemon := mkDaemon(t)
  558. defer nuke(daemon)
  559. container, _, err := daemon.Create(&runconfig.Config{
  560. Image: GetTestImage(daemon).ID,
  561. Cmd: []string{"cat"},
  562. OpenStdin: true,
  563. },
  564. "",
  565. )
  566. if err != nil {
  567. t.Fatal(err)
  568. }
  569. defer daemon.Destroy(container)
  570. stdin, err := container.StdinPipe()
  571. if err != nil {
  572. t.Fatal(err)
  573. }
  574. stdout, err := container.StdoutPipe()
  575. if err != nil {
  576. t.Fatal(err)
  577. }
  578. if err := container.Start(); err != nil {
  579. t.Fatal(err)
  580. }
  581. if _, err := io.WriteString(stdin, "hello world"); err != nil {
  582. t.Fatal(err)
  583. }
  584. if err := stdin.Close(); err != nil {
  585. t.Fatal(err)
  586. }
  587. container.Wait()
  588. output, err := ioutil.ReadAll(stdout)
  589. if err != nil {
  590. t.Fatal(err)
  591. }
  592. if err := stdout.Close(); err != nil {
  593. t.Fatal(err)
  594. }
  595. if string(output) != "hello world" {
  596. t.Fatalf("Unexpected output. Expected %s, received: %s", "hello world", string(output))
  597. }
  598. // Restart and try again
  599. stdin, err = container.StdinPipe()
  600. if err != nil {
  601. t.Fatal(err)
  602. }
  603. stdout, err = container.StdoutPipe()
  604. if err != nil {
  605. t.Fatal(err)
  606. }
  607. if err := container.Start(); err != nil {
  608. t.Fatal(err)
  609. }
  610. if _, err := io.WriteString(stdin, "hello world #2"); err != nil {
  611. t.Fatal(err)
  612. }
  613. if err := stdin.Close(); err != nil {
  614. t.Fatal(err)
  615. }
  616. container.Wait()
  617. output, err = ioutil.ReadAll(stdout)
  618. if err != nil {
  619. t.Fatal(err)
  620. }
  621. if err := stdout.Close(); err != nil {
  622. t.Fatal(err)
  623. }
  624. if string(output) != "hello world #2" {
  625. t.Fatalf("Unexpected output. Expected %s, received: %s", "hello world #2", string(output))
  626. }
  627. }
  628. func TestUser(t *testing.T) {
  629. daemon := mkDaemon(t)
  630. defer nuke(daemon)
  631. // Default user must be root
  632. container, _, err := daemon.Create(&runconfig.Config{
  633. Image: GetTestImage(daemon).ID,
  634. Cmd: []string{"id"},
  635. },
  636. "",
  637. )
  638. if err != nil {
  639. t.Fatal(err)
  640. }
  641. defer daemon.Destroy(container)
  642. output, err := container.Output()
  643. if err != nil {
  644. t.Fatal(err)
  645. }
  646. if !strings.Contains(string(output), "uid=0(root) gid=0(root)") {
  647. t.Error(string(output))
  648. }
  649. // Set a username
  650. container, _, err = daemon.Create(&runconfig.Config{
  651. Image: GetTestImage(daemon).ID,
  652. Cmd: []string{"id"},
  653. User: "root",
  654. },
  655. "",
  656. )
  657. if err != nil {
  658. t.Fatal(err)
  659. }
  660. defer daemon.Destroy(container)
  661. output, err = container.Output()
  662. if code := container.State.GetExitCode(); err != nil || code != 0 {
  663. t.Fatal(err)
  664. }
  665. if !strings.Contains(string(output), "uid=0(root) gid=0(root)") {
  666. t.Error(string(output))
  667. }
  668. // Set a UID
  669. container, _, err = daemon.Create(&runconfig.Config{
  670. Image: GetTestImage(daemon).ID,
  671. Cmd: []string{"id"},
  672. User: "0",
  673. },
  674. "",
  675. )
  676. if code := container.State.GetExitCode(); err != nil || code != 0 {
  677. t.Fatal(err)
  678. }
  679. defer daemon.Destroy(container)
  680. output, err = container.Output()
  681. if code := container.State.GetExitCode(); err != nil || code != 0 {
  682. t.Fatal(err)
  683. }
  684. if !strings.Contains(string(output), "uid=0(root) gid=0(root)") {
  685. t.Error(string(output))
  686. }
  687. // Set a different user by uid
  688. container, _, err = daemon.Create(&runconfig.Config{
  689. Image: GetTestImage(daemon).ID,
  690. Cmd: []string{"id"},
  691. User: "1",
  692. },
  693. "",
  694. )
  695. if err != nil {
  696. t.Fatal(err)
  697. }
  698. defer daemon.Destroy(container)
  699. output, err = container.Output()
  700. if err != nil {
  701. t.Fatal(err)
  702. } else if code := container.State.GetExitCode(); code != 0 {
  703. t.Fatalf("Container exit code is invalid: %d\nOutput:\n%s\n", code, output)
  704. }
  705. if !strings.Contains(string(output), "uid=1(daemon) gid=1(daemon)") {
  706. t.Error(string(output))
  707. }
  708. // Set a different user by username
  709. container, _, err = daemon.Create(&runconfig.Config{
  710. Image: GetTestImage(daemon).ID,
  711. Cmd: []string{"id"},
  712. User: "daemon",
  713. },
  714. "",
  715. )
  716. if err != nil {
  717. t.Fatal(err)
  718. }
  719. defer daemon.Destroy(container)
  720. output, err = container.Output()
  721. if code := container.State.GetExitCode(); err != nil || code != 0 {
  722. t.Fatal(err)
  723. }
  724. if !strings.Contains(string(output), "uid=1(daemon) gid=1(daemon)") {
  725. t.Error(string(output))
  726. }
  727. // Test an wrong username
  728. container, _, err = daemon.Create(&runconfig.Config{
  729. Image: GetTestImage(daemon).ID,
  730. Cmd: []string{"id"},
  731. User: "unknownuser",
  732. },
  733. "",
  734. )
  735. if err != nil {
  736. t.Fatal(err)
  737. }
  738. defer daemon.Destroy(container)
  739. output, err = container.Output()
  740. if container.State.GetExitCode() == 0 {
  741. t.Fatal("Starting container with wrong uid should fail but it passed.")
  742. }
  743. }
  744. func TestMultipleContainers(t *testing.T) {
  745. daemon := mkDaemon(t)
  746. defer nuke(daemon)
  747. container1, _, err := daemon.Create(&runconfig.Config{
  748. Image: GetTestImage(daemon).ID,
  749. Cmd: []string{"sleep", "2"},
  750. },
  751. "",
  752. )
  753. if err != nil {
  754. t.Fatal(err)
  755. }
  756. defer daemon.Destroy(container1)
  757. container2, _, err := daemon.Create(&runconfig.Config{
  758. Image: GetTestImage(daemon).ID,
  759. Cmd: []string{"sleep", "2"},
  760. },
  761. "",
  762. )
  763. if err != nil {
  764. t.Fatal(err)
  765. }
  766. defer daemon.Destroy(container2)
  767. // Start both containers
  768. if err := container1.Start(); err != nil {
  769. t.Fatal(err)
  770. }
  771. if err := container2.Start(); err != nil {
  772. t.Fatal(err)
  773. }
  774. // Make sure they are running before trying to kill them
  775. container1.WaitTimeout(250 * time.Millisecond)
  776. container2.WaitTimeout(250 * time.Millisecond)
  777. // If we are here, both containers should be running
  778. if !container1.State.IsRunning() {
  779. t.Fatal("Container not running")
  780. }
  781. if !container2.State.IsRunning() {
  782. t.Fatal("Container not running")
  783. }
  784. // Kill them
  785. if err := container1.Kill(); err != nil {
  786. t.Fatal(err)
  787. }
  788. if err := container2.Kill(); err != nil {
  789. t.Fatal(err)
  790. }
  791. }
  792. func TestStdin(t *testing.T) {
  793. daemon := mkDaemon(t)
  794. defer nuke(daemon)
  795. container, _, err := daemon.Create(&runconfig.Config{
  796. Image: GetTestImage(daemon).ID,
  797. Cmd: []string{"cat"},
  798. OpenStdin: true,
  799. },
  800. "",
  801. )
  802. if err != nil {
  803. t.Fatal(err)
  804. }
  805. defer daemon.Destroy(container)
  806. stdin, err := container.StdinPipe()
  807. if err != nil {
  808. t.Fatal(err)
  809. }
  810. stdout, err := container.StdoutPipe()
  811. if err != nil {
  812. t.Fatal(err)
  813. }
  814. if err := container.Start(); err != nil {
  815. t.Fatal(err)
  816. }
  817. defer stdin.Close()
  818. defer stdout.Close()
  819. if _, err := io.WriteString(stdin, "hello world"); err != nil {
  820. t.Fatal(err)
  821. }
  822. if err := stdin.Close(); err != nil {
  823. t.Fatal(err)
  824. }
  825. container.Wait()
  826. output, err := ioutil.ReadAll(stdout)
  827. if err != nil {
  828. t.Fatal(err)
  829. }
  830. if string(output) != "hello world" {
  831. t.Fatalf("Unexpected output. Expected %s, received: %s", "hello world", string(output))
  832. }
  833. }
  834. func TestTty(t *testing.T) {
  835. daemon := mkDaemon(t)
  836. defer nuke(daemon)
  837. container, _, err := daemon.Create(&runconfig.Config{
  838. Image: GetTestImage(daemon).ID,
  839. Cmd: []string{"cat"},
  840. OpenStdin: true,
  841. },
  842. "",
  843. )
  844. if err != nil {
  845. t.Fatal(err)
  846. }
  847. defer daemon.Destroy(container)
  848. stdin, err := container.StdinPipe()
  849. if err != nil {
  850. t.Fatal(err)
  851. }
  852. stdout, err := container.StdoutPipe()
  853. if err != nil {
  854. t.Fatal(err)
  855. }
  856. if err := container.Start(); err != nil {
  857. t.Fatal(err)
  858. }
  859. defer stdin.Close()
  860. defer stdout.Close()
  861. if _, err := io.WriteString(stdin, "hello world"); err != nil {
  862. t.Fatal(err)
  863. }
  864. if err := stdin.Close(); err != nil {
  865. t.Fatal(err)
  866. }
  867. container.Wait()
  868. output, err := ioutil.ReadAll(stdout)
  869. if err != nil {
  870. t.Fatal(err)
  871. }
  872. if string(output) != "hello world" {
  873. t.Fatalf("Unexpected output. Expected %s, received: %s", "hello world", string(output))
  874. }
  875. }
  876. func TestEnv(t *testing.T) {
  877. os.Setenv("TRUE", "false")
  878. os.Setenv("TRICKY", "tri\ncky\n")
  879. daemon := mkDaemon(t)
  880. defer nuke(daemon)
  881. config, _, _, err := runconfig.Parse([]string{"-e=FALSE=true", "-e=TRUE", "-e=TRICKY", GetTestImage(daemon).ID, "env"}, nil)
  882. if err != nil {
  883. t.Fatal(err)
  884. }
  885. container, _, err := daemon.Create(config, "")
  886. if err != nil {
  887. t.Fatal(err)
  888. }
  889. defer daemon.Destroy(container)
  890. stdout, err := container.StdoutPipe()
  891. if err != nil {
  892. t.Fatal(err)
  893. }
  894. defer stdout.Close()
  895. if err := container.Start(); err != nil {
  896. t.Fatal(err)
  897. }
  898. container.Wait()
  899. output, err := ioutil.ReadAll(stdout)
  900. if err != nil {
  901. t.Fatal(err)
  902. }
  903. actualEnv := strings.Split(string(output), "\n")
  904. if actualEnv[len(actualEnv)-1] == "" {
  905. actualEnv = actualEnv[:len(actualEnv)-1]
  906. }
  907. sort.Strings(actualEnv)
  908. goodEnv := []string{
  909. "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
  910. "HOME=/",
  911. "HOSTNAME=" + utils.TruncateID(container.ID),
  912. "FALSE=true",
  913. "TRUE=false",
  914. "TRICKY=tri",
  915. "cky",
  916. "",
  917. }
  918. sort.Strings(goodEnv)
  919. if len(goodEnv) != len(actualEnv) {
  920. t.Fatalf("Wrong environment: should be %d variables, not: '%s'\n", len(goodEnv), strings.Join(actualEnv, ", "))
  921. }
  922. for i := range goodEnv {
  923. if actualEnv[i] != goodEnv[i] {
  924. t.Fatalf("Wrong environment variable: should be %s, not %s", goodEnv[i], actualEnv[i])
  925. }
  926. }
  927. }
  928. func TestEntrypoint(t *testing.T) {
  929. daemon := mkDaemon(t)
  930. defer nuke(daemon)
  931. container, _, err := daemon.Create(
  932. &runconfig.Config{
  933. Image: GetTestImage(daemon).ID,
  934. Entrypoint: []string{"/bin/echo"},
  935. Cmd: []string{"-n", "foobar"},
  936. },
  937. "",
  938. )
  939. if err != nil {
  940. t.Fatal(err)
  941. }
  942. defer daemon.Destroy(container)
  943. output, err := container.Output()
  944. if err != nil {
  945. t.Fatal(err)
  946. }
  947. if string(output) != "foobar" {
  948. t.Error(string(output))
  949. }
  950. }
  951. func TestEntrypointNoCmd(t *testing.T) {
  952. daemon := mkDaemon(t)
  953. defer nuke(daemon)
  954. container, _, err := daemon.Create(
  955. &runconfig.Config{
  956. Image: GetTestImage(daemon).ID,
  957. Entrypoint: []string{"/bin/echo", "foobar"},
  958. },
  959. "",
  960. )
  961. if err != nil {
  962. t.Fatal(err)
  963. }
  964. defer daemon.Destroy(container)
  965. output, err := container.Output()
  966. if err != nil {
  967. t.Fatal(err)
  968. }
  969. if strings.Trim(string(output), "\r\n") != "foobar" {
  970. t.Error(string(output))
  971. }
  972. }
  973. func BenchmarkRunSequential(b *testing.B) {
  974. daemon := mkDaemon(b)
  975. defer nuke(daemon)
  976. for i := 0; i < b.N; i++ {
  977. container, _, err := daemon.Create(&runconfig.Config{
  978. Image: GetTestImage(daemon).ID,
  979. Cmd: []string{"echo", "-n", "foo"},
  980. },
  981. "",
  982. )
  983. if err != nil {
  984. b.Fatal(err)
  985. }
  986. defer daemon.Destroy(container)
  987. output, err := container.Output()
  988. if err != nil {
  989. b.Fatal(err)
  990. }
  991. if string(output) != "foo" {
  992. b.Fatalf("Unexpected output: %s", output)
  993. }
  994. if err := daemon.Destroy(container); err != nil {
  995. b.Fatal(err)
  996. }
  997. }
  998. }
  999. func BenchmarkRunParallel(b *testing.B) {
  1000. daemon := mkDaemon(b)
  1001. defer nuke(daemon)
  1002. var tasks []chan error
  1003. for i := 0; i < b.N; i++ {
  1004. complete := make(chan error)
  1005. tasks = append(tasks, complete)
  1006. go func(i int, complete chan error) {
  1007. container, _, err := daemon.Create(&runconfig.Config{
  1008. Image: GetTestImage(daemon).ID,
  1009. Cmd: []string{"echo", "-n", "foo"},
  1010. },
  1011. "",
  1012. )
  1013. if err != nil {
  1014. complete <- err
  1015. return
  1016. }
  1017. defer daemon.Destroy(container)
  1018. if err := container.Start(); err != nil {
  1019. complete <- err
  1020. return
  1021. }
  1022. if err := container.WaitTimeout(15 * time.Second); err != nil {
  1023. complete <- err
  1024. return
  1025. }
  1026. // if string(output) != "foo" {
  1027. // complete <- fmt.Errorf("Unexecpted output: %v", string(output))
  1028. // }
  1029. if err := daemon.Destroy(container); err != nil {
  1030. complete <- err
  1031. return
  1032. }
  1033. complete <- nil
  1034. }(i, complete)
  1035. }
  1036. var errors []error
  1037. for _, task := range tasks {
  1038. err := <-task
  1039. if err != nil {
  1040. errors = append(errors, err)
  1041. }
  1042. }
  1043. if len(errors) > 0 {
  1044. b.Fatal(errors)
  1045. }
  1046. }
  1047. func tempDir(t *testing.T) string {
  1048. tmpDir, err := ioutil.TempDir("", "docker-test-container")
  1049. if err != nil {
  1050. t.Fatal(err)
  1051. }
  1052. return tmpDir
  1053. }
  1054. // Test for #1737
  1055. func TestCopyVolumeUidGid(t *testing.T) {
  1056. eng := NewTestEngine(t)
  1057. r := mkDaemonFromEngine(eng, t)
  1058. defer r.Nuke()
  1059. // Add directory not owned by root
  1060. container1, _, _ := mkContainer(r, []string{"_", "/bin/sh", "-c", "mkdir -p /hello && touch /hello/test.txt && chown daemon.daemon /hello"}, t)
  1061. defer r.Destroy(container1)
  1062. if container1.State.IsRunning() {
  1063. t.Errorf("Container shouldn't be running")
  1064. }
  1065. if err := container1.Run(); err != nil {
  1066. t.Fatal(err)
  1067. }
  1068. if container1.State.IsRunning() {
  1069. t.Errorf("Container shouldn't be running")
  1070. }
  1071. img, err := r.Commit(container1, "", "", "unit test commited image", "", nil)
  1072. if err != nil {
  1073. t.Error(err)
  1074. }
  1075. // Test that the uid and gid is copied from the image to the volume
  1076. tmpDir1 := tempDir(t)
  1077. defer os.RemoveAll(tmpDir1)
  1078. stdout1, _ := runContainer(eng, r, []string{"-v", "/hello", img.ID, "stat", "-c", "%U %G", "/hello"}, t)
  1079. if !strings.Contains(stdout1, "daemon daemon") {
  1080. t.Fatal("Container failed to transfer uid and gid to volume")
  1081. }
  1082. }
  1083. // Test for #1582
  1084. func TestCopyVolumeContent(t *testing.T) {
  1085. eng := NewTestEngine(t)
  1086. r := mkDaemonFromEngine(eng, t)
  1087. defer r.Nuke()
  1088. // Put some content in a directory of a container and commit it
  1089. container1, _, _ := mkContainer(r, []string{"_", "/bin/sh", "-c", "mkdir -p /hello/local && echo hello > /hello/local/world"}, t)
  1090. defer r.Destroy(container1)
  1091. if container1.State.IsRunning() {
  1092. t.Errorf("Container shouldn't be running")
  1093. }
  1094. if err := container1.Run(); err != nil {
  1095. t.Fatal(err)
  1096. }
  1097. if container1.State.IsRunning() {
  1098. t.Errorf("Container shouldn't be running")
  1099. }
  1100. img, err := r.Commit(container1, "", "", "unit test commited image", "", nil)
  1101. if err != nil {
  1102. t.Error(err)
  1103. }
  1104. // Test that the content is copied from the image to the volume
  1105. tmpDir1 := tempDir(t)
  1106. defer os.RemoveAll(tmpDir1)
  1107. stdout1, _ := runContainer(eng, r, []string{"-v", "/hello", img.ID, "find", "/hello"}, t)
  1108. if !(strings.Contains(stdout1, "/hello/local/world") && strings.Contains(stdout1, "/hello/local")) {
  1109. t.Fatal("Container failed to transfer content to volume")
  1110. }
  1111. }
  1112. func TestBindMounts(t *testing.T) {
  1113. eng := NewTestEngine(t)
  1114. r := mkDaemonFromEngine(eng, t)
  1115. defer r.Nuke()
  1116. tmpDir := tempDir(t)
  1117. defer os.RemoveAll(tmpDir)
  1118. writeFile(path.Join(tmpDir, "touch-me"), "", t)
  1119. // Test reading from a read-only bind mount
  1120. stdout, _ := runContainer(eng, r, []string{"-v", fmt.Sprintf("%s:/tmp:ro", tmpDir), "_", "ls", "/tmp"}, t)
  1121. if !strings.Contains(stdout, "touch-me") {
  1122. t.Fatal("Container failed to read from bind mount")
  1123. }
  1124. // test writing to bind mount
  1125. runContainer(eng, r, []string{"-v", fmt.Sprintf("%s:/tmp:rw", tmpDir), "_", "touch", "/tmp/holla"}, t)
  1126. readFile(path.Join(tmpDir, "holla"), t) // Will fail if the file doesn't exist
  1127. // test mounting to an illegal destination directory
  1128. if _, err := runContainer(eng, r, []string{"-v", fmt.Sprintf("%s:.", tmpDir), "_", "ls", "."}, nil); err == nil {
  1129. t.Fatal("Container bind mounted illegal directory")
  1130. }
  1131. // test mount a file
  1132. runContainer(eng, r, []string{"-v", fmt.Sprintf("%s/holla:/tmp/holla:rw", tmpDir), "_", "sh", "-c", "echo -n 'yotta' > /tmp/holla"}, t)
  1133. content := readFile(path.Join(tmpDir, "holla"), t) // Will fail if the file doesn't exist
  1134. if content != "yotta" {
  1135. t.Fatal("Container failed to write to bind mount file")
  1136. }
  1137. }
  1138. // Test that restarting a container with a volume does not create a new volume on restart. Regression test for #819.
  1139. func TestRestartWithVolumes(t *testing.T) {
  1140. daemon := mkDaemon(t)
  1141. defer nuke(daemon)
  1142. container, _, err := daemon.Create(&runconfig.Config{
  1143. Image: GetTestImage(daemon).ID,
  1144. Cmd: []string{"echo", "-n", "foobar"},
  1145. Volumes: map[string]struct{}{"/test": {}},
  1146. },
  1147. "",
  1148. )
  1149. if err != nil {
  1150. t.Fatal(err)
  1151. }
  1152. defer daemon.Destroy(container)
  1153. for key := range container.Config.Volumes {
  1154. if key != "/test" {
  1155. t.Fail()
  1156. }
  1157. }
  1158. _, err = container.Output()
  1159. if err != nil {
  1160. t.Fatal(err)
  1161. }
  1162. expected := container.Volumes["/test"]
  1163. if expected == "" {
  1164. t.Fail()
  1165. }
  1166. // Run the container again to verify the volume path persists
  1167. _, err = container.Output()
  1168. if err != nil {
  1169. t.Fatal(err)
  1170. }
  1171. actual := container.Volumes["/test"]
  1172. if expected != actual {
  1173. t.Fatalf("Expected volume path: %s Actual path: %s", expected, actual)
  1174. }
  1175. }
  1176. func TestContainerNetwork(t *testing.T) {
  1177. daemon := mkDaemon(t)
  1178. defer nuke(daemon)
  1179. container, _, err := daemon.Create(
  1180. &runconfig.Config{
  1181. Image: GetTestImage(daemon).ID,
  1182. // If I change this to ping 8.8.8.8 it fails. Any idea why? - timthelion
  1183. Cmd: []string{"ping", "-c", "1", "127.0.0.1"},
  1184. },
  1185. "",
  1186. )
  1187. if err != nil {
  1188. t.Fatal(err)
  1189. }
  1190. defer daemon.Destroy(container)
  1191. if err := container.Run(); err != nil {
  1192. t.Fatal(err)
  1193. }
  1194. if code := container.State.GetExitCode(); code != 0 {
  1195. t.Fatalf("Unexpected ping 127.0.0.1 exit code %d (expected 0)", code)
  1196. }
  1197. }
  1198. // Issue #4681
  1199. func TestLoopbackFunctionsWhenNetworkingIsDissabled(t *testing.T) {
  1200. daemon := mkDaemon(t)
  1201. defer nuke(daemon)
  1202. container, _, err := daemon.Create(
  1203. &runconfig.Config{
  1204. Image: GetTestImage(daemon).ID,
  1205. Cmd: []string{"ping", "-c", "1", "127.0.0.1"},
  1206. NetworkDisabled: true,
  1207. },
  1208. "",
  1209. )
  1210. if err != nil {
  1211. t.Fatal(err)
  1212. }
  1213. defer daemon.Destroy(container)
  1214. if err := container.Run(); err != nil {
  1215. t.Fatal(err)
  1216. }
  1217. if code := container.State.GetExitCode(); code != 0 {
  1218. t.Fatalf("Unexpected ping 127.0.0.1 exit code %d (expected 0)", code)
  1219. }
  1220. }
  1221. func TestOnlyLoopbackExistsWhenUsingDisableNetworkOption(t *testing.T) {
  1222. eng := NewTestEngine(t)
  1223. daemon := mkDaemonFromEngine(eng, t)
  1224. defer nuke(daemon)
  1225. config, hc, _, err := runconfig.Parse([]string{"-n=false", GetTestImage(daemon).ID, "ip", "addr", "show", "up"}, nil)
  1226. if err != nil {
  1227. t.Fatal(err)
  1228. }
  1229. jobCreate := eng.Job("create")
  1230. if err := jobCreate.ImportEnv(config); err != nil {
  1231. t.Fatal(err)
  1232. }
  1233. var id string
  1234. jobCreate.Stdout.AddString(&id)
  1235. if err := jobCreate.Run(); err != nil {
  1236. t.Fatal(err)
  1237. }
  1238. // FIXME: this hack can be removed once Wait is a job
  1239. c := daemon.Get(id)
  1240. if c == nil {
  1241. t.Fatalf("Couldn't retrieve container %s from daemon", id)
  1242. }
  1243. stdout, err := c.StdoutPipe()
  1244. if err != nil {
  1245. t.Fatal(err)
  1246. }
  1247. jobStart := eng.Job("start", id)
  1248. if err := jobStart.ImportEnv(hc); err != nil {
  1249. t.Fatal(err)
  1250. }
  1251. if err := jobStart.Run(); err != nil {
  1252. t.Fatal(err)
  1253. }
  1254. c.WaitTimeout(500 * time.Millisecond)
  1255. c.Wait()
  1256. output, err := ioutil.ReadAll(stdout)
  1257. if err != nil {
  1258. t.Fatal(err)
  1259. }
  1260. interfaces := regexp.MustCompile(`(?m)^[0-9]+: [a-zA-Z0-9]+`).FindAllString(string(output), -1)
  1261. if len(interfaces) != 1 {
  1262. t.Fatalf("Wrong interface count in test container: expected [*: lo], got %s", interfaces)
  1263. }
  1264. if !strings.HasSuffix(interfaces[0], ": lo") {
  1265. t.Fatalf("Wrong interface in test container: expected [*: lo], got %s", interfaces)
  1266. }
  1267. }
  1268. func TestPrivilegedCanMknod(t *testing.T) {
  1269. eng := NewTestEngine(t)
  1270. daemon := mkDaemonFromEngine(eng, t)
  1271. defer daemon.Nuke()
  1272. if output, err := runContainer(eng, daemon, []string{"--privileged", "_", "sh", "-c", "mknod /tmp/sda b 8 0 && echo ok"}, t); output != "ok\n" {
  1273. t.Fatalf("Could not mknod into privileged container %s %v", output, err)
  1274. }
  1275. }
  1276. func TestPrivilegedCanMount(t *testing.T) {
  1277. eng := NewTestEngine(t)
  1278. daemon := mkDaemonFromEngine(eng, t)
  1279. defer daemon.Nuke()
  1280. if output, _ := runContainer(eng, daemon, []string{"--privileged", "_", "sh", "-c", "mount -t tmpfs none /tmp && echo ok"}, t); output != "ok\n" {
  1281. t.Fatal("Could not mount into privileged container")
  1282. }
  1283. }
  1284. func TestUnprivilegedCanMknod(t *testing.T) {
  1285. eng := NewTestEngine(t)
  1286. daemon := mkDaemonFromEngine(eng, t)
  1287. defer daemon.Nuke()
  1288. if output, _ := runContainer(eng, daemon, []string{"_", "sh", "-c", "mknod /tmp/sda b 8 0 && echo ok"}, t); output != "ok\n" {
  1289. t.Fatal("Couldn't mknod into secure container")
  1290. }
  1291. }
  1292. func TestUnprivilegedCannotMount(t *testing.T) {
  1293. eng := NewTestEngine(t)
  1294. daemon := mkDaemonFromEngine(eng, t)
  1295. defer daemon.Nuke()
  1296. if output, _ := runContainer(eng, daemon, []string{"_", "sh", "-c", "mount -t tmpfs none /tmp || echo ok"}, t); output != "ok\n" {
  1297. t.Fatal("Could mount into secure container")
  1298. }
  1299. }