api_test.go 34 KB

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