api.go 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838
  1. package docker
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "github.com/dotcloud/docker/auth"
  6. "github.com/dotcloud/docker/utils"
  7. "github.com/gorilla/mux"
  8. "io"
  9. "io/ioutil"
  10. "log"
  11. "net/http"
  12. "os"
  13. "os/exec"
  14. "path"
  15. "strconv"
  16. "strings"
  17. )
  18. const APIVERSION = 1.1
  19. func hijackServer(w http.ResponseWriter) (io.ReadCloser, io.Writer, error) {
  20. conn, _, err := w.(http.Hijacker).Hijack()
  21. if err != nil {
  22. return nil, nil, err
  23. }
  24. // Flush the options to make sure the client sets the raw mode
  25. conn.Write([]byte{})
  26. return conn, conn, nil
  27. }
  28. //If we don't do this, POST method without Content-type (even with empty body) will fail
  29. func parseForm(r *http.Request) error {
  30. if err := r.ParseForm(); err != nil && !strings.HasPrefix(err.Error(), "mime:") {
  31. return err
  32. }
  33. return nil
  34. }
  35. func parseMultipartForm(r *http.Request) error {
  36. if err := r.ParseMultipartForm(4096); err != nil && !strings.HasPrefix(err.Error(), "mime:") {
  37. return err
  38. }
  39. return nil
  40. }
  41. func httpError(w http.ResponseWriter, err error) {
  42. if strings.HasPrefix(err.Error(), "No such") {
  43. http.Error(w, err.Error(), http.StatusNotFound)
  44. } else if strings.HasPrefix(err.Error(), "Bad parameter") {
  45. http.Error(w, err.Error(), http.StatusBadRequest)
  46. } else if strings.HasPrefix(err.Error(), "Impossible") {
  47. http.Error(w, err.Error(), http.StatusNotAcceptable)
  48. } else {
  49. http.Error(w, err.Error(), http.StatusInternalServerError)
  50. }
  51. }
  52. func writeJSON(w http.ResponseWriter, b []byte) {
  53. w.Header().Set("Content-Type", "application/json")
  54. w.Write(b)
  55. }
  56. // FIXME: Use stvconv.ParseBool() instead?
  57. func getBoolParam(value string) (bool, error) {
  58. if value == "1" || strings.ToLower(value) == "true" {
  59. return true, nil
  60. }
  61. if value == "" || value == "0" || strings.ToLower(value) == "false" {
  62. return false, nil
  63. }
  64. return false, fmt.Errorf("Bad parameter")
  65. }
  66. func getAuth(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
  67. // FIXME: Handle multiple login at once
  68. // FIXME: return specific error code if config file missing?
  69. authConfig, err := auth.LoadConfig(srv.runtime.root)
  70. if err != nil {
  71. if err != auth.ErrConfigFileMissing {
  72. return err
  73. }
  74. authConfig = &auth.AuthConfig{}
  75. }
  76. b, err := json.Marshal(&auth.AuthConfig{Username: authConfig.Username, Email: authConfig.Email})
  77. if err != nil {
  78. return err
  79. }
  80. writeJSON(w, b)
  81. return nil
  82. }
  83. func postAuth(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
  84. // FIXME: Handle multiple login at once
  85. config := &auth.AuthConfig{}
  86. if err := json.NewDecoder(r.Body).Decode(config); err != nil {
  87. return err
  88. }
  89. authConfig, err := auth.LoadConfig(srv.runtime.root)
  90. if err != nil {
  91. if err != auth.ErrConfigFileMissing {
  92. return err
  93. }
  94. authConfig = &auth.AuthConfig{}
  95. }
  96. if config.Username == authConfig.Username {
  97. config.Password = authConfig.Password
  98. }
  99. newAuthConfig := auth.NewAuthConfig(config.Username, config.Password, config.Email, srv.runtime.root)
  100. status, err := auth.Login(newAuthConfig)
  101. if err != nil {
  102. return err
  103. }
  104. if status != "" {
  105. b, err := json.Marshal(&APIAuth{Status: status})
  106. if err != nil {
  107. return err
  108. }
  109. writeJSON(w, b)
  110. return nil
  111. }
  112. w.WriteHeader(http.StatusNoContent)
  113. return nil
  114. }
  115. func getVersion(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
  116. m := srv.DockerVersion()
  117. b, err := json.Marshal(m)
  118. if err != nil {
  119. return err
  120. }
  121. writeJSON(w, b)
  122. return nil
  123. }
  124. func postContainersKill(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
  125. if vars == nil {
  126. return fmt.Errorf("Missing parameter")
  127. }
  128. name := vars["name"]
  129. if err := srv.ContainerKill(name); err != nil {
  130. return err
  131. }
  132. w.WriteHeader(http.StatusNoContent)
  133. return nil
  134. }
  135. func getContainersExport(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
  136. if vars == nil {
  137. return fmt.Errorf("Missing parameter")
  138. }
  139. name := vars["name"]
  140. if err := srv.ContainerExport(name, w); err != nil {
  141. utils.Debugf("%s", err.Error())
  142. return err
  143. }
  144. return nil
  145. }
  146. func getImagesJSON(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
  147. if err := parseForm(r); err != nil {
  148. return err
  149. }
  150. all, err := getBoolParam(r.Form.Get("all"))
  151. if err != nil {
  152. return err
  153. }
  154. filter := r.Form.Get("filter")
  155. outs, err := srv.Images(all, filter)
  156. if err != nil {
  157. return err
  158. }
  159. b, err := json.Marshal(outs)
  160. if err != nil {
  161. return err
  162. }
  163. writeJSON(w, b)
  164. return nil
  165. }
  166. func getImagesViz(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
  167. if err := srv.ImagesViz(w); err != nil {
  168. return err
  169. }
  170. return nil
  171. }
  172. func getInfo(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
  173. out := srv.DockerInfo()
  174. b, err := json.Marshal(out)
  175. if err != nil {
  176. return err
  177. }
  178. writeJSON(w, b)
  179. return nil
  180. }
  181. func getImagesHistory(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
  182. if vars == nil {
  183. return fmt.Errorf("Missing parameter")
  184. }
  185. name := vars["name"]
  186. outs, err := srv.ImageHistory(name)
  187. if err != nil {
  188. return err
  189. }
  190. b, err := json.Marshal(outs)
  191. if err != nil {
  192. return err
  193. }
  194. writeJSON(w, b)
  195. return nil
  196. }
  197. func getContainersChanges(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
  198. if vars == nil {
  199. return fmt.Errorf("Missing parameter")
  200. }
  201. name := vars["name"]
  202. changesStr, err := srv.ContainerChanges(name)
  203. if err != nil {
  204. return err
  205. }
  206. b, err := json.Marshal(changesStr)
  207. if err != nil {
  208. return err
  209. }
  210. writeJSON(w, b)
  211. return nil
  212. }
  213. func getContainersJSON(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
  214. if err := parseForm(r); err != nil {
  215. return err
  216. }
  217. all, err := getBoolParam(r.Form.Get("all"))
  218. if err != nil {
  219. return err
  220. }
  221. since := r.Form.Get("since")
  222. before := r.Form.Get("before")
  223. n, err := strconv.Atoi(r.Form.Get("limit"))
  224. if err != nil {
  225. n = -1
  226. }
  227. outs := srv.Containers(all, n, since, before)
  228. b, err := json.Marshal(outs)
  229. if err != nil {
  230. return err
  231. }
  232. writeJSON(w, b)
  233. return nil
  234. }
  235. func postImagesTag(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
  236. if err := parseForm(r); err != nil {
  237. return err
  238. }
  239. repo := r.Form.Get("repo")
  240. tag := r.Form.Get("tag")
  241. if vars == nil {
  242. return fmt.Errorf("Missing parameter")
  243. }
  244. name := vars["name"]
  245. force, err := getBoolParam(r.Form.Get("force"))
  246. if err != nil {
  247. return err
  248. }
  249. if err := srv.ContainerTag(name, repo, tag, force); err != nil {
  250. return err
  251. }
  252. w.WriteHeader(http.StatusCreated)
  253. return nil
  254. }
  255. func postCommit(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
  256. if err := parseForm(r); err != nil {
  257. return err
  258. }
  259. config := &Config{}
  260. if err := json.NewDecoder(r.Body).Decode(config); err != nil {
  261. utils.Debugf("%s", err.Error())
  262. }
  263. repo := r.Form.Get("repo")
  264. tag := r.Form.Get("tag")
  265. container := r.Form.Get("container")
  266. author := r.Form.Get("author")
  267. comment := r.Form.Get("comment")
  268. id, err := srv.ContainerCommit(container, repo, tag, author, comment, config)
  269. if err != nil {
  270. return err
  271. }
  272. b, err := json.Marshal(&APIID{id})
  273. if err != nil {
  274. return err
  275. }
  276. w.WriteHeader(http.StatusCreated)
  277. writeJSON(w, b)
  278. return nil
  279. }
  280. // Creates an image from Pull or from Import
  281. func postImagesCreate(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
  282. if err := parseForm(r); err != nil {
  283. return err
  284. }
  285. src := r.Form.Get("fromSrc")
  286. image := r.Form.Get("fromImage")
  287. tag := r.Form.Get("tag")
  288. repo := r.Form.Get("repo")
  289. if version > 1.0 {
  290. w.Header().Set("Content-Type", "application/json")
  291. }
  292. sf := utils.NewStreamFormatter(version > 1.0)
  293. if image != "" { //pull
  294. registry := r.Form.Get("registry")
  295. if err := srv.ImagePull(image, tag, registry, w, sf); err != nil {
  296. if sf.Used() {
  297. w.Write(sf.FormatError(err))
  298. return nil
  299. }
  300. return err
  301. }
  302. } else { //import
  303. if err := srv.ImageImport(src, repo, tag, r.Body, w, sf); err != nil {
  304. if sf.Used() {
  305. w.Write(sf.FormatError(err))
  306. return nil
  307. }
  308. return err
  309. }
  310. }
  311. return nil
  312. }
  313. func getImagesSearch(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
  314. if err := parseForm(r); err != nil {
  315. return err
  316. }
  317. term := r.Form.Get("term")
  318. outs, err := srv.ImagesSearch(term)
  319. if err != nil {
  320. return err
  321. }
  322. b, err := json.Marshal(outs)
  323. if err != nil {
  324. return err
  325. }
  326. writeJSON(w, b)
  327. return nil
  328. }
  329. func postImagesInsert(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
  330. if err := parseForm(r); err != nil {
  331. return err
  332. }
  333. url := r.Form.Get("url")
  334. path := r.Form.Get("path")
  335. if vars == nil {
  336. return fmt.Errorf("Missing parameter")
  337. }
  338. name := vars["name"]
  339. if version > 1.0 {
  340. w.Header().Set("Content-Type", "application/json")
  341. }
  342. sf := utils.NewStreamFormatter(version > 1.0)
  343. imgID, err := srv.ImageInsert(name, url, path, w, sf)
  344. if err != nil {
  345. if sf.Used() {
  346. w.Write(sf.FormatError(err))
  347. return nil
  348. }
  349. }
  350. b, err := json.Marshal(&APIID{ID: imgID})
  351. if err != nil {
  352. return err
  353. }
  354. writeJSON(w, b)
  355. return nil
  356. }
  357. func postImagesPush(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
  358. if err := parseForm(r); err != nil {
  359. return err
  360. }
  361. registry := r.Form.Get("registry")
  362. if vars == nil {
  363. return fmt.Errorf("Missing parameter")
  364. }
  365. name := vars["name"]
  366. if version > 1.0 {
  367. w.Header().Set("Content-Type", "application/json")
  368. }
  369. sf := utils.NewStreamFormatter(version > 1.0)
  370. if err := srv.ImagePush(name, registry, w, sf); err != nil {
  371. if sf.Used() {
  372. w.Write(sf.FormatError(err))
  373. return nil
  374. }
  375. return err
  376. }
  377. return nil
  378. }
  379. func postContainersCreate(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
  380. config := &Config{}
  381. if err := json.NewDecoder(r.Body).Decode(config); err != nil {
  382. return err
  383. }
  384. id, err := srv.ContainerCreate(config)
  385. if err != nil {
  386. return err
  387. }
  388. out := &APIRun{
  389. ID: id,
  390. }
  391. if config.Memory > 0 && !srv.runtime.capabilities.MemoryLimit {
  392. log.Println("WARNING: Your kernel does not support memory limit capabilities. Limitation discarded.")
  393. out.Warnings = append(out.Warnings, "Your kernel does not support memory limit capabilities. Limitation discarded.")
  394. }
  395. if config.Memory > 0 && !srv.runtime.capabilities.SwapLimit {
  396. log.Println("WARNING: Your kernel does not support swap limit capabilities. Limitation discarded.")
  397. out.Warnings = append(out.Warnings, "Your kernel does not support memory swap capabilities. Limitation discarded.")
  398. }
  399. b, err := json.Marshal(out)
  400. if err != nil {
  401. return err
  402. }
  403. w.WriteHeader(http.StatusCreated)
  404. writeJSON(w, b)
  405. return nil
  406. }
  407. func postContainersRestart(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
  408. if err := parseForm(r); err != nil {
  409. return err
  410. }
  411. t, err := strconv.Atoi(r.Form.Get("t"))
  412. if err != nil || t < 0 {
  413. t = 10
  414. }
  415. if vars == nil {
  416. return fmt.Errorf("Missing parameter")
  417. }
  418. name := vars["name"]
  419. if err := srv.ContainerRestart(name, t); err != nil {
  420. return err
  421. }
  422. w.WriteHeader(http.StatusNoContent)
  423. return nil
  424. }
  425. func deleteContainers(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
  426. if err := parseForm(r); err != nil {
  427. return err
  428. }
  429. if vars == nil {
  430. return fmt.Errorf("Missing parameter")
  431. }
  432. name := vars["name"]
  433. removeVolume, err := getBoolParam(r.Form.Get("v"))
  434. if err != nil {
  435. return err
  436. }
  437. if err := srv.ContainerDestroy(name, removeVolume); err != nil {
  438. return err
  439. }
  440. w.WriteHeader(http.StatusNoContent)
  441. return nil
  442. }
  443. func deleteImages(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
  444. if vars == nil {
  445. return fmt.Errorf("Missing parameter")
  446. }
  447. name := vars["name"]
  448. if err := srv.ImageDelete(name); err != nil {
  449. return err
  450. }
  451. w.WriteHeader(http.StatusNoContent)
  452. return nil
  453. }
  454. func postContainersStart(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
  455. if vars == nil {
  456. return fmt.Errorf("Missing parameter")
  457. }
  458. name := vars["name"]
  459. if err := srv.ContainerStart(name); err != nil {
  460. return err
  461. }
  462. w.WriteHeader(http.StatusNoContent)
  463. return nil
  464. }
  465. func postContainersStop(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
  466. if err := parseForm(r); err != nil {
  467. return err
  468. }
  469. t, err := strconv.Atoi(r.Form.Get("t"))
  470. if err != nil || t < 0 {
  471. t = 10
  472. }
  473. if vars == nil {
  474. return fmt.Errorf("Missing parameter")
  475. }
  476. name := vars["name"]
  477. if err := srv.ContainerStop(name, t); err != nil {
  478. return err
  479. }
  480. w.WriteHeader(http.StatusNoContent)
  481. return nil
  482. }
  483. func postContainersWait(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
  484. if vars == nil {
  485. return fmt.Errorf("Missing parameter")
  486. }
  487. name := vars["name"]
  488. status, err := srv.ContainerWait(name)
  489. if err != nil {
  490. return err
  491. }
  492. b, err := json.Marshal(&APIWait{StatusCode: status})
  493. if err != nil {
  494. return err
  495. }
  496. writeJSON(w, b)
  497. return nil
  498. }
  499. func postContainersResize(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
  500. if err := parseForm(r); err != nil {
  501. return err
  502. }
  503. height, err := strconv.Atoi(r.Form.Get("h"))
  504. if err != nil {
  505. return err
  506. }
  507. width, err := strconv.Atoi(r.Form.Get("w"))
  508. if err != nil {
  509. return err
  510. }
  511. if vars == nil {
  512. return fmt.Errorf("Missing parameter")
  513. }
  514. name := vars["name"]
  515. if err := srv.ContainerResize(name, height, width); err != nil {
  516. return err
  517. }
  518. return nil
  519. }
  520. func postContainersAttach(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
  521. if err := parseForm(r); err != nil {
  522. return err
  523. }
  524. logs, err := getBoolParam(r.Form.Get("logs"))
  525. if err != nil {
  526. return err
  527. }
  528. stream, err := getBoolParam(r.Form.Get("stream"))
  529. if err != nil {
  530. return err
  531. }
  532. stdin, err := getBoolParam(r.Form.Get("stdin"))
  533. if err != nil {
  534. return err
  535. }
  536. stdout, err := getBoolParam(r.Form.Get("stdout"))
  537. if err != nil {
  538. return err
  539. }
  540. stderr, err := getBoolParam(r.Form.Get("stderr"))
  541. if err != nil {
  542. return err
  543. }
  544. if vars == nil {
  545. return fmt.Errorf("Missing parameter")
  546. }
  547. name := vars["name"]
  548. if _, err := srv.ContainerInspect(name); err != nil {
  549. return err
  550. }
  551. in, out, err := hijackServer(w)
  552. if err != nil {
  553. return err
  554. }
  555. defer in.Close()
  556. fmt.Fprintf(out, "HTTP/1.1 200 OK\r\nContent-Type: application/vnd.docker.raw-stream\r\n\r\n")
  557. if err := srv.ContainerAttach(name, logs, stream, stdin, stdout, stderr, in, out); err != nil {
  558. fmt.Fprintf(out, "Error: %s\n", err)
  559. }
  560. return nil
  561. }
  562. func getContainersByName(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
  563. if vars == nil {
  564. return fmt.Errorf("Missing parameter")
  565. }
  566. name := vars["name"]
  567. container, err := srv.ContainerInspect(name)
  568. if err != nil {
  569. return err
  570. }
  571. b, err := json.Marshal(container)
  572. if err != nil {
  573. return err
  574. }
  575. writeJSON(w, b)
  576. return nil
  577. }
  578. func getImagesByName(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
  579. if vars == nil {
  580. return fmt.Errorf("Missing parameter")
  581. }
  582. name := vars["name"]
  583. image, err := srv.ImageInspect(name)
  584. if err != nil {
  585. return err
  586. }
  587. b, err := json.Marshal(image)
  588. if err != nil {
  589. return err
  590. }
  591. writeJSON(w, b)
  592. return nil
  593. }
  594. func postImagesGetCache(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
  595. apiConfig := &APIImageConfig{}
  596. if err := json.NewDecoder(r.Body).Decode(apiConfig); err != nil {
  597. return err
  598. }
  599. image, err := srv.ImageGetCached(apiConfig.ID, apiConfig.Config)
  600. if err != nil {
  601. return err
  602. }
  603. if image == nil {
  604. w.WriteHeader(http.StatusNotFound)
  605. return nil
  606. }
  607. apiID := &APIID{ID: image.ID}
  608. b, err := json.Marshal(apiID)
  609. if err != nil {
  610. return err
  611. }
  612. writeJSON(w, b)
  613. return nil
  614. }
  615. func postBuild(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
  616. if err := r.ParseMultipartForm(4096); err != nil {
  617. return err
  618. }
  619. remoteURL := r.FormValue("remote")
  620. repoName := r.FormValue("t")
  621. tag := ""
  622. if strings.Contains(repoName, ":") {
  623. remoteParts := strings.Split(repoName, ":")
  624. tag = remoteParts[1]
  625. repoName = remoteParts[0]
  626. }
  627. var dockerfile, context io.Reader
  628. if remoteURL == "" {
  629. d, _, err := r.FormFile("Dockerfile")
  630. if err != nil {
  631. return err
  632. } else {
  633. dockerfile = d
  634. }
  635. c, _, err := r.FormFile("Context")
  636. if err != nil {
  637. if err != http.ErrMissingFile {
  638. return err
  639. }
  640. } else {
  641. context = c
  642. }
  643. } else {
  644. if utils.IsGIT(remoteURL) {
  645. if !strings.HasPrefix(remoteURL, "git://") {
  646. remoteURL = "https://" + remoteURL
  647. }
  648. root, err := ioutil.TempDir("", "docker-build-git")
  649. if err != nil {
  650. return err
  651. }
  652. defer os.RemoveAll(root)
  653. if output, err := exec.Command("git", "clone", remoteURL, root).CombinedOutput(); err != nil {
  654. return fmt.Errorf("Error trying to use git: %s (%s)", err, output)
  655. }
  656. d, err := os.Open(path.Join(root, "Dockerfile"))
  657. if err != nil {
  658. if os.IsNotExist(err) {
  659. return fmt.Errorf("No Dockerfile found in the repository")
  660. }
  661. return err
  662. } else {
  663. dockerfile = d
  664. }
  665. c, err := Tar(root, Bzip2)
  666. if err != nil {
  667. return err
  668. } else {
  669. context = c
  670. }
  671. } else if utils.IsURL(remoteURL) {
  672. f, err := utils.Download(remoteURL, ioutil.Discard)
  673. if err != nil {
  674. return err
  675. } else {
  676. dockerfile = f.Body
  677. }
  678. defer f.Body.Close()
  679. }
  680. }
  681. b := NewBuildFile(srv, utils.NewWriteFlusher(w))
  682. if id, err := b.Build(dockerfile, context); err != nil {
  683. fmt.Fprintf(w, "Error build: %s\n", err)
  684. } else if repoName != "" {
  685. srv.runtime.repositories.Set(repoName, tag, id, false)
  686. }
  687. return nil
  688. }
  689. func ListenAndServe(addr string, srv *Server, logging bool) error {
  690. r := mux.NewRouter()
  691. log.Printf("Listening for HTTP on %s\n", addr)
  692. m := map[string]map[string]func(*Server, float64, http.ResponseWriter, *http.Request, map[string]string) error{
  693. "GET": {
  694. "/auth": getAuth,
  695. "/version": getVersion,
  696. "/info": getInfo,
  697. "/images/json": getImagesJSON,
  698. "/images/viz": getImagesViz,
  699. "/images/search": getImagesSearch,
  700. "/images/{name:.*}/history": getImagesHistory,
  701. "/images/{name:.*}/json": getImagesByName,
  702. "/containers/ps": getContainersJSON,
  703. "/containers/json": getContainersJSON,
  704. "/containers/{name:.*}/export": getContainersExport,
  705. "/containers/{name:.*}/changes": getContainersChanges,
  706. "/containers/{name:.*}/json": getContainersByName,
  707. },
  708. "POST": {
  709. "/auth": postAuth,
  710. "/commit": postCommit,
  711. "/build": postBuild,
  712. "/images/create": postImagesCreate,
  713. "/images/{name:.*}/insert": postImagesInsert,
  714. "/images/{name:.*}/push": postImagesPush,
  715. "/images/{name:.*}/tag": postImagesTag,
  716. "/images/getCache": postImagesGetCache,
  717. "/containers/create": postContainersCreate,
  718. "/containers/{name:.*}/kill": postContainersKill,
  719. "/containers/{name:.*}/restart": postContainersRestart,
  720. "/containers/{name:.*}/start": postContainersStart,
  721. "/containers/{name:.*}/stop": postContainersStop,
  722. "/containers/{name:.*}/wait": postContainersWait,
  723. "/containers/{name:.*}/resize": postContainersResize,
  724. "/containers/{name:.*}/attach": postContainersAttach,
  725. },
  726. "DELETE": {
  727. "/containers/{name:.*}": deleteContainers,
  728. "/images/{name:.*}": deleteImages,
  729. },
  730. }
  731. for method, routes := range m {
  732. for route, fct := range routes {
  733. utils.Debugf("Registering %s, %s", method, route)
  734. // NOTE: scope issue, make sure the variables are local and won't be changed
  735. localRoute := route
  736. localMethod := method
  737. localFct := fct
  738. f := func(w http.ResponseWriter, r *http.Request) {
  739. utils.Debugf("Calling %s %s", localMethod, localRoute)
  740. if logging {
  741. log.Println(r.Method, r.RequestURI)
  742. }
  743. if strings.Contains(r.Header.Get("User-Agent"), "Docker-Client/") {
  744. userAgent := strings.Split(r.Header.Get("User-Agent"), "/")
  745. if len(userAgent) == 2 && userAgent[1] != VERSION {
  746. utils.Debugf("Warning: client and server don't have the same version (client: %s, server: %s)", userAgent[1], VERSION)
  747. }
  748. }
  749. version, err := strconv.ParseFloat(mux.Vars(r)["version"], 64)
  750. if err != nil {
  751. version = APIVERSION
  752. }
  753. if version == 0 || version > APIVERSION {
  754. w.WriteHeader(http.StatusNotFound)
  755. return
  756. }
  757. if err := localFct(srv, version, w, r, mux.Vars(r)); err != nil {
  758. httpError(w, err)
  759. }
  760. }
  761. r.Path("/v{version:[0-9.]+}" + localRoute).Methods(localMethod).HandlerFunc(f)
  762. r.Path(localRoute).Methods(localMethod).HandlerFunc(f)
  763. }
  764. }
  765. return http.ListenAndServe(addr, r)
  766. }