api_test.go 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212
  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, 15); 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. func TestPostContainersStop(t *testing.T) {
  635. eng := NewTestEngine(t)
  636. defer mkRuntimeFromEngine(eng, t).Nuke()
  637. srv := mkServerFromEngine(eng, t)
  638. containerID := createTestContainer(eng,
  639. &docker.Config{
  640. Image: unitTestImageID,
  641. Cmd: []string{"/bin/top"},
  642. OpenStdin: true,
  643. },
  644. t,
  645. )
  646. startContainer(eng, containerID, t)
  647. // Give some time to the process to start
  648. containerWaitTimeout(eng, containerID, t)
  649. if !containerRunning(eng, containerID, t) {
  650. t.Errorf("Container should be running")
  651. }
  652. // Note: as it is a POST request, it requires a body.
  653. req, err := http.NewRequest("POST", "/containers/"+containerID+"/stop?t=1", bytes.NewReader([]byte{}))
  654. if err != nil {
  655. t.Fatal(err)
  656. }
  657. r := httptest.NewRecorder()
  658. if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
  659. t.Fatal(err)
  660. }
  661. assertHttpNotError(r, t)
  662. if r.Code != http.StatusNoContent {
  663. t.Fatalf("%d NO CONTENT expected, received %d\n", http.StatusNoContent, r.Code)
  664. }
  665. if containerRunning(eng, containerID, t) {
  666. t.Fatalf("The container hasn't been stopped")
  667. }
  668. }
  669. func TestPostContainersWait(t *testing.T) {
  670. eng := NewTestEngine(t)
  671. defer mkRuntimeFromEngine(eng, t).Nuke()
  672. srv := mkServerFromEngine(eng, t)
  673. containerID := createTestContainer(eng,
  674. &docker.Config{
  675. Image: unitTestImageID,
  676. Cmd: []string{"/bin/sleep", "1"},
  677. OpenStdin: true,
  678. },
  679. t,
  680. )
  681. startContainer(eng, containerID, t)
  682. setTimeout(t, "Wait timed out", 3*time.Second, func() {
  683. r := httptest.NewRecorder()
  684. req, err := http.NewRequest("POST", "/containers/"+containerID+"/wait", bytes.NewReader([]byte{}))
  685. if err != nil {
  686. t.Fatal(err)
  687. }
  688. if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
  689. t.Fatal(err)
  690. }
  691. assertHttpNotError(r, t)
  692. apiWait := &docker.APIWait{}
  693. if err := json.Unmarshal(r.Body.Bytes(), apiWait); err != nil {
  694. t.Fatal(err)
  695. }
  696. if apiWait.StatusCode != 0 {
  697. t.Fatalf("Non zero exit code for sleep: %d\n", apiWait.StatusCode)
  698. }
  699. })
  700. if containerRunning(eng, containerID, t) {
  701. t.Fatalf("The container should be stopped after wait")
  702. }
  703. }
  704. func TestPostContainersAttach(t *testing.T) {
  705. eng := NewTestEngine(t)
  706. defer mkRuntimeFromEngine(eng, t).Nuke()
  707. srv := mkServerFromEngine(eng, t)
  708. containerID := createTestContainer(eng,
  709. &docker.Config{
  710. Image: unitTestImageID,
  711. Cmd: []string{"/bin/cat"},
  712. OpenStdin: true,
  713. },
  714. t,
  715. )
  716. // Start the process
  717. startContainer(eng, containerID, t)
  718. stdin, stdinPipe := io.Pipe()
  719. stdout, stdoutPipe := io.Pipe()
  720. // Try to avoid the timeout in destroy. Best effort, don't check error
  721. defer func() {
  722. closeWrap(stdin, stdinPipe, stdout, stdoutPipe)
  723. containerKill(eng, containerID, t)
  724. }()
  725. // Attach to it
  726. c1 := make(chan struct{})
  727. go func() {
  728. defer close(c1)
  729. r := &hijackTester{
  730. ResponseRecorder: httptest.NewRecorder(),
  731. in: stdin,
  732. out: stdoutPipe,
  733. }
  734. req, err := http.NewRequest("POST", "/containers/"+containerID+"/attach?stream=1&stdin=1&stdout=1&stderr=1", bytes.NewReader([]byte{}))
  735. if err != nil {
  736. t.Fatal(err)
  737. }
  738. if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
  739. t.Fatal(err)
  740. }
  741. assertHttpNotError(r.ResponseRecorder, t)
  742. }()
  743. // Acknowledge hijack
  744. setTimeout(t, "hijack acknowledge timed out", 2*time.Second, func() {
  745. stdout.Read([]byte{})
  746. stdout.Read(make([]byte, 4096))
  747. })
  748. setTimeout(t, "read/write assertion timed out", 2*time.Second, func() {
  749. if err := assertPipe("hello\n", string([]byte{1, 0, 0, 0, 0, 0, 0, 6})+"hello", stdout, stdinPipe, 15); err != nil {
  750. t.Fatal(err)
  751. }
  752. })
  753. // Close pipes (client disconnects)
  754. if err := closeWrap(stdin, stdinPipe, stdout, stdoutPipe); err != nil {
  755. t.Fatal(err)
  756. }
  757. // Wait for attach to finish, the client disconnected, therefore, Attach finished his job
  758. setTimeout(t, "Waiting for CmdAttach timed out", 10*time.Second, func() {
  759. <-c1
  760. })
  761. // We closed stdin, expect /bin/cat to still be running
  762. // Wait a little bit to make sure container.monitor() did his thing
  763. containerWaitTimeout(eng, containerID, t)
  764. // Try to avoid the timeout in destroy. Best effort, don't check error
  765. cStdin, _ := containerAttach(eng, containerID, t)
  766. cStdin.Close()
  767. containerWait(eng, containerID, t)
  768. }
  769. func TestPostContainersAttachStderr(t *testing.T) {
  770. eng := NewTestEngine(t)
  771. defer mkRuntimeFromEngine(eng, t).Nuke()
  772. srv := mkServerFromEngine(eng, t)
  773. containerID := createTestContainer(eng,
  774. &docker.Config{
  775. Image: unitTestImageID,
  776. Cmd: []string{"/bin/sh", "-c", "/bin/cat >&2"},
  777. OpenStdin: true,
  778. },
  779. t,
  780. )
  781. // Start the process
  782. startContainer(eng, containerID, t)
  783. stdin, stdinPipe := io.Pipe()
  784. stdout, stdoutPipe := io.Pipe()
  785. // Try to avoid the timeout in destroy. Best effort, don't check error
  786. defer func() {
  787. closeWrap(stdin, stdinPipe, stdout, stdoutPipe)
  788. containerKill(eng, containerID, t)
  789. }()
  790. // Attach to it
  791. c1 := make(chan struct{})
  792. go func() {
  793. defer close(c1)
  794. r := &hijackTester{
  795. ResponseRecorder: httptest.NewRecorder(),
  796. in: stdin,
  797. out: stdoutPipe,
  798. }
  799. req, err := http.NewRequest("POST", "/containers/"+containerID+"/attach?stream=1&stdin=1&stdout=1&stderr=1", bytes.NewReader([]byte{}))
  800. if err != nil {
  801. t.Fatal(err)
  802. }
  803. if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
  804. t.Fatal(err)
  805. }
  806. assertHttpNotError(r.ResponseRecorder, t)
  807. }()
  808. // Acknowledge hijack
  809. setTimeout(t, "hijack acknowledge timed out", 2*time.Second, func() {
  810. stdout.Read([]byte{})
  811. stdout.Read(make([]byte, 4096))
  812. })
  813. setTimeout(t, "read/write assertion timed out", 2*time.Second, func() {
  814. if err := assertPipe("hello\n", string([]byte{2, 0, 0, 0, 0, 0, 0, 6})+"hello", stdout, stdinPipe, 15); err != nil {
  815. t.Fatal(err)
  816. }
  817. })
  818. // Close pipes (client disconnects)
  819. if err := closeWrap(stdin, stdinPipe, stdout, stdoutPipe); err != nil {
  820. t.Fatal(err)
  821. }
  822. // Wait for attach to finish, the client disconnected, therefore, Attach finished his job
  823. setTimeout(t, "Waiting for CmdAttach timed out", 10*time.Second, func() {
  824. <-c1
  825. })
  826. // We closed stdin, expect /bin/cat to still be running
  827. // Wait a little bit to make sure container.monitor() did his thing
  828. containerWaitTimeout(eng, containerID, t)
  829. // Try to avoid the timeout in destroy. Best effort, don't check error
  830. cStdin, _ := containerAttach(eng, containerID, t)
  831. cStdin.Close()
  832. containerWait(eng, containerID, t)
  833. }
  834. // FIXME: Test deleting running container
  835. // FIXME: Test deleting container with volume
  836. // FIXME: Test deleting volume in use by other container
  837. func TestDeleteContainers(t *testing.T) {
  838. eng := NewTestEngine(t)
  839. defer mkRuntimeFromEngine(eng, t).Nuke()
  840. srv := mkServerFromEngine(eng, t)
  841. containerID := createTestContainer(eng,
  842. &docker.Config{
  843. Image: unitTestImageID,
  844. Cmd: []string{"touch", "/test"},
  845. },
  846. t,
  847. )
  848. req, err := http.NewRequest("DELETE", "/containers/"+containerID, nil)
  849. if err != nil {
  850. t.Fatal(err)
  851. }
  852. r := httptest.NewRecorder()
  853. if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
  854. t.Fatal(err)
  855. }
  856. assertHttpNotError(r, t)
  857. if r.Code != http.StatusNoContent {
  858. t.Fatalf("%d NO CONTENT expected, received %d\n", http.StatusNoContent, r.Code)
  859. }
  860. containerAssertNotExists(eng, containerID, t)
  861. }
  862. func TestOptionsRoute(t *testing.T) {
  863. eng := NewTestEngine(t)
  864. defer mkRuntimeFromEngine(eng, t).Nuke()
  865. srv := mkServerFromEngine(eng, t)
  866. r := httptest.NewRecorder()
  867. req, err := http.NewRequest("OPTIONS", "/", nil)
  868. if err != nil {
  869. t.Fatal(err)
  870. }
  871. if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
  872. t.Fatal(err)
  873. }
  874. assertHttpNotError(r, t)
  875. if r.Code != http.StatusOK {
  876. t.Errorf("Expected response for OPTIONS request to be \"200\", %v found.", r.Code)
  877. }
  878. }
  879. func TestGetEnabledCors(t *testing.T) {
  880. eng := NewTestEngine(t)
  881. defer mkRuntimeFromEngine(eng, t).Nuke()
  882. srv := mkServerFromEngine(eng, t)
  883. r := httptest.NewRecorder()
  884. req, err := http.NewRequest("GET", "/version", nil)
  885. if err != nil {
  886. t.Fatal(err)
  887. }
  888. if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
  889. t.Fatal(err)
  890. }
  891. assertHttpNotError(r, t)
  892. if r.Code != http.StatusOK {
  893. t.Errorf("Expected response for OPTIONS request to be \"200\", %v found.", r.Code)
  894. }
  895. allowOrigin := r.Header().Get("Access-Control-Allow-Origin")
  896. allowHeaders := r.Header().Get("Access-Control-Allow-Headers")
  897. allowMethods := r.Header().Get("Access-Control-Allow-Methods")
  898. if allowOrigin != "*" {
  899. t.Errorf("Expected header Access-Control-Allow-Origin to be \"*\", %s found.", allowOrigin)
  900. }
  901. if allowHeaders != "Origin, X-Requested-With, Content-Type, Accept" {
  902. t.Errorf("Expected header Access-Control-Allow-Headers to be \"Origin, X-Requested-With, Content-Type, Accept\", %s found.", allowHeaders)
  903. }
  904. if allowMethods != "GET, POST, DELETE, PUT, OPTIONS" {
  905. t.Errorf("Expected hearder Access-Control-Allow-Methods to be \"GET, POST, DELETE, PUT, OPTIONS\", %s found.", allowMethods)
  906. }
  907. }
  908. func TestDeleteImages(t *testing.T) {
  909. eng := NewTestEngine(t)
  910. defer mkRuntimeFromEngine(eng, t).Nuke()
  911. srv := mkServerFromEngine(eng, t)
  912. initialImages, err := srv.Images(false, "")
  913. if err != nil {
  914. t.Fatal(err)
  915. }
  916. if err := srv.ContainerTag(unitTestImageName, "test", "test", false); err != nil {
  917. t.Fatal(err)
  918. }
  919. images, err := srv.Images(false, "")
  920. if err != nil {
  921. t.Fatal(err)
  922. }
  923. if len(images[0].RepoTags) != len(initialImages[0].RepoTags)+1 {
  924. t.Errorf("Expected %d images, %d found", len(initialImages)+1, len(images))
  925. }
  926. req, err := http.NewRequest("DELETE", "/images/"+unitTestImageID, nil)
  927. if err != nil {
  928. t.Fatal(err)
  929. }
  930. r := httptest.NewRecorder()
  931. if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
  932. t.Fatal(err)
  933. }
  934. if r.Code != http.StatusConflict {
  935. t.Fatalf("Expected http status 409-conflict, got %v", r.Code)
  936. }
  937. req2, err := http.NewRequest("DELETE", "/images/test:test", nil)
  938. if err != nil {
  939. t.Fatal(err)
  940. }
  941. r2 := httptest.NewRecorder()
  942. if err := docker.ServeRequest(srv, docker.APIVERSION, r2, req2); err != nil {
  943. t.Fatal(err)
  944. }
  945. assertHttpNotError(r2, t)
  946. if r2.Code != http.StatusOK {
  947. t.Fatalf("%d OK expected, received %d\n", http.StatusOK, r.Code)
  948. }
  949. var outs []docker.APIRmi
  950. if err := json.Unmarshal(r2.Body.Bytes(), &outs); err != nil {
  951. t.Fatal(err)
  952. }
  953. if len(outs) != 1 {
  954. t.Fatalf("Expected %d event (untagged), got %d", 1, len(outs))
  955. }
  956. images, err = srv.Images(false, "")
  957. if err != nil {
  958. t.Fatal(err)
  959. }
  960. if len(images[0].RepoTags) != len(initialImages[0].RepoTags) {
  961. t.Errorf("Expected %d image, %d found", len(initialImages), len(images))
  962. }
  963. }
  964. func TestPostContainersCopy(t *testing.T) {
  965. eng := NewTestEngine(t)
  966. defer mkRuntimeFromEngine(eng, t).Nuke()
  967. srv := mkServerFromEngine(eng, t)
  968. // Create a container and remove a file
  969. containerID := createTestContainer(eng,
  970. &docker.Config{
  971. Image: unitTestImageID,
  972. Cmd: []string{"touch", "/test.txt"},
  973. },
  974. t,
  975. )
  976. containerRun(eng, containerID, t)
  977. r := httptest.NewRecorder()
  978. copyData := docker.APICopy{HostPath: ".", Resource: "/test.txt"}
  979. jsonData, err := json.Marshal(copyData)
  980. if err != nil {
  981. t.Fatal(err)
  982. }
  983. req, err := http.NewRequest("POST", "/containers/"+containerID+"/copy", bytes.NewReader(jsonData))
  984. if err != nil {
  985. t.Fatal(err)
  986. }
  987. req.Header.Add("Content-Type", "application/json")
  988. if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
  989. t.Fatal(err)
  990. }
  991. assertHttpNotError(r, t)
  992. if r.Code != http.StatusOK {
  993. t.Fatalf("%d OK expected, received %d\n", http.StatusOK, r.Code)
  994. }
  995. found := false
  996. for tarReader := tar.NewReader(r.Body); ; {
  997. h, err := tarReader.Next()
  998. if err != nil {
  999. if err == io.EOF {
  1000. break
  1001. }
  1002. t.Fatal(err)
  1003. }
  1004. if h.Name == "test.txt" {
  1005. found = true
  1006. break
  1007. }
  1008. }
  1009. if !found {
  1010. t.Fatalf("The created test file has not been found in the copied output")
  1011. }
  1012. }
  1013. // Mocked types for tests
  1014. type NopConn struct {
  1015. io.ReadCloser
  1016. io.Writer
  1017. }
  1018. func (c *NopConn) LocalAddr() net.Addr { return nil }
  1019. func (c *NopConn) RemoteAddr() net.Addr { return nil }
  1020. func (c *NopConn) SetDeadline(t time.Time) error { return nil }
  1021. func (c *NopConn) SetReadDeadline(t time.Time) error { return nil }
  1022. func (c *NopConn) SetWriteDeadline(t time.Time) error { return nil }
  1023. type hijackTester struct {
  1024. *httptest.ResponseRecorder
  1025. in io.ReadCloser
  1026. out io.Writer
  1027. }
  1028. func (t *hijackTester) Hijack() (net.Conn, *bufio.ReadWriter, error) {
  1029. bufrw := bufio.NewReadWriter(bufio.NewReader(t.in), bufio.NewWriter(t.out))
  1030. conn := &NopConn{
  1031. ReadCloser: t.in,
  1032. Writer: t.out,
  1033. }
  1034. return conn, bufrw, nil
  1035. }