api_test.go 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249
  1. package docker
  2. import (
  3. "archive/tar"
  4. "bufio"
  5. "bytes"
  6. "encoding/json"
  7. "fmt"
  8. "github.com/dotcloud/docker"
  9. "github.com/dotcloud/docker/utils"
  10. "io"
  11. "net"
  12. "net/http"
  13. "net/http/httptest"
  14. "strings"
  15. "testing"
  16. "time"
  17. )
  18. func TestGetVersion(t *testing.T) {
  19. eng := NewTestEngine(t)
  20. defer mkRuntimeFromEngine(eng, t).Nuke()
  21. srv := mkServerFromEngine(eng, t)
  22. var err error
  23. r := httptest.NewRecorder()
  24. req, err := http.NewRequest("GET", "/version", nil)
  25. if err != nil {
  26. t.Fatal(err)
  27. }
  28. // FIXME getting the version should require an actual running Server
  29. if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
  30. t.Fatal(err)
  31. }
  32. assertHttpNotError(r, t)
  33. v := &docker.APIVersion{}
  34. if err = json.Unmarshal(r.Body.Bytes(), v); err != nil {
  35. t.Fatal(err)
  36. }
  37. if v.Version != docker.VERSION {
  38. t.Errorf("Expected version %s, %s found", docker.VERSION, v.Version)
  39. }
  40. }
  41. func TestGetInfo(t *testing.T) {
  42. eng := NewTestEngine(t)
  43. defer mkRuntimeFromEngine(eng, t).Nuke()
  44. srv := mkServerFromEngine(eng, t)
  45. initialImages, err := srv.Images(false, "")
  46. if err != nil {
  47. t.Fatal(err)
  48. }
  49. req, err := http.NewRequest("GET", "/info", nil)
  50. if err != nil {
  51. t.Fatal(err)
  52. }
  53. r := httptest.NewRecorder()
  54. if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
  55. t.Fatal(err)
  56. }
  57. assertHttpNotError(r, t)
  58. infos := &docker.APIInfo{}
  59. err = json.Unmarshal(r.Body.Bytes(), infos)
  60. if err != nil {
  61. t.Fatal(err)
  62. }
  63. if infos.Images != len(initialImages) {
  64. t.Errorf("Expected images: %d, %d found", len(initialImages), infos.Images)
  65. }
  66. }
  67. func TestGetEvents(t *testing.T) {
  68. eng := NewTestEngine(t)
  69. srv := mkServerFromEngine(eng, t)
  70. // FIXME: we might not need runtime, why not simply nuke
  71. // the engine?
  72. runtime := mkRuntimeFromEngine(eng, t)
  73. defer nuke(runtime)
  74. var events []*utils.JSONMessage
  75. for _, parts := range [][3]string{
  76. {"fakeaction", "fakeid", "fakeimage"},
  77. {"fakeaction2", "fakeid", "fakeimage"},
  78. } {
  79. action, id, from := parts[0], parts[1], parts[2]
  80. ev := srv.LogEvent(action, id, from)
  81. events = append(events, ev)
  82. }
  83. req, err := http.NewRequest("GET", "/events?since=1", nil)
  84. if err != nil {
  85. t.Fatal(err)
  86. }
  87. r := httptest.NewRecorder()
  88. setTimeout(t, "", 500*time.Millisecond, func() {
  89. if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
  90. t.Fatal(err)
  91. }
  92. assertHttpNotError(r, t)
  93. })
  94. dec := json.NewDecoder(r.Body)
  95. for i := 0; i < 2; i++ {
  96. var jm utils.JSONMessage
  97. if err := dec.Decode(&jm); err == io.EOF {
  98. break
  99. } else if err != nil {
  100. t.Fatal(err)
  101. }
  102. if jm != *events[i] {
  103. t.Fatalf("Event received it different than expected")
  104. }
  105. }
  106. }
  107. func TestGetImagesJSON(t *testing.T) {
  108. eng := NewTestEngine(t)
  109. defer mkRuntimeFromEngine(eng, t).Nuke()
  110. srv := mkServerFromEngine(eng, t)
  111. // all=0
  112. initialImages, err := srv.Images(false, "")
  113. if err != nil {
  114. t.Fatal(err)
  115. }
  116. req, err := http.NewRequest("GET", "/images/json?all=0", nil)
  117. if err != nil {
  118. t.Fatal(err)
  119. }
  120. r := httptest.NewRecorder()
  121. if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
  122. t.Fatal(err)
  123. }
  124. assertHttpNotError(r, t)
  125. images := []docker.APIImages{}
  126. if err := json.Unmarshal(r.Body.Bytes(), &images); err != nil {
  127. t.Fatal(err)
  128. }
  129. if len(images) != len(initialImages) {
  130. t.Errorf("Expected %d image, %d found", len(initialImages), len(images))
  131. }
  132. found := false
  133. for _, img := range images {
  134. if strings.Contains(img.RepoTags[0], unitTestImageName) {
  135. found = true
  136. break
  137. }
  138. }
  139. if !found {
  140. t.Errorf("Expected image %s, %+v found", unitTestImageName, images)
  141. }
  142. r2 := httptest.NewRecorder()
  143. // all=1
  144. initialImages, err = srv.Images(true, "")
  145. if err != nil {
  146. t.Fatal(err)
  147. }
  148. req2, err := http.NewRequest("GET", "/images/json?all=true", nil)
  149. if err != nil {
  150. t.Fatal(err)
  151. }
  152. if err := docker.ServeRequest(srv, docker.APIVERSION, r2, req2); err != nil {
  153. t.Fatal(err)
  154. }
  155. assertHttpNotError(r2, t)
  156. images2 := []docker.APIImages{}
  157. if err := json.Unmarshal(r2.Body.Bytes(), &images2); err != nil {
  158. t.Fatal(err)
  159. }
  160. if len(images2) != len(initialImages) {
  161. t.Errorf("Expected %d image, %d found", len(initialImages), len(images2))
  162. }
  163. found = false
  164. for _, img := range images2 {
  165. if img.ID == unitTestImageID {
  166. found = true
  167. break
  168. }
  169. }
  170. if !found {
  171. t.Errorf("Retrieved image Id differs, expected %s, received %+v", unitTestImageID, images2)
  172. }
  173. r3 := httptest.NewRecorder()
  174. // filter=a
  175. req3, err := http.NewRequest("GET", "/images/json?filter=aaaaaaaaaa", nil)
  176. if err != nil {
  177. t.Fatal(err)
  178. }
  179. if err := docker.ServeRequest(srv, docker.APIVERSION, r3, req3); err != nil {
  180. t.Fatal(err)
  181. }
  182. assertHttpNotError(r3, t)
  183. images3 := []docker.APIImages{}
  184. if err := json.Unmarshal(r3.Body.Bytes(), &images3); err != nil {
  185. t.Fatal(err)
  186. }
  187. if len(images3) != 0 {
  188. t.Errorf("Expected 0 image, %d found", len(images3))
  189. }
  190. r4 := httptest.NewRecorder()
  191. // all=foobar
  192. req4, err := http.NewRequest("GET", "/images/json?all=foobar", nil)
  193. if err != nil {
  194. t.Fatal(err)
  195. }
  196. if err := docker.ServeRequest(srv, docker.APIVERSION, r4, req4); err != nil {
  197. t.Fatal(err)
  198. }
  199. // Don't assert against HTTP error since we expect an error
  200. if r4.Code != http.StatusBadRequest {
  201. t.Fatalf("%d Bad Request expected, received %d\n", http.StatusBadRequest, r4.Code)
  202. }
  203. }
  204. func TestGetImagesHistory(t *testing.T) {
  205. eng := NewTestEngine(t)
  206. defer mkRuntimeFromEngine(eng, t).Nuke()
  207. srv := mkServerFromEngine(eng, t)
  208. r := httptest.NewRecorder()
  209. req, err := http.NewRequest("GET", fmt.Sprintf("/images/%s/history", unitTestImageName), nil)
  210. if err != nil {
  211. t.Fatal(err)
  212. }
  213. if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
  214. t.Fatal(err)
  215. }
  216. assertHttpNotError(r, t)
  217. history := []docker.APIHistory{}
  218. if err := json.Unmarshal(r.Body.Bytes(), &history); err != nil {
  219. t.Fatal(err)
  220. }
  221. if len(history) != 1 {
  222. t.Errorf("Expected 1 line, %d found", len(history))
  223. }
  224. }
  225. func TestGetImagesByName(t *testing.T) {
  226. eng := NewTestEngine(t)
  227. defer mkRuntimeFromEngine(eng, t).Nuke()
  228. srv := mkServerFromEngine(eng, t)
  229. req, err := http.NewRequest("GET", "/images/"+unitTestImageName+"/json", nil)
  230. if err != nil {
  231. t.Fatal(err)
  232. }
  233. r := httptest.NewRecorder()
  234. if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
  235. t.Fatal(err)
  236. }
  237. assertHttpNotError(r, t)
  238. img := &docker.Image{}
  239. if err := json.Unmarshal(r.Body.Bytes(), img); err != nil {
  240. t.Fatal(err)
  241. }
  242. if img.ID != unitTestImageID {
  243. t.Errorf("Error inspecting image")
  244. }
  245. }
  246. func TestGetContainersJSON(t *testing.T) {
  247. eng := NewTestEngine(t)
  248. defer mkRuntimeFromEngine(eng, t).Nuke()
  249. srv := mkServerFromEngine(eng, t)
  250. beginLen := len(srv.Containers(true, false, -1, "", ""))
  251. containerID := createTestContainer(eng, &docker.Config{
  252. Image: unitTestImageID,
  253. Cmd: []string{"echo", "test"},
  254. }, t)
  255. req, err := http.NewRequest("GET", "/containers/json?all=1", nil)
  256. if err != nil {
  257. t.Fatal(err)
  258. }
  259. r := httptest.NewRecorder()
  260. if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
  261. t.Fatal(err)
  262. }
  263. assertHttpNotError(r, t)
  264. containers := []docker.APIContainers{}
  265. if err := json.Unmarshal(r.Body.Bytes(), &containers); err != nil {
  266. t.Fatal(err)
  267. }
  268. if len(containers) != beginLen+1 {
  269. t.Fatalf("Expected %d container, %d found (started with: %d)", beginLen+1, len(containers), beginLen)
  270. }
  271. if containers[0].ID != containerID {
  272. t.Fatalf("Container ID mismatch. Expected: %s, received: %s\n", containerID, containers[0].ID)
  273. }
  274. }
  275. func TestGetContainersExport(t *testing.T) {
  276. eng := NewTestEngine(t)
  277. defer mkRuntimeFromEngine(eng, t).Nuke()
  278. srv := mkServerFromEngine(eng, t)
  279. // Create a container and remove a file
  280. containerID := createTestContainer(eng,
  281. &docker.Config{
  282. Image: unitTestImageID,
  283. Cmd: []string{"touch", "/test"},
  284. },
  285. t,
  286. )
  287. containerRun(eng, containerID, t)
  288. r := httptest.NewRecorder()
  289. req, err := http.NewRequest("GET", "/containers/"+containerID+"/export", nil)
  290. if err != nil {
  291. t.Fatal(err)
  292. }
  293. if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
  294. t.Fatal(err)
  295. }
  296. assertHttpNotError(r, t)
  297. if r.Code != http.StatusOK {
  298. t.Fatalf("%d OK expected, received %d\n", http.StatusOK, r.Code)
  299. }
  300. found := false
  301. for tarReader := tar.NewReader(r.Body); ; {
  302. h, err := tarReader.Next()
  303. if err != nil {
  304. if err == io.EOF {
  305. break
  306. }
  307. t.Fatal(err)
  308. }
  309. if h.Name == "./test" {
  310. found = true
  311. break
  312. }
  313. }
  314. if !found {
  315. t.Fatalf("The created test file has not been found in the exported image")
  316. }
  317. }
  318. func TestGetContainersChanges(t *testing.T) {
  319. eng := NewTestEngine(t)
  320. defer mkRuntimeFromEngine(eng, t).Nuke()
  321. srv := mkServerFromEngine(eng, t)
  322. // Create a container and remove a file
  323. containerID := createTestContainer(eng,
  324. &docker.Config{
  325. Image: unitTestImageID,
  326. Cmd: []string{"/bin/rm", "/etc/passwd"},
  327. },
  328. t,
  329. )
  330. containerRun(eng, containerID, t)
  331. r := httptest.NewRecorder()
  332. req, err := http.NewRequest("GET", "/containers/"+containerID+"/changes", nil)
  333. if err != nil {
  334. t.Fatal(err)
  335. }
  336. if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
  337. t.Fatal(err)
  338. }
  339. assertHttpNotError(r, t)
  340. changes := []docker.Change{}
  341. if err := json.Unmarshal(r.Body.Bytes(), &changes); err != nil {
  342. t.Fatal(err)
  343. }
  344. // Check the changelog
  345. success := false
  346. for _, elem := range changes {
  347. if elem.Path == "/etc/passwd" && elem.Kind == 2 {
  348. success = true
  349. }
  350. }
  351. if !success {
  352. t.Fatalf("/etc/passwd as been removed but is not present in the diff")
  353. }
  354. }
  355. func TestGetContainersTop(t *testing.T) {
  356. t.Skip("Fixme. Skipping test for now. Reported error when testing using dind: 'api_test.go:527: Expected 2 processes, found 0.'")
  357. eng := NewTestEngine(t)
  358. defer mkRuntimeFromEngine(eng, t).Nuke()
  359. srv := mkServerFromEngine(eng, t)
  360. containerID := createTestContainer(eng,
  361. &docker.Config{
  362. Image: unitTestImageID,
  363. Cmd: []string{"/bin/sh", "-c", "cat"},
  364. OpenStdin: true,
  365. },
  366. t,
  367. )
  368. defer func() {
  369. // Make sure the process dies before destroying runtime
  370. containerKill(eng, containerID, t)
  371. containerWait(eng, containerID, t)
  372. }()
  373. startContainer(eng, containerID, t)
  374. setTimeout(t, "Waiting for the container to be started timed out", 10*time.Second, func() {
  375. for {
  376. if containerRunning(eng, containerID, t) {
  377. break
  378. }
  379. time.Sleep(10 * time.Millisecond)
  380. }
  381. })
  382. if !containerRunning(eng, containerID, t) {
  383. t.Fatalf("Container should be running")
  384. }
  385. // Make sure sh spawn up cat
  386. setTimeout(t, "read/write assertion timed out", 2*time.Second, func() {
  387. in, out := containerAttach(eng, containerID, t)
  388. if err := assertPipe("hello\n", "hello", out, in, 150); err != nil {
  389. t.Fatal(err)
  390. }
  391. })
  392. r := httptest.NewRecorder()
  393. req, err := http.NewRequest("GET", "/"+containerID+"/top?ps_args=u", bytes.NewReader([]byte{}))
  394. if err != nil {
  395. t.Fatal(err)
  396. }
  397. if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
  398. t.Fatal(err)
  399. }
  400. assertHttpNotError(r, t)
  401. procs := docker.APITop{}
  402. if err := json.Unmarshal(r.Body.Bytes(), &procs); err != nil {
  403. t.Fatal(err)
  404. }
  405. if len(procs.Titles) != 11 {
  406. t.Fatalf("Expected 11 titles, found %d.", len(procs.Titles))
  407. }
  408. if procs.Titles[0] != "USER" || procs.Titles[10] != "COMMAND" {
  409. t.Fatalf("Expected Titles[0] to be USER and Titles[10] to be COMMAND, found %s and %s.", procs.Titles[0], procs.Titles[10])
  410. }
  411. if len(procs.Processes) != 2 {
  412. t.Fatalf("Expected 2 processes, found %d.", len(procs.Processes))
  413. }
  414. if procs.Processes[0][10] != "/bin/sh" && procs.Processes[0][10] != "cat" {
  415. t.Fatalf("Expected `cat` or `/bin/sh`, found %s.", procs.Processes[0][10])
  416. }
  417. if procs.Processes[1][10] != "/bin/sh" && procs.Processes[1][10] != "cat" {
  418. t.Fatalf("Expected `cat` or `/bin/sh`, found %s.", procs.Processes[1][10])
  419. }
  420. }
  421. func TestGetContainersByName(t *testing.T) {
  422. eng := NewTestEngine(t)
  423. defer mkRuntimeFromEngine(eng, t).Nuke()
  424. srv := mkServerFromEngine(eng, t)
  425. // Create a container and remove a file
  426. containerID := createTestContainer(eng,
  427. &docker.Config{
  428. Image: unitTestImageID,
  429. Cmd: []string{"echo", "test"},
  430. },
  431. t,
  432. )
  433. r := httptest.NewRecorder()
  434. req, err := http.NewRequest("GET", "/containers/"+containerID+"/json", nil)
  435. if err != nil {
  436. t.Fatal(err)
  437. }
  438. if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
  439. t.Fatal(err)
  440. }
  441. assertHttpNotError(r, t)
  442. outContainer := &docker.Container{}
  443. if err := json.Unmarshal(r.Body.Bytes(), outContainer); err != nil {
  444. t.Fatal(err)
  445. }
  446. if outContainer.ID != containerID {
  447. t.Fatalf("Wrong containers retrieved. Expected %s, received %s", containerID, outContainer.ID)
  448. }
  449. }
  450. func TestPostCommit(t *testing.T) {
  451. eng := NewTestEngine(t)
  452. defer mkRuntimeFromEngine(eng, t).Nuke()
  453. srv := mkServerFromEngine(eng, t)
  454. // Create a container and remove a file
  455. containerID := createTestContainer(eng,
  456. &docker.Config{
  457. Image: unitTestImageID,
  458. Cmd: []string{"touch", "/test"},
  459. },
  460. t,
  461. )
  462. containerRun(eng, containerID, t)
  463. req, err := http.NewRequest("POST", "/commit?repo=testrepo&testtag=tag&container="+containerID, bytes.NewReader([]byte{}))
  464. if err != nil {
  465. t.Fatal(err)
  466. }
  467. r := httptest.NewRecorder()
  468. if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
  469. t.Fatal(err)
  470. }
  471. assertHttpNotError(r, t)
  472. if r.Code != http.StatusCreated {
  473. t.Fatalf("%d Created expected, received %d\n", http.StatusCreated, r.Code)
  474. }
  475. apiID := &docker.APIID{}
  476. if err := json.Unmarshal(r.Body.Bytes(), apiID); err != nil {
  477. t.Fatal(err)
  478. }
  479. if _, err := srv.ImageInspect(apiID.ID); err != nil {
  480. t.Fatalf("The image has not been committed")
  481. }
  482. }
  483. func TestPostContainersCreate(t *testing.T) {
  484. eng := NewTestEngine(t)
  485. defer mkRuntimeFromEngine(eng, t).Nuke()
  486. srv := mkServerFromEngine(eng, t)
  487. configJSON, err := json.Marshal(&docker.Config{
  488. Image: unitTestImageID,
  489. Memory: 33554432,
  490. Cmd: []string{"touch", "/test"},
  491. })
  492. if err != nil {
  493. t.Fatal(err)
  494. }
  495. req, err := http.NewRequest("POST", "/containers/create", bytes.NewReader(configJSON))
  496. if err != nil {
  497. t.Fatal(err)
  498. }
  499. r := httptest.NewRecorder()
  500. if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
  501. t.Fatal(err)
  502. }
  503. assertHttpNotError(r, t)
  504. if r.Code != http.StatusCreated {
  505. t.Fatalf("%d Created expected, received %d\n", http.StatusCreated, r.Code)
  506. }
  507. apiRun := &docker.APIRun{}
  508. if err := json.Unmarshal(r.Body.Bytes(), apiRun); err != nil {
  509. t.Fatal(err)
  510. }
  511. containerID := apiRun.ID
  512. containerAssertExists(eng, containerID, t)
  513. containerRun(eng, containerID, t)
  514. if !containerFileExists(eng, containerID, "test", t) {
  515. t.Fatal("Test file was not created")
  516. }
  517. }
  518. func TestPostContainersKill(t *testing.T) {
  519. eng := NewTestEngine(t)
  520. defer mkRuntimeFromEngine(eng, t).Nuke()
  521. srv := mkServerFromEngine(eng, t)
  522. containerID := createTestContainer(eng,
  523. &docker.Config{
  524. Image: unitTestImageID,
  525. Cmd: []string{"/bin/cat"},
  526. OpenStdin: true,
  527. },
  528. t,
  529. )
  530. startContainer(eng, containerID, t)
  531. // Give some time to the process to start
  532. containerWaitTimeout(eng, containerID, t)
  533. if !containerRunning(eng, containerID, t) {
  534. t.Errorf("Container should be running")
  535. }
  536. r := httptest.NewRecorder()
  537. req, err := http.NewRequest("POST", "/containers/"+containerID+"/kill", bytes.NewReader([]byte{}))
  538. if err != nil {
  539. t.Fatal(err)
  540. }
  541. if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
  542. t.Fatal(err)
  543. }
  544. assertHttpNotError(r, t)
  545. if r.Code != http.StatusNoContent {
  546. t.Fatalf("%d NO CONTENT expected, received %d\n", http.StatusNoContent, r.Code)
  547. }
  548. if containerRunning(eng, containerID, t) {
  549. t.Fatalf("The container hasn't been killed")
  550. }
  551. }
  552. func TestPostContainersRestart(t *testing.T) {
  553. eng := NewTestEngine(t)
  554. defer mkRuntimeFromEngine(eng, t).Nuke()
  555. srv := mkServerFromEngine(eng, t)
  556. containerID := createTestContainer(eng,
  557. &docker.Config{
  558. Image: unitTestImageID,
  559. Cmd: []string{"/bin/top"},
  560. OpenStdin: true,
  561. },
  562. t,
  563. )
  564. startContainer(eng, containerID, t)
  565. // Give some time to the process to start
  566. containerWaitTimeout(eng, containerID, t)
  567. if !containerRunning(eng, containerID, t) {
  568. t.Errorf("Container should be running")
  569. }
  570. req, err := http.NewRequest("POST", "/containers/"+containerID+"/restart?t=1", bytes.NewReader([]byte{}))
  571. if err != nil {
  572. t.Fatal(err)
  573. }
  574. r := httptest.NewRecorder()
  575. if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
  576. t.Fatal(err)
  577. }
  578. assertHttpNotError(r, t)
  579. if r.Code != http.StatusNoContent {
  580. t.Fatalf("%d NO CONTENT expected, received %d\n", http.StatusNoContent, r.Code)
  581. }
  582. // Give some time to the process to restart
  583. containerWaitTimeout(eng, containerID, t)
  584. if !containerRunning(eng, containerID, t) {
  585. t.Fatalf("Container should be running")
  586. }
  587. containerKill(eng, containerID, t)
  588. }
  589. func TestPostContainersStart(t *testing.T) {
  590. eng := NewTestEngine(t)
  591. defer mkRuntimeFromEngine(eng, t).Nuke()
  592. srv := mkServerFromEngine(eng, t)
  593. containerID := createTestContainer(
  594. eng,
  595. &docker.Config{
  596. Image: unitTestImageID,
  597. Cmd: []string{"/bin/cat"},
  598. OpenStdin: true,
  599. },
  600. t,
  601. )
  602. hostConfigJSON, err := json.Marshal(&docker.HostConfig{})
  603. req, err := http.NewRequest("POST", "/containers/"+containerID+"/start", bytes.NewReader(hostConfigJSON))
  604. if err != nil {
  605. t.Fatal(err)
  606. }
  607. req.Header.Set("Content-Type", "application/json")
  608. r := httptest.NewRecorder()
  609. if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
  610. t.Fatal(err)
  611. }
  612. assertHttpNotError(r, t)
  613. if r.Code != http.StatusNoContent {
  614. t.Fatalf("%d NO CONTENT expected, received %d\n", http.StatusNoContent, r.Code)
  615. }
  616. containerAssertExists(eng, containerID, t)
  617. // Give some time to the process to start
  618. // FIXME: use Wait once it's available as a job
  619. containerWaitTimeout(eng, containerID, t)
  620. if !containerRunning(eng, containerID, t) {
  621. t.Errorf("Container should be running")
  622. }
  623. r = httptest.NewRecorder()
  624. if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
  625. t.Fatal(err)
  626. }
  627. // Starting an already started container should return an error
  628. // FIXME: verify a precise error code. There is a possible bug here
  629. // which causes this to return 404 even though the container exists.
  630. assertHttpError(r, t)
  631. containerAssertExists(eng, containerID, t)
  632. containerKill(eng, containerID, t)
  633. }
  634. // Expected behaviour: using / as a bind mount source should throw an error
  635. func TestRunErrorBindMountRootSource(t *testing.T) {
  636. eng := NewTestEngine(t)
  637. defer mkRuntimeFromEngine(eng, t).Nuke()
  638. srv := mkServerFromEngine(eng, t)
  639. containerID := createTestContainer(
  640. eng,
  641. &docker.Config{
  642. Image: unitTestImageID,
  643. Cmd: []string{"/bin/cat"},
  644. OpenStdin: true,
  645. },
  646. t,
  647. )
  648. hostConfigJSON, err := json.Marshal(&docker.HostConfig{
  649. Binds: []string{"/:/tmp"},
  650. })
  651. req, err := http.NewRequest("POST", "/containers/"+containerID+"/start", bytes.NewReader(hostConfigJSON))
  652. if err != nil {
  653. t.Fatal(err)
  654. }
  655. req.Header.Set("Content-Type", "application/json")
  656. r := httptest.NewRecorder()
  657. if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
  658. t.Fatal(err)
  659. }
  660. if r.Code != http.StatusInternalServerError {
  661. containerKill(eng, containerID, t)
  662. t.Fatal("should have failed to run when using / as a source for the bind mount")
  663. }
  664. }
  665. func TestPostContainersStop(t *testing.T) {
  666. eng := NewTestEngine(t)
  667. defer mkRuntimeFromEngine(eng, t).Nuke()
  668. srv := mkServerFromEngine(eng, t)
  669. containerID := createTestContainer(eng,
  670. &docker.Config{
  671. Image: unitTestImageID,
  672. Cmd: []string{"/bin/top"},
  673. OpenStdin: true,
  674. },
  675. t,
  676. )
  677. startContainer(eng, containerID, t)
  678. // Give some time to the process to start
  679. containerWaitTimeout(eng, containerID, t)
  680. if !containerRunning(eng, containerID, t) {
  681. t.Errorf("Container should be running")
  682. }
  683. // Note: as it is a POST request, it requires a body.
  684. req, err := http.NewRequest("POST", "/containers/"+containerID+"/stop?t=1", bytes.NewReader([]byte{}))
  685. if err != nil {
  686. t.Fatal(err)
  687. }
  688. r := httptest.NewRecorder()
  689. if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
  690. t.Fatal(err)
  691. }
  692. assertHttpNotError(r, t)
  693. if r.Code != http.StatusNoContent {
  694. t.Fatalf("%d NO CONTENT expected, received %d\n", http.StatusNoContent, r.Code)
  695. }
  696. if containerRunning(eng, containerID, t) {
  697. t.Fatalf("The container hasn't been stopped")
  698. }
  699. }
  700. func TestPostContainersWait(t *testing.T) {
  701. eng := NewTestEngine(t)
  702. defer mkRuntimeFromEngine(eng, t).Nuke()
  703. srv := mkServerFromEngine(eng, t)
  704. containerID := createTestContainer(eng,
  705. &docker.Config{
  706. Image: unitTestImageID,
  707. Cmd: []string{"/bin/sleep", "1"},
  708. OpenStdin: true,
  709. },
  710. t,
  711. )
  712. startContainer(eng, containerID, t)
  713. setTimeout(t, "Wait timed out", 3*time.Second, func() {
  714. r := httptest.NewRecorder()
  715. req, err := http.NewRequest("POST", "/containers/"+containerID+"/wait", bytes.NewReader([]byte{}))
  716. if err != nil {
  717. t.Fatal(err)
  718. }
  719. if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
  720. t.Fatal(err)
  721. }
  722. assertHttpNotError(r, t)
  723. apiWait := &docker.APIWait{}
  724. if err := json.Unmarshal(r.Body.Bytes(), apiWait); err != nil {
  725. t.Fatal(err)
  726. }
  727. if apiWait.StatusCode != 0 {
  728. t.Fatalf("Non zero exit code for sleep: %d\n", apiWait.StatusCode)
  729. }
  730. })
  731. if containerRunning(eng, containerID, t) {
  732. t.Fatalf("The container should be stopped after wait")
  733. }
  734. }
  735. func TestPostContainersAttach(t *testing.T) {
  736. eng := NewTestEngine(t)
  737. defer mkRuntimeFromEngine(eng, t).Nuke()
  738. srv := mkServerFromEngine(eng, t)
  739. containerID := createTestContainer(eng,
  740. &docker.Config{
  741. Image: unitTestImageID,
  742. Cmd: []string{"/bin/cat"},
  743. OpenStdin: true,
  744. },
  745. t,
  746. )
  747. // Start the process
  748. startContainer(eng, containerID, t)
  749. stdin, stdinPipe := io.Pipe()
  750. stdout, stdoutPipe := io.Pipe()
  751. // Try to avoid the timeout in destroy. Best effort, don't check error
  752. defer func() {
  753. closeWrap(stdin, stdinPipe, stdout, stdoutPipe)
  754. containerKill(eng, containerID, t)
  755. }()
  756. // Attach to it
  757. c1 := make(chan struct{})
  758. go func() {
  759. defer close(c1)
  760. r := &hijackTester{
  761. ResponseRecorder: httptest.NewRecorder(),
  762. in: stdin,
  763. out: stdoutPipe,
  764. }
  765. req, err := http.NewRequest("POST", "/containers/"+containerID+"/attach?stream=1&stdin=1&stdout=1&stderr=1", bytes.NewReader([]byte{}))
  766. if err != nil {
  767. t.Fatal(err)
  768. }
  769. if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
  770. t.Fatal(err)
  771. }
  772. assertHttpNotError(r.ResponseRecorder, t)
  773. }()
  774. // Acknowledge hijack
  775. setTimeout(t, "hijack acknowledge timed out", 2*time.Second, func() {
  776. stdout.Read([]byte{})
  777. stdout.Read(make([]byte, 4096))
  778. })
  779. setTimeout(t, "read/write assertion timed out", 2*time.Second, func() {
  780. if err := assertPipe("hello\n", string([]byte{1, 0, 0, 0, 0, 0, 0, 6})+"hello", stdout, stdinPipe, 150); err != nil {
  781. t.Fatal(err)
  782. }
  783. })
  784. // Close pipes (client disconnects)
  785. if err := closeWrap(stdin, stdinPipe, stdout, stdoutPipe); err != nil {
  786. t.Fatal(err)
  787. }
  788. // Wait for attach to finish, the client disconnected, therefore, Attach finished his job
  789. setTimeout(t, "Waiting for CmdAttach timed out", 10*time.Second, func() {
  790. <-c1
  791. })
  792. // We closed stdin, expect /bin/cat to still be running
  793. // Wait a little bit to make sure container.monitor() did his thing
  794. containerWaitTimeout(eng, containerID, t)
  795. // Try to avoid the timeout in destroy. Best effort, don't check error
  796. cStdin, _ := containerAttach(eng, containerID, t)
  797. cStdin.Close()
  798. containerWait(eng, containerID, t)
  799. }
  800. func TestPostContainersAttachStderr(t *testing.T) {
  801. eng := NewTestEngine(t)
  802. defer mkRuntimeFromEngine(eng, t).Nuke()
  803. srv := mkServerFromEngine(eng, t)
  804. containerID := createTestContainer(eng,
  805. &docker.Config{
  806. Image: unitTestImageID,
  807. Cmd: []string{"/bin/sh", "-c", "/bin/cat >&2"},
  808. OpenStdin: true,
  809. },
  810. t,
  811. )
  812. // Start the process
  813. startContainer(eng, containerID, t)
  814. stdin, stdinPipe := io.Pipe()
  815. stdout, stdoutPipe := io.Pipe()
  816. // Try to avoid the timeout in destroy. Best effort, don't check error
  817. defer func() {
  818. closeWrap(stdin, stdinPipe, stdout, stdoutPipe)
  819. containerKill(eng, containerID, t)
  820. }()
  821. // Attach to it
  822. c1 := make(chan struct{})
  823. go func() {
  824. defer close(c1)
  825. r := &hijackTester{
  826. ResponseRecorder: httptest.NewRecorder(),
  827. in: stdin,
  828. out: stdoutPipe,
  829. }
  830. req, err := http.NewRequest("POST", "/containers/"+containerID+"/attach?stream=1&stdin=1&stdout=1&stderr=1", bytes.NewReader([]byte{}))
  831. if err != nil {
  832. t.Fatal(err)
  833. }
  834. if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
  835. t.Fatal(err)
  836. }
  837. assertHttpNotError(r.ResponseRecorder, t)
  838. }()
  839. // Acknowledge hijack
  840. setTimeout(t, "hijack acknowledge timed out", 2*time.Second, func() {
  841. stdout.Read([]byte{})
  842. stdout.Read(make([]byte, 4096))
  843. })
  844. setTimeout(t, "read/write assertion timed out", 2*time.Second, func() {
  845. if err := assertPipe("hello\n", string([]byte{2, 0, 0, 0, 0, 0, 0, 6})+"hello", stdout, stdinPipe, 150); err != nil {
  846. t.Fatal(err)
  847. }
  848. })
  849. // Close pipes (client disconnects)
  850. if err := closeWrap(stdin, stdinPipe, stdout, stdoutPipe); err != nil {
  851. t.Fatal(err)
  852. }
  853. // Wait for attach to finish, the client disconnected, therefore, Attach finished his job
  854. setTimeout(t, "Waiting for CmdAttach timed out", 10*time.Second, func() {
  855. <-c1
  856. })
  857. // We closed stdin, expect /bin/cat to still be running
  858. // Wait a little bit to make sure container.monitor() did his thing
  859. containerWaitTimeout(eng, containerID, t)
  860. // Try to avoid the timeout in destroy. Best effort, don't check error
  861. cStdin, _ := containerAttach(eng, containerID, t)
  862. cStdin.Close()
  863. containerWait(eng, containerID, t)
  864. }
  865. // FIXME: Test deleting running container
  866. // FIXME: Test deleting container with volume
  867. // FIXME: Test deleting volume in use by other container
  868. func TestDeleteContainers(t *testing.T) {
  869. eng := NewTestEngine(t)
  870. defer mkRuntimeFromEngine(eng, t).Nuke()
  871. srv := mkServerFromEngine(eng, t)
  872. containerID := createTestContainer(eng,
  873. &docker.Config{
  874. Image: unitTestImageID,
  875. Cmd: []string{"touch", "/test"},
  876. },
  877. t,
  878. )
  879. req, err := http.NewRequest("DELETE", "/containers/"+containerID, nil)
  880. if err != nil {
  881. t.Fatal(err)
  882. }
  883. r := httptest.NewRecorder()
  884. if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
  885. t.Fatal(err)
  886. }
  887. assertHttpNotError(r, t)
  888. if r.Code != http.StatusNoContent {
  889. t.Fatalf("%d NO CONTENT expected, received %d\n", http.StatusNoContent, r.Code)
  890. }
  891. containerAssertNotExists(eng, containerID, t)
  892. }
  893. func TestOptionsRoute(t *testing.T) {
  894. eng := NewTestEngine(t)
  895. defer mkRuntimeFromEngine(eng, t).Nuke()
  896. srv := mkServerFromEngine(eng, t)
  897. r := httptest.NewRecorder()
  898. req, err := http.NewRequest("OPTIONS", "/", nil)
  899. if err != nil {
  900. t.Fatal(err)
  901. }
  902. if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
  903. t.Fatal(err)
  904. }
  905. assertHttpNotError(r, t)
  906. if r.Code != http.StatusOK {
  907. t.Errorf("Expected response for OPTIONS request to be \"200\", %v found.", r.Code)
  908. }
  909. }
  910. func TestGetEnabledCors(t *testing.T) {
  911. eng := NewTestEngine(t)
  912. defer mkRuntimeFromEngine(eng, t).Nuke()
  913. srv := mkServerFromEngine(eng, t)
  914. r := httptest.NewRecorder()
  915. req, err := http.NewRequest("GET", "/version", nil)
  916. if err != nil {
  917. t.Fatal(err)
  918. }
  919. if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
  920. t.Fatal(err)
  921. }
  922. assertHttpNotError(r, t)
  923. if r.Code != http.StatusOK {
  924. t.Errorf("Expected response for OPTIONS request to be \"200\", %v found.", r.Code)
  925. }
  926. allowOrigin := r.Header().Get("Access-Control-Allow-Origin")
  927. allowHeaders := r.Header().Get("Access-Control-Allow-Headers")
  928. allowMethods := r.Header().Get("Access-Control-Allow-Methods")
  929. if allowOrigin != "*" {
  930. t.Errorf("Expected header Access-Control-Allow-Origin to be \"*\", %s found.", allowOrigin)
  931. }
  932. if allowHeaders != "Origin, X-Requested-With, Content-Type, Accept" {
  933. t.Errorf("Expected header Access-Control-Allow-Headers to be \"Origin, X-Requested-With, Content-Type, Accept\", %s found.", allowHeaders)
  934. }
  935. if allowMethods != "GET, POST, DELETE, PUT, OPTIONS" {
  936. t.Errorf("Expected hearder Access-Control-Allow-Methods to be \"GET, POST, DELETE, PUT, OPTIONS\", %s found.", allowMethods)
  937. }
  938. }
  939. func TestDeleteImages(t *testing.T) {
  940. eng := NewTestEngine(t)
  941. defer mkRuntimeFromEngine(eng, t).Nuke()
  942. srv := mkServerFromEngine(eng, t)
  943. initialImages, err := srv.Images(false, "")
  944. if err != nil {
  945. t.Fatal(err)
  946. }
  947. if err := srv.ContainerTag(unitTestImageName, "test", "test", false); err != nil {
  948. t.Fatal(err)
  949. }
  950. images, err := srv.Images(false, "")
  951. if err != nil {
  952. t.Fatal(err)
  953. }
  954. if len(images[0].RepoTags) != len(initialImages[0].RepoTags)+1 {
  955. t.Errorf("Expected %d images, %d found", len(initialImages)+1, len(images))
  956. }
  957. req, err := http.NewRequest("DELETE", "/images/"+unitTestImageID, nil)
  958. if err != nil {
  959. t.Fatal(err)
  960. }
  961. r := httptest.NewRecorder()
  962. if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
  963. t.Fatal(err)
  964. }
  965. if r.Code != http.StatusConflict {
  966. t.Fatalf("Expected http status 409-conflict, got %v", r.Code)
  967. }
  968. req2, err := http.NewRequest("DELETE", "/images/test:test", nil)
  969. if err != nil {
  970. t.Fatal(err)
  971. }
  972. r2 := httptest.NewRecorder()
  973. if err := docker.ServeRequest(srv, docker.APIVERSION, r2, req2); err != nil {
  974. t.Fatal(err)
  975. }
  976. assertHttpNotError(r2, t)
  977. if r2.Code != http.StatusOK {
  978. t.Fatalf("%d OK expected, received %d\n", http.StatusOK, r.Code)
  979. }
  980. var outs []docker.APIRmi
  981. if err := json.Unmarshal(r2.Body.Bytes(), &outs); err != nil {
  982. t.Fatal(err)
  983. }
  984. if len(outs) != 1 {
  985. t.Fatalf("Expected %d event (untagged), got %d", 1, len(outs))
  986. }
  987. images, err = srv.Images(false, "")
  988. if err != nil {
  989. t.Fatal(err)
  990. }
  991. if len(images[0].RepoTags) != len(initialImages[0].RepoTags) {
  992. t.Errorf("Expected %d image, %d found", len(initialImages), len(images))
  993. }
  994. }
  995. func TestPostContainersCopy(t *testing.T) {
  996. eng := NewTestEngine(t)
  997. defer mkRuntimeFromEngine(eng, t).Nuke()
  998. srv := mkServerFromEngine(eng, t)
  999. // Create a container and remove a file
  1000. containerID := createTestContainer(eng,
  1001. &docker.Config{
  1002. Image: unitTestImageID,
  1003. Cmd: []string{"touch", "/test.txt"},
  1004. },
  1005. t,
  1006. )
  1007. containerRun(eng, containerID, t)
  1008. r := httptest.NewRecorder()
  1009. copyData := docker.APICopy{HostPath: ".", Resource: "/test.txt"}
  1010. jsonData, err := json.Marshal(copyData)
  1011. if err != nil {
  1012. t.Fatal(err)
  1013. }
  1014. req, err := http.NewRequest("POST", "/containers/"+containerID+"/copy", bytes.NewReader(jsonData))
  1015. if err != nil {
  1016. t.Fatal(err)
  1017. }
  1018. req.Header.Add("Content-Type", "application/json")
  1019. if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
  1020. t.Fatal(err)
  1021. }
  1022. assertHttpNotError(r, t)
  1023. if r.Code != http.StatusOK {
  1024. t.Fatalf("%d OK expected, received %d\n", http.StatusOK, r.Code)
  1025. }
  1026. found := false
  1027. for tarReader := tar.NewReader(r.Body); ; {
  1028. h, err := tarReader.Next()
  1029. if err != nil {
  1030. if err == io.EOF {
  1031. break
  1032. }
  1033. t.Fatal(err)
  1034. }
  1035. if h.Name == "test.txt" {
  1036. found = true
  1037. break
  1038. }
  1039. }
  1040. if !found {
  1041. t.Fatalf("The created test file has not been found in the copied output")
  1042. }
  1043. }
  1044. // Mocked types for tests
  1045. type NopConn struct {
  1046. io.ReadCloser
  1047. io.Writer
  1048. }
  1049. func (c *NopConn) LocalAddr() net.Addr { return nil }
  1050. func (c *NopConn) RemoteAddr() net.Addr { return nil }
  1051. func (c *NopConn) SetDeadline(t time.Time) error { return nil }
  1052. func (c *NopConn) SetReadDeadline(t time.Time) error { return nil }
  1053. func (c *NopConn) SetWriteDeadline(t time.Time) error { return nil }
  1054. type hijackTester struct {
  1055. *httptest.ResponseRecorder
  1056. in io.ReadCloser
  1057. out io.Writer
  1058. }
  1059. func (t *hijackTester) Hijack() (net.Conn, *bufio.ReadWriter, error) {
  1060. bufrw := bufio.NewReadWriter(bufio.NewReader(t.in), bufio.NewWriter(t.out))
  1061. conn := &NopConn{
  1062. ReadCloser: t.in,
  1063. Writer: t.out,
  1064. }
  1065. return conn, bufrw, nil
  1066. }