server_test.go 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711
  1. package docker
  2. import (
  3. "github.com/dotcloud/docker"
  4. "github.com/dotcloud/docker/engine"
  5. "strings"
  6. "testing"
  7. "time"
  8. )
  9. func TestImageTagImageDelete(t *testing.T) {
  10. eng := NewTestEngine(t)
  11. defer mkRuntimeFromEngine(eng, t).Nuke()
  12. srv := mkServerFromEngine(eng, t)
  13. initialImages := getAllImages(eng, t)
  14. if err := eng.Job("tag", unitTestImageName, "utest", "tag1").Run(); err != nil {
  15. t.Fatal(err)
  16. }
  17. if err := eng.Job("tag", unitTestImageName, "utest/docker", "tag2").Run(); err != nil {
  18. t.Fatal(err)
  19. }
  20. if err := eng.Job("tag", unitTestImageName, "utest:5000/docker", "tag3").Run(); err != nil {
  21. t.Fatal(err)
  22. }
  23. images := getAllImages(eng, t)
  24. nExpected := len(initialImages.Data[0].GetList("RepoTags")) + 3
  25. nActual := len(images.Data[0].GetList("RepoTags"))
  26. if nExpected != nActual {
  27. t.Errorf("Expected %d images, %d found", nExpected, nActual)
  28. }
  29. if _, err := srv.DeleteImage("utest/docker:tag2", true); err != nil {
  30. t.Fatal(err)
  31. }
  32. images = getAllImages(eng, t)
  33. nExpected = len(initialImages.Data[0].GetList("RepoTags")) + 2
  34. nActual = len(images.Data[0].GetList("RepoTags"))
  35. if nExpected != nActual {
  36. t.Errorf("Expected %d images, %d found", nExpected, nActual)
  37. }
  38. if _, err := srv.DeleteImage("utest:5000/docker:tag3", true); err != nil {
  39. t.Fatal(err)
  40. }
  41. images = getAllImages(eng, t)
  42. nExpected = len(initialImages.Data[0].GetList("RepoTags")) + 1
  43. nActual = len(images.Data[0].GetList("RepoTags"))
  44. if _, err := srv.DeleteImage("utest:tag1", true); err != nil {
  45. t.Fatal(err)
  46. }
  47. images = getAllImages(eng, t)
  48. if images.Len() != initialImages.Len() {
  49. t.Errorf("Expected %d image, %d found", initialImages.Len(), images.Len())
  50. }
  51. }
  52. func TestCreateRm(t *testing.T) {
  53. eng := NewTestEngine(t)
  54. defer mkRuntimeFromEngine(eng, t).Nuke()
  55. config, _, _, err := docker.ParseRun([]string{unitTestImageID, "echo test"}, nil)
  56. if err != nil {
  57. t.Fatal(err)
  58. }
  59. id := createTestContainer(eng, config, t)
  60. job := eng.Job("containers")
  61. job.SetenvBool("all", true)
  62. outs, err := job.Stdout.AddListTable()
  63. if err != nil {
  64. t.Fatal(err)
  65. }
  66. if err := job.Run(); err != nil {
  67. t.Fatal(err)
  68. }
  69. if len(outs.Data) != 1 {
  70. t.Errorf("Expected 1 container, %v found", len(outs.Data))
  71. }
  72. job = eng.Job("container_delete", id)
  73. job.SetenvBool("removeVolume", true)
  74. if err := job.Run(); err != nil {
  75. t.Fatal(err)
  76. }
  77. job = eng.Job("containers")
  78. job.SetenvBool("all", true)
  79. outs, err = job.Stdout.AddListTable()
  80. if err != nil {
  81. t.Fatal(err)
  82. }
  83. if err := job.Run(); err != nil {
  84. t.Fatal(err)
  85. }
  86. if len(outs.Data) != 0 {
  87. t.Errorf("Expected 0 container, %v found", len(outs.Data))
  88. }
  89. }
  90. func TestCreateNumberHostname(t *testing.T) {
  91. eng := NewTestEngine(t)
  92. defer mkRuntimeFromEngine(eng, t).Nuke()
  93. config, _, _, err := docker.ParseRun([]string{"-h", "web.0", unitTestImageID, "echo test"}, nil)
  94. if err != nil {
  95. t.Fatal(err)
  96. }
  97. createTestContainer(eng, config, t)
  98. }
  99. func TestCreateNumberUsername(t *testing.T) {
  100. eng := NewTestEngine(t)
  101. defer mkRuntimeFromEngine(eng, t).Nuke()
  102. config, _, _, err := docker.ParseRun([]string{"-u", "1002", unitTestImageID, "echo test"}, nil)
  103. if err != nil {
  104. t.Fatal(err)
  105. }
  106. createTestContainer(eng, config, t)
  107. }
  108. func TestCreateRmVolumes(t *testing.T) {
  109. eng := NewTestEngine(t)
  110. defer mkRuntimeFromEngine(eng, t).Nuke()
  111. config, hostConfig, _, err := docker.ParseRun([]string{"-v", "/srv", unitTestImageID, "echo", "test"}, nil)
  112. if err != nil {
  113. t.Fatal(err)
  114. }
  115. id := createTestContainer(eng, config, t)
  116. job := eng.Job("containers")
  117. job.SetenvBool("all", true)
  118. outs, err := job.Stdout.AddListTable()
  119. if err != nil {
  120. t.Fatal(err)
  121. }
  122. if err := job.Run(); err != nil {
  123. t.Fatal(err)
  124. }
  125. if len(outs.Data) != 1 {
  126. t.Errorf("Expected 1 container, %v found", len(outs.Data))
  127. }
  128. job = eng.Job("start", id)
  129. if err := job.ImportEnv(hostConfig); err != nil {
  130. t.Fatal(err)
  131. }
  132. if err := job.Run(); err != nil {
  133. t.Fatal(err)
  134. }
  135. job = eng.Job("stop", id)
  136. job.SetenvInt("t", 1)
  137. if err := job.Run(); err != nil {
  138. t.Fatal(err)
  139. }
  140. job = eng.Job("container_delete", id)
  141. job.SetenvBool("removeVolume", true)
  142. if err := job.Run(); err != nil {
  143. t.Fatal(err)
  144. }
  145. job = eng.Job("containers")
  146. job.SetenvBool("all", true)
  147. outs, err = job.Stdout.AddListTable()
  148. if err != nil {
  149. t.Fatal(err)
  150. }
  151. if err := job.Run(); err != nil {
  152. t.Fatal(err)
  153. }
  154. if len(outs.Data) != 0 {
  155. t.Errorf("Expected 0 container, %v found", len(outs.Data))
  156. }
  157. }
  158. func TestCommit(t *testing.T) {
  159. eng := NewTestEngine(t)
  160. defer mkRuntimeFromEngine(eng, t).Nuke()
  161. config, _, _, err := docker.ParseRun([]string{unitTestImageID, "/bin/cat"}, nil)
  162. if err != nil {
  163. t.Fatal(err)
  164. }
  165. id := createTestContainer(eng, config, t)
  166. job := eng.Job("commit", id)
  167. job.Setenv("repo", "testrepo")
  168. job.Setenv("tag", "testtag")
  169. job.SetenvJson("config", config)
  170. if err := job.Run(); err != nil {
  171. t.Fatal(err)
  172. }
  173. }
  174. func TestRestartKillWait(t *testing.T) {
  175. eng := NewTestEngine(t)
  176. srv := mkServerFromEngine(eng, t)
  177. runtime := mkRuntimeFromEngine(eng, t)
  178. defer runtime.Nuke()
  179. config, hostConfig, _, err := docker.ParseRun([]string{"-i", unitTestImageID, "/bin/cat"}, nil)
  180. if err != nil {
  181. t.Fatal(err)
  182. }
  183. id := createTestContainer(eng, config, t)
  184. job := eng.Job("containers")
  185. job.SetenvBool("all", true)
  186. outs, err := job.Stdout.AddListTable()
  187. if err != nil {
  188. t.Fatal(err)
  189. }
  190. if err := job.Run(); err != nil {
  191. t.Fatal(err)
  192. }
  193. if len(outs.Data) != 1 {
  194. t.Errorf("Expected 1 container, %v found", len(outs.Data))
  195. }
  196. job = eng.Job("start", id)
  197. if err := job.ImportEnv(hostConfig); err != nil {
  198. t.Fatal(err)
  199. }
  200. if err := job.Run(); err != nil {
  201. t.Fatal(err)
  202. }
  203. job = eng.Job("kill", id)
  204. if err := job.Run(); err != nil {
  205. t.Fatal(err)
  206. }
  207. eng, err = engine.New(eng.Root())
  208. if err != nil {
  209. t.Fatal(err)
  210. }
  211. job = eng.Job("initapi")
  212. job.Setenv("Root", eng.Root())
  213. job.SetenvBool("AutoRestart", false)
  214. // TestGetEnabledCors and TestOptionsRoute require EnableCors=true
  215. job.SetenvBool("EnableCors", true)
  216. if err := job.Run(); err != nil {
  217. t.Fatal(err)
  218. }
  219. srv = mkServerFromEngine(eng, t)
  220. job = srv.Eng.Job("containers")
  221. job.SetenvBool("all", true)
  222. outs, err = job.Stdout.AddListTable()
  223. if err != nil {
  224. t.Fatal(err)
  225. }
  226. if err := job.Run(); err != nil {
  227. t.Fatal(err)
  228. }
  229. if len(outs.Data) != 1 {
  230. t.Errorf("Expected 1 container, %v found", len(outs.Data))
  231. }
  232. setTimeout(t, "Waiting on stopped container timedout", 5*time.Second, func() {
  233. job = srv.Eng.Job("wait", outs.Data[0].Get("Id"))
  234. var statusStr string
  235. job.Stdout.AddString(&statusStr)
  236. if err := job.Run(); err != nil {
  237. t.Fatal(err)
  238. }
  239. })
  240. }
  241. func TestCreateStartRestartStopStartKillRm(t *testing.T) {
  242. eng := NewTestEngine(t)
  243. srv := mkServerFromEngine(eng, t)
  244. defer mkRuntimeFromEngine(eng, t).Nuke()
  245. config, hostConfig, _, err := docker.ParseRun([]string{"-i", unitTestImageID, "/bin/cat"}, nil)
  246. if err != nil {
  247. t.Fatal(err)
  248. }
  249. id := createTestContainer(eng, config, t)
  250. job := srv.Eng.Job("containers")
  251. job.SetenvBool("all", true)
  252. outs, err := job.Stdout.AddListTable()
  253. if err != nil {
  254. t.Fatal(err)
  255. }
  256. if err := job.Run(); err != nil {
  257. t.Fatal(err)
  258. }
  259. if len(outs.Data) != 1 {
  260. t.Errorf("Expected 1 container, %v found", len(outs.Data))
  261. }
  262. job = eng.Job("start", id)
  263. if err := job.ImportEnv(hostConfig); err != nil {
  264. t.Fatal(err)
  265. }
  266. if err := job.Run(); err != nil {
  267. t.Fatal(err)
  268. }
  269. job = eng.Job("restart", id)
  270. job.SetenvInt("t", 15)
  271. if err := job.Run(); err != nil {
  272. t.Fatal(err)
  273. }
  274. job = eng.Job("stop", id)
  275. job.SetenvInt("t", 15)
  276. if err := job.Run(); err != nil {
  277. t.Fatal(err)
  278. }
  279. job = eng.Job("start", id)
  280. if err := job.ImportEnv(hostConfig); err != nil {
  281. t.Fatal(err)
  282. }
  283. if err := job.Run(); err != nil {
  284. t.Fatal(err)
  285. }
  286. if err := eng.Job("kill", id).Run(); err != nil {
  287. t.Fatal(err)
  288. }
  289. // FIXME: this failed once with a race condition ("Unable to remove filesystem for xxx: directory not empty")
  290. job = eng.Job("container_delete", id)
  291. job.SetenvBool("removeVolume", true)
  292. if err := job.Run(); err != nil {
  293. t.Fatal(err)
  294. }
  295. job = srv.Eng.Job("containers")
  296. job.SetenvBool("all", true)
  297. outs, err = job.Stdout.AddListTable()
  298. if err != nil {
  299. t.Fatal(err)
  300. }
  301. if err := job.Run(); err != nil {
  302. t.Fatal(err)
  303. }
  304. if len(outs.Data) != 0 {
  305. t.Errorf("Expected 0 container, %v found", len(outs.Data))
  306. }
  307. }
  308. func TestRunWithTooLowMemoryLimit(t *testing.T) {
  309. eng := NewTestEngine(t)
  310. defer mkRuntimeFromEngine(eng, t).Nuke()
  311. // Try to create a container with a memory limit of 1 byte less than the minimum allowed limit.
  312. job := eng.Job("create")
  313. job.Setenv("Image", unitTestImageID)
  314. job.Setenv("Memory", "524287")
  315. job.Setenv("CpuShares", "1000")
  316. job.SetenvList("Cmd", []string{"/bin/cat"})
  317. var id string
  318. job.Stdout.AddString(&id)
  319. if err := job.Run(); err == nil {
  320. t.Errorf("Memory limit is smaller than the allowed limit. Container creation should've failed!")
  321. }
  322. }
  323. func TestRmi(t *testing.T) {
  324. eng := NewTestEngine(t)
  325. srv := mkServerFromEngine(eng, t)
  326. defer mkRuntimeFromEngine(eng, t).Nuke()
  327. initialImages := getAllImages(eng, t)
  328. config, hostConfig, _, err := docker.ParseRun([]string{unitTestImageID, "echo", "test"}, nil)
  329. if err != nil {
  330. t.Fatal(err)
  331. }
  332. containerID := createTestContainer(eng, config, t)
  333. //To remove
  334. job := eng.Job("start", containerID)
  335. if err := job.ImportEnv(hostConfig); err != nil {
  336. t.Fatal(err)
  337. }
  338. if err := job.Run(); err != nil {
  339. t.Fatal(err)
  340. }
  341. if err := eng.Job("wait", containerID).Run(); err != nil {
  342. t.Fatal(err)
  343. }
  344. job = eng.Job("commit", containerID)
  345. job.Setenv("repo", "test")
  346. var imageID string
  347. job.Stdout.AddString(&imageID)
  348. if err := job.Run(); err != nil {
  349. t.Fatal(err)
  350. }
  351. if err := eng.Job("tag", imageID, "test", "0.1").Run(); err != nil {
  352. t.Fatal(err)
  353. }
  354. containerID = createTestContainer(eng, config, t)
  355. //To remove
  356. job = eng.Job("start", containerID)
  357. if err := job.ImportEnv(hostConfig); err != nil {
  358. t.Fatal(err)
  359. }
  360. if err := job.Run(); err != nil {
  361. t.Fatal(err)
  362. }
  363. if err := eng.Job("wait", containerID).Run(); err != nil {
  364. t.Fatal(err)
  365. }
  366. job = eng.Job("commit", containerID)
  367. job.Setenv("repo", "test")
  368. if err := job.Run(); err != nil {
  369. t.Fatal(err)
  370. }
  371. images := getAllImages(eng, t)
  372. if images.Len()-initialImages.Len() != 2 {
  373. t.Fatalf("Expected 2 new images, found %d.", images.Len()-initialImages.Len())
  374. }
  375. _, err = srv.DeleteImage(imageID, true)
  376. if err != nil {
  377. t.Fatal(err)
  378. }
  379. images = getAllImages(eng, t)
  380. if images.Len()-initialImages.Len() != 1 {
  381. t.Fatalf("Expected 1 new image, found %d.", images.Len()-initialImages.Len())
  382. }
  383. for _, image := range images.Data {
  384. if strings.Contains(unitTestImageID, image.Get("Id")) {
  385. continue
  386. }
  387. if image.GetList("RepoTags")[0] == "<none>:<none>" {
  388. t.Fatalf("Expected tagged image, got untagged one.")
  389. }
  390. }
  391. }
  392. func TestImagesFilter(t *testing.T) {
  393. eng := NewTestEngine(t)
  394. defer nuke(mkRuntimeFromEngine(eng, t))
  395. if err := eng.Job("tag", unitTestImageName, "utest", "tag1").Run(); err != nil {
  396. t.Fatal(err)
  397. }
  398. if err := eng.Job("tag", unitTestImageName, "utest/docker", "tag2").Run(); err != nil {
  399. t.Fatal(err)
  400. }
  401. if err := eng.Job("tag", unitTestImageName, "utest:5000/docker", "tag3").Run(); err != nil {
  402. t.Fatal(err)
  403. }
  404. images := getImages(eng, t, false, "utest*/*")
  405. if len(images.Data[0].GetList("RepoTags")) != 2 {
  406. t.Fatal("incorrect number of matches returned")
  407. }
  408. images = getImages(eng, t, false, "utest")
  409. if len(images.Data[0].GetList("RepoTags")) != 1 {
  410. t.Fatal("incorrect number of matches returned")
  411. }
  412. images = getImages(eng, t, false, "utest*")
  413. if len(images.Data[0].GetList("RepoTags")) != 1 {
  414. t.Fatal("incorrect number of matches returned")
  415. }
  416. images = getImages(eng, t, false, "*5000*/*")
  417. if len(images.Data[0].GetList("RepoTags")) != 1 {
  418. t.Fatal("incorrect number of matches returned")
  419. }
  420. }
  421. func TestImageInsert(t *testing.T) {
  422. eng := NewTestEngine(t)
  423. defer mkRuntimeFromEngine(eng, t).Nuke()
  424. srv := mkServerFromEngine(eng, t)
  425. // bad image name fails
  426. if err := srv.Eng.Job("insert", "foo", "https://www.docker.io/static/img/docker-top-logo.png", "/foo").Run(); err == nil {
  427. t.Fatal("expected an error and got none")
  428. }
  429. // bad url fails
  430. if err := srv.Eng.Job("insert", unitTestImageID, "http://bad_host_name_that_will_totally_fail.com/", "/foo").Run(); err == nil {
  431. t.Fatal("expected an error and got none")
  432. }
  433. // success returns nil
  434. if err := srv.Eng.Job("insert", unitTestImageID, "https://www.docker.io/static/img/docker-top-logo.png", "/foo").Run(); err != nil {
  435. t.Fatalf("expected no error, but got %v", err)
  436. }
  437. }
  438. func TestListContainers(t *testing.T) {
  439. eng := NewTestEngine(t)
  440. srv := mkServerFromEngine(eng, t)
  441. defer mkRuntimeFromEngine(eng, t).Nuke()
  442. config := docker.Config{
  443. Image: unitTestImageID,
  444. Cmd: []string{"/bin/sh", "-c", "cat"},
  445. OpenStdin: true,
  446. }
  447. firstID := createTestContainer(eng, &config, t)
  448. secondID := createTestContainer(eng, &config, t)
  449. thirdID := createTestContainer(eng, &config, t)
  450. fourthID := createTestContainer(eng, &config, t)
  451. defer func() {
  452. containerKill(eng, firstID, t)
  453. containerKill(eng, secondID, t)
  454. containerKill(eng, fourthID, t)
  455. containerWait(eng, firstID, t)
  456. containerWait(eng, secondID, t)
  457. containerWait(eng, fourthID, t)
  458. }()
  459. startContainer(eng, firstID, t)
  460. startContainer(eng, secondID, t)
  461. startContainer(eng, fourthID, t)
  462. // all
  463. if !assertContainerList(srv, true, -1, "", "", []string{fourthID, thirdID, secondID, firstID}) {
  464. t.Error("Container list is not in the correct order")
  465. }
  466. // running
  467. if !assertContainerList(srv, false, -1, "", "", []string{fourthID, secondID, firstID}) {
  468. t.Error("Container list is not in the correct order")
  469. }
  470. // from here 'all' flag is ignored
  471. // limit
  472. expected := []string{fourthID, thirdID}
  473. if !assertContainerList(srv, true, 2, "", "", expected) ||
  474. !assertContainerList(srv, false, 2, "", "", expected) {
  475. t.Error("Container list is not in the correct order")
  476. }
  477. // since
  478. expected = []string{fourthID, thirdID, secondID}
  479. if !assertContainerList(srv, true, -1, firstID, "", expected) ||
  480. !assertContainerList(srv, false, -1, firstID, "", expected) {
  481. t.Error("Container list is not in the correct order")
  482. }
  483. // before
  484. expected = []string{secondID, firstID}
  485. if !assertContainerList(srv, true, -1, "", thirdID, expected) ||
  486. !assertContainerList(srv, false, -1, "", thirdID, expected) {
  487. t.Error("Container list is not in the correct order")
  488. }
  489. // since & before
  490. expected = []string{thirdID, secondID}
  491. if !assertContainerList(srv, true, -1, firstID, fourthID, expected) ||
  492. !assertContainerList(srv, false, -1, firstID, fourthID, expected) {
  493. t.Error("Container list is not in the correct order")
  494. }
  495. // since & limit
  496. expected = []string{fourthID, thirdID}
  497. if !assertContainerList(srv, true, 2, firstID, "", expected) ||
  498. !assertContainerList(srv, false, 2, firstID, "", expected) {
  499. t.Error("Container list is not in the correct order")
  500. }
  501. // before & limit
  502. expected = []string{thirdID}
  503. if !assertContainerList(srv, true, 1, "", fourthID, expected) ||
  504. !assertContainerList(srv, false, 1, "", fourthID, expected) {
  505. t.Error("Container list is not in the correct order")
  506. }
  507. // since & before & limit
  508. expected = []string{thirdID}
  509. if !assertContainerList(srv, true, 1, firstID, fourthID, expected) ||
  510. !assertContainerList(srv, false, 1, firstID, fourthID, expected) {
  511. t.Error("Container list is not in the correct order")
  512. }
  513. }
  514. func assertContainerList(srv *docker.Server, all bool, limit int, since, before string, expected []string) bool {
  515. job := srv.Eng.Job("containers")
  516. job.SetenvBool("all", all)
  517. job.SetenvInt("limit", limit)
  518. job.Setenv("since", since)
  519. job.Setenv("before", before)
  520. outs, err := job.Stdout.AddListTable()
  521. if err != nil {
  522. return false
  523. }
  524. if err := job.Run(); err != nil {
  525. return false
  526. }
  527. if len(outs.Data) != len(expected) {
  528. return false
  529. }
  530. for i := 0; i < len(outs.Data); i++ {
  531. if outs.Data[i].Get("Id") != expected[i] {
  532. return false
  533. }
  534. }
  535. return true
  536. }
  537. // Regression test for being able to untag an image with an existing
  538. // container
  539. func TestDeleteTagWithExistingContainers(t *testing.T) {
  540. eng := NewTestEngine(t)
  541. defer nuke(mkRuntimeFromEngine(eng, t))
  542. srv := mkServerFromEngine(eng, t)
  543. // Tag the image
  544. if err := eng.Job("tag", unitTestImageID, "utest", "tag1").Run(); err != nil {
  545. t.Fatal(err)
  546. }
  547. // Create a container from the image
  548. config, _, _, err := docker.ParseRun([]string{unitTestImageID, "echo test"}, nil)
  549. if err != nil {
  550. t.Fatal(err)
  551. }
  552. id := createNamedTestContainer(eng, config, t, "testingtags")
  553. if id == "" {
  554. t.Fatal("No id returned")
  555. }
  556. job := srv.Eng.Job("containers")
  557. job.SetenvBool("all", true)
  558. outs, err := job.Stdout.AddListTable()
  559. if err != nil {
  560. t.Fatal(err)
  561. }
  562. if err := job.Run(); err != nil {
  563. t.Fatal(err)
  564. }
  565. if len(outs.Data) != 1 {
  566. t.Fatalf("Expected 1 container got %d", len(outs.Data))
  567. }
  568. // Try to remove the tag
  569. imgs, err := srv.DeleteImage("utest:tag1", true)
  570. if err != nil {
  571. t.Fatal(err)
  572. }
  573. if len(imgs.Data) != 1 {
  574. t.Fatalf("Should only have deleted one untag %d", len(imgs.Data))
  575. }
  576. if untag := imgs.Data[0].Get("Untagged"); untag != unitTestImageID {
  577. t.Fatalf("Expected %s got %s", unitTestImageID, untag)
  578. }
  579. }