🌐 AI搜索 & 代理 主页
blob: e870ca7723c6dd7226e6a0f82b5e0cb9b7e3d428 [file] [log] [blame]
Solomon Hykesa11b3132013-04-11 02:48:211package docker
2
3import (
Victor Vieuxc0d5d592013-04-18 01:13:434 "encoding/json"
Victor Vieuxb2952392013-04-19 13:24:375 "fmt"
Victor Vieuxf37399d2013-05-06 11:34:316 "github.com/dotcloud/docker/auth"
Guillaume J. Charmes2e69e172013-05-14 22:37:357 "github.com/dotcloud/docker/utils"
Solomon Hykesa11b3132013-04-11 02:48:218 "github.com/gorilla/mux"
Guillaume J. Charmes57cfe722013-05-08 01:06:499 "io"
Victor Vieux79e91052013-04-18 16:56:2210 "log"
Solomon Hykesa11b3132013-04-11 02:48:2111 "net/http"
Victor Vieux1aa7f132013-04-22 16:17:4712 "strconv"
Victor Vieuxb2952392013-04-19 13:24:3713 "strings"
Solomon Hykesa11b3132013-04-11 02:48:2114)
15
Victor Vieuxc9062392013-06-05 10:23:4516const APIVERSION = 1.2
Victor Vieuxfaae7222013-05-22 15:29:5417
Guillaume J. Charmes57cfe722013-05-08 01:06:4918func hijackServer(w http.ResponseWriter) (io.ReadCloser, io.Writer, error) {
19 conn, _, err := w.(http.Hijacker).Hijack()
Victor Vieux04cd20f2013-05-06 09:31:2220 if err != nil {
21 return nil, nil, err
22 }
Victor Vieux04cd20f2013-05-06 09:31:2223 // Flush the options to make sure the client sets the raw mode
Guillaume J. Charmes57cfe722013-05-08 01:06:4924 conn.Write([]byte{})
25 return conn, conn, nil
Victor Vieux04cd20f2013-05-06 09:31:2226}
27
Victor Vieux954ecac2013-05-08 16:52:0128//If we don't do this, POST method without Content-type (even with empty body) will fail
29func 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
Guillaume J. Charmes0f135ad2013-05-23 03:07:2636func parseMultipartForm(r *http.Request) error {
37 if err := r.ParseMultipartForm(4096); err != nil && !strings.HasPrefix(err.Error(), "mime:") {
38 return err
39 }
40 return nil
41}
42
Victor Vieux04cd20f2013-05-06 09:31:2243func httpError(w http.ResponseWriter, err error) {
44 if strings.HasPrefix(err.Error(), "No such") {
45 http.Error(w, err.Error(), http.StatusNotFound)
Victor Vieux0c544352013-05-16 13:45:2946 } else if strings.HasPrefix(err.Error(), "Bad parameter") {
47 http.Error(w, err.Error(), http.StatusBadRequest)
Victor Vieux67b20f22013-05-20 18:31:4548 } else if strings.HasPrefix(err.Error(), "Conflict") {
49 http.Error(w, err.Error(), http.StatusConflict)
Victor Vieux468e4c42013-05-31 15:34:2350 } else if strings.HasPrefix(err.Error(), "Impossible") {
51 http.Error(w, err.Error(), http.StatusNotAcceptable)
Victor Vieux04cd20f2013-05-06 09:31:2252 } else {
53 http.Error(w, err.Error(), http.StatusInternalServerError)
54 }
55}
56
Victor Vieuxfd224ee2013-06-04 18:00:2257func writeJSON(w http.ResponseWriter, b []byte) {
Victor Vieuxf7beba32013-05-10 19:11:5958 w.Header().Set("Content-Type", "application/json")
59 w.Write(b)
60}
61
Guillaume J. Charmes70d21232013-05-24 02:33:2862// FIXME: Use stvconv.ParseBool() instead?
Victor Vieux0c544352013-05-16 13:45:2963func getBoolParam(value string) (bool, error) {
64 if value == "1" || strings.ToLower(value) == "true" {
65 return true, nil
66 }
67 if value == "" || value == "0" || strings.ToLower(value) == "false" {
68 return false, nil
69 }
70 return false, fmt.Errorf("Bad parameter")
71}
72
Victor Vieux3dd1e4d2013-06-03 12:09:1673func getAuth(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
74 if version > 1.1 {
75 w.WriteHeader(http.StatusNotFound)
76 return nil
Guillaume J. Charmesb56b2da2013-05-07 23:33:1277 }
Victor Vieux3dd1e4d2013-06-03 12:09:1678 authConfig, err := auth.LoadConfig(srv.runtime.root)
79 if err != nil {
80 if err != auth.ErrConfigFileMissing {
81 return err
82 }
83 authConfig = &auth.AuthConfig{}
84 }
85 b, err := json.Marshal(&auth.AuthConfig{Username: authConfig.Username, Email: authConfig.Email})
Guillaume J. Charmesb56b2da2013-05-07 23:33:1286 if err != nil {
Victor Vieux7cc08232013-05-10 18:20:4987 return err
Guillaume J. Charmesb56b2da2013-05-07 23:33:1288 }
Victor Vieuxfd224ee2013-06-04 18:00:2289 writeJSON(w, b)
Victor Vieux3dd1e4d2013-06-03 12:09:1690 return nil
91}
92
93func postAuth(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
94 authConfig := &auth.AuthConfig{}
95 err := json.NewDecoder(r.Body).Decode(authConfig)
96 if err != nil {
97 return err
98 }
99 status := ""
100 if version > 1.1 {
101 status, err = auth.Login(authConfig, false)
102 if err != nil {
103 return err
104 }
105 } else {
106 localAuthConfig, err := auth.LoadConfig(srv.runtime.root)
107 if err != nil {
108 if err != auth.ErrConfigFileMissing {
109 return err
110 }
111 }
112 if authConfig.Username == localAuthConfig.Username {
113 authConfig.Password = localAuthConfig.Password
114 }
115
116 newAuthConfig := auth.NewAuthConfig(authConfig.Username, authConfig.Password, authConfig.Email, srv.runtime.root)
117 status, err = auth.Login(newAuthConfig, true)
118 if err != nil {
119 return err
120 }
121 }
Guillaume J. Charmesb56b2da2013-05-07 23:33:12122 if status != "" {
Victor Vieuxfd224ee2013-06-04 18:00:22123 b, err := json.Marshal(&APIAuth{Status: status})
Guillaume J. Charmesb56b2da2013-05-07 23:33:12124 if err != nil {
Victor Vieux7cc08232013-05-10 18:20:49125 return err
Guillaume J. Charmesb56b2da2013-05-07 23:33:12126 }
Victor Vieuxfd224ee2013-06-04 18:00:22127 writeJSON(w, b)
Victor Vieux7cc08232013-05-10 18:20:49128 return nil
Guillaume J. Charmesb56b2da2013-05-07 23:33:12129 }
Victor Vieux08621832013-05-09 19:42:29130 w.WriteHeader(http.StatusNoContent)
Victor Vieux7cc08232013-05-10 18:20:49131 return nil
Guillaume J. Charmesb56b2da2013-05-07 23:33:12132}
133
Victor Vieuxfaae7222013-05-22 15:29:54134func getVersion(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
Guillaume J. Charmesb56b2da2013-05-07 23:33:12135 m := srv.DockerVersion()
136 b, err := json.Marshal(m)
137 if err != nil {
Victor Vieux7cc08232013-05-10 18:20:49138 return err
Guillaume J. Charmesb56b2da2013-05-07 23:33:12139 }
Victor Vieuxfd224ee2013-06-04 18:00:22140 writeJSON(w, b)
Victor Vieux7cc08232013-05-10 18:20:49141 return nil
Guillaume J. Charmesb56b2da2013-05-07 23:33:12142}
143
Victor Vieuxfaae7222013-05-22 15:29:54144func postContainersKill(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
Guillaume J. Charmesff67da92013-05-09 23:28:47145 if vars == nil {
Victor Vieux7cc08232013-05-10 18:20:49146 return fmt.Errorf("Missing parameter")
Guillaume J. Charmesff67da92013-05-09 23:28:47147 }
Guillaume J. Charmesb56b2da2013-05-07 23:33:12148 name := vars["name"]
149 if err := srv.ContainerKill(name); err != nil {
Victor Vieux7cc08232013-05-10 18:20:49150 return err
Guillaume J. Charmesb56b2da2013-05-07 23:33:12151 }
Victor Vieux08621832013-05-09 19:42:29152 w.WriteHeader(http.StatusNoContent)
Victor Vieux7cc08232013-05-10 18:20:49153 return nil
Guillaume J. Charmesb56b2da2013-05-07 23:33:12154}
155
Victor Vieuxfaae7222013-05-22 15:29:54156func getContainersExport(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
Guillaume J. Charmesff67da92013-05-09 23:28:47157 if vars == nil {
Victor Vieux7cc08232013-05-10 18:20:49158 return fmt.Errorf("Missing parameter")
Guillaume J. Charmesff67da92013-05-09 23:28:47159 }
Guillaume J. Charmesb56b2da2013-05-07 23:33:12160 name := vars["name"]
161
Victor Vieux93dc2c32013-05-09 21:28:03162 if err := srv.ContainerExport(name, w); err != nil {
Guillaume J. Charmes2e69e172013-05-14 22:37:35163 utils.Debugf("%s", err.Error())
Victor Vieux8b31d302013-05-13 09:38:13164 return err
Guillaume J. Charmesb56b2da2013-05-07 23:33:12165 }
Victor Vieux7cc08232013-05-10 18:20:49166 return nil
Guillaume J. Charmesb56b2da2013-05-07 23:33:12167}
168
Victor Vieuxfd224ee2013-06-04 18:00:22169func getImagesJSON(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
Victor Vieux954ecac2013-05-08 16:52:01170 if err := parseForm(r); err != nil {
Victor Vieux7cc08232013-05-10 18:20:49171 return err
Guillaume J. Charmesb56b2da2013-05-07 23:33:12172 }
173
Victor Vieux0c544352013-05-16 13:45:29174 all, err := getBoolParam(r.Form.Get("all"))
175 if err != nil {
176 return err
177 }
Victor Vieuxc423a792013-05-09 21:52:12178 filter := r.Form.Get("filter")
Victor Vieux0ecf5e22013-05-09 21:10:26179
Victor Vieux1990c492013-05-13 10:18:55180 outs, err := srv.Images(all, filter)
Victor Vieuxc423a792013-05-09 21:52:12181 if err != nil {
Victor Vieux7cc08232013-05-10 18:20:49182 return err
Guillaume J. Charmesb56b2da2013-05-07 23:33:12183 }
Victor Vieuxc423a792013-05-09 21:52:12184 b, err := json.Marshal(outs)
185 if err != nil {
Victor Vieux7cc08232013-05-10 18:20:49186 return err
Victor Vieuxc423a792013-05-09 21:52:12187 }
Victor Vieuxfd224ee2013-06-04 18:00:22188 writeJSON(w, b)
Victor Vieux7cc08232013-05-10 18:20:49189 return nil
Victor Vieuxc423a792013-05-09 21:52:12190}
191
Victor Vieuxfaae7222013-05-22 15:29:54192func getImagesViz(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
Victor Vieuxc423a792013-05-09 21:52:12193 if err := srv.ImagesViz(w); err != nil {
Victor Vieux7cc08232013-05-10 18:20:49194 return err
Victor Vieuxc423a792013-05-09 21:52:12195 }
Victor Vieux7cc08232013-05-10 18:20:49196 return nil
Guillaume J. Charmesb56b2da2013-05-07 23:33:12197}
198
Victor Vieuxfaae7222013-05-22 15:29:54199func getInfo(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
Guillaume J. Charmesb56b2da2013-05-07 23:33:12200 out := srv.DockerInfo()
201 b, err := json.Marshal(out)
202 if err != nil {
Victor Vieux7cc08232013-05-10 18:20:49203 return err
Guillaume J. Charmesb56b2da2013-05-07 23:33:12204 }
Victor Vieuxfd224ee2013-06-04 18:00:22205 writeJSON(w, b)
Victor Vieux7cc08232013-05-10 18:20:49206 return nil
Guillaume J. Charmesb56b2da2013-05-07 23:33:12207}
208
Victor Vieuxfaae7222013-05-22 15:29:54209func getImagesHistory(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
Guillaume J. Charmesff67da92013-05-09 23:28:47210 if vars == nil {
Victor Vieux7cc08232013-05-10 18:20:49211 return fmt.Errorf("Missing parameter")
Guillaume J. Charmesff67da92013-05-09 23:28:47212 }
Guillaume J. Charmesb56b2da2013-05-07 23:33:12213 name := vars["name"]
214 outs, err := srv.ImageHistory(name)
215 if err != nil {
Victor Vieux7cc08232013-05-10 18:20:49216 return err
Guillaume J. Charmesb56b2da2013-05-07 23:33:12217 }
218 b, err := json.Marshal(outs)
219 if err != nil {
Victor Vieux7cc08232013-05-10 18:20:49220 return err
Guillaume J. Charmesb56b2da2013-05-07 23:33:12221 }
Victor Vieuxfd224ee2013-06-04 18:00:22222 writeJSON(w, b)
Victor Vieux7cc08232013-05-10 18:20:49223 return nil
Guillaume J. Charmesb56b2da2013-05-07 23:33:12224}
225
Victor Vieuxfaae7222013-05-22 15:29:54226func getContainersChanges(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
Guillaume J. Charmesff67da92013-05-09 23:28:47227 if vars == nil {
Victor Vieux7cc08232013-05-10 18:20:49228 return fmt.Errorf("Missing parameter")
Guillaume J. Charmesff67da92013-05-09 23:28:47229 }
Guillaume J. Charmesb56b2da2013-05-07 23:33:12230 name := vars["name"]
231 changesStr, err := srv.ContainerChanges(name)
232 if err != nil {
Victor Vieux7cc08232013-05-10 18:20:49233 return err
Guillaume J. Charmesb56b2da2013-05-07 23:33:12234 }
235 b, err := json.Marshal(changesStr)
236 if err != nil {
Victor Vieux7cc08232013-05-10 18:20:49237 return err
Guillaume J. Charmesb56b2da2013-05-07 23:33:12238 }
Victor Vieuxfd224ee2013-06-04 18:00:22239 writeJSON(w, b)
Victor Vieux7cc08232013-05-10 18:20:49240 return nil
Guillaume J. Charmesb56b2da2013-05-07 23:33:12241}
242
Victor Vieuxfd224ee2013-06-04 18:00:22243func getContainersJSON(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
Victor Vieux954ecac2013-05-08 16:52:01244 if err := parseForm(r); err != nil {
Victor Vieux7cc08232013-05-10 18:20:49245 return err
Guillaume J. Charmesb56b2da2013-05-07 23:33:12246 }
Victor Vieux0c544352013-05-16 13:45:29247 all, err := getBoolParam(r.Form.Get("all"))
248 if err != nil {
249 return err
250 }
Victor Vieuxbc3fa502013-05-08 16:28:11251 since := r.Form.Get("since")
252 before := r.Form.Get("before")
Victor Vieux60ddcaa2013-05-08 15:35:50253 n, err := strconv.Atoi(r.Form.Get("limit"))
Guillaume J. Charmesb56b2da2013-05-07 23:33:12254 if err != nil {
255 n = -1
256 }
257
Victor Vieux1990c492013-05-13 10:18:55258 outs := srv.Containers(all, n, since, before)
Guillaume J. Charmesb56b2da2013-05-07 23:33:12259 b, err := json.Marshal(outs)
260 if err != nil {
Victor Vieux7cc08232013-05-10 18:20:49261 return err
Guillaume J. Charmesb56b2da2013-05-07 23:33:12262 }
Victor Vieuxfd224ee2013-06-04 18:00:22263 writeJSON(w, b)
Victor Vieux7cc08232013-05-10 18:20:49264 return nil
Guillaume J. Charmesb56b2da2013-05-07 23:33:12265}
266
Victor Vieuxfaae7222013-05-22 15:29:54267func postImagesTag(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
Victor Vieux954ecac2013-05-08 16:52:01268 if err := parseForm(r); err != nil {
Victor Vieux7cc08232013-05-10 18:20:49269 return err
Guillaume J. Charmesb56b2da2013-05-07 23:33:12270 }
271 repo := r.Form.Get("repo")
272 tag := r.Form.Get("tag")
Guillaume J. Charmesff67da92013-05-09 23:28:47273 if vars == nil {
Victor Vieux7cc08232013-05-10 18:20:49274 return fmt.Errorf("Missing parameter")
Guillaume J. Charmesff67da92013-05-09 23:28:47275 }
Guillaume J. Charmesb56b2da2013-05-07 23:33:12276 name := vars["name"]
Victor Vieux0c544352013-05-16 13:45:29277 force, err := getBoolParam(r.Form.Get("force"))
278 if err != nil {
279 return err
280 }
Guillaume J. Charmesb56b2da2013-05-07 23:33:12281
282 if err := srv.ContainerTag(name, repo, tag, force); err != nil {
Victor Vieux7cc08232013-05-10 18:20:49283 return err
Guillaume J. Charmesb56b2da2013-05-07 23:33:12284 }
285 w.WriteHeader(http.StatusCreated)
Victor Vieux7cc08232013-05-10 18:20:49286 return nil
Guillaume J. Charmesb56b2da2013-05-07 23:33:12287}
288
Victor Vieuxfaae7222013-05-22 15:29:54289func postCommit(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
Victor Vieux954ecac2013-05-08 16:52:01290 if err := parseForm(r); err != nil {
Victor Vieux7cc08232013-05-10 18:20:49291 return err
Guillaume J. Charmesb56b2da2013-05-07 23:33:12292 }
Guillaume J. Charmes5bec9272013-05-10 19:28:07293 config := &Config{}
294 if err := json.NewDecoder(r.Body).Decode(config); err != nil {
Guillaume J. Charmes2e69e172013-05-14 22:37:35295 utils.Debugf("%s", err.Error())
Guillaume J. Charmesb56b2da2013-05-07 23:33:12296 }
297 repo := r.Form.Get("repo")
298 tag := r.Form.Get("tag")
299 container := r.Form.Get("container")
300 author := r.Form.Get("author")
301 comment := r.Form.Get("comment")
Guillaume J. Charmes5bec9272013-05-10 19:28:07302 id, err := srv.ContainerCommit(container, repo, tag, author, comment, config)
Guillaume J. Charmesb56b2da2013-05-07 23:33:12303 if err != nil {
Victor Vieux7cc08232013-05-10 18:20:49304 return err
Guillaume J. Charmesb56b2da2013-05-07 23:33:12305 }
Victor Vieuxfd224ee2013-06-04 18:00:22306 b, err := json.Marshal(&APIID{id})
Guillaume J. Charmesb56b2da2013-05-07 23:33:12307 if err != nil {
Victor Vieux7cc08232013-05-10 18:20:49308 return err
Guillaume J. Charmesb56b2da2013-05-07 23:33:12309 }
Victor Vieux08621832013-05-09 19:42:29310 w.WriteHeader(http.StatusCreated)
Victor Vieuxfd224ee2013-06-04 18:00:22311 writeJSON(w, b)
Victor Vieux7cc08232013-05-10 18:20:49312 return nil
Guillaume J. Charmesb56b2da2013-05-07 23:33:12313}
314
Guillaume J. Charmes152ebee2013-05-10 00:50:56315// Creates an image from Pull or from Import
Victor Vieuxfaae7222013-05-22 15:29:54316func postImagesCreate(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
Victor Vieux954ecac2013-05-08 16:52:01317 if err := parseForm(r); err != nil {
Victor Vieux7cc08232013-05-10 18:20:49318 return err
Guillaume J. Charmesb56b2da2013-05-07 23:33:12319 }
320
321 src := r.Form.Get("fromSrc")
322 image := r.Form.Get("fromImage")
Guillaume J. Charmesb56b2da2013-05-07 23:33:12323 tag := r.Form.Get("tag")
Guillaume J. Charmesf29e5dc2013-05-16 19:09:06324 repo := r.Form.Get("repo")
Guillaume J. Charmesb56b2da2013-05-07 23:33:12325
Victor Vieuxc8c70942013-05-25 15:09:46326 if version > 1.0 {
327 w.Header().Set("Content-Type", "application/json")
328 }
329 sf := utils.NewStreamFormatter(version > 1.0)
Guillaume J. Charmesb56b2da2013-05-07 23:33:12330 if image != "" { //pull
331 registry := r.Form.Get("registry")
Victor Vieux7e59b832013-06-03 17:51:52332 if err := srv.ImagePull(image, tag, registry, w, sf, &auth.AuthConfig{}); err != nil {
Victor Vieuxc8c70942013-05-25 15:09:46333 if sf.Used() {
Victor Vieux5a36efb2013-05-26 23:45:45334 w.Write(sf.FormatError(err))
Victor Vieuxc8c70942013-05-25 15:09:46335 return nil
336 }
Guillaume J. Charmesf29e5dc2013-05-16 19:09:06337 return err
Guillaume J. Charmesb56b2da2013-05-07 23:33:12338 }
339 } else { //import
Victor Vieuxc8c70942013-05-25 15:09:46340 if err := srv.ImageImport(src, repo, tag, r.Body, w, sf); err != nil {
341 if sf.Used() {
Victor Vieux5a36efb2013-05-26 23:45:45342 w.Write(sf.FormatError(err))
Victor Vieuxc8c70942013-05-25 15:09:46343 return nil
344 }
Guillaume J. Charmesf29e5dc2013-05-16 19:09:06345 return err
Guillaume J. Charmesb56b2da2013-05-07 23:33:12346 }
347 }
Victor Vieux7cc08232013-05-10 18:20:49348 return nil
Guillaume J. Charmesb56b2da2013-05-07 23:33:12349}
350
Victor Vieuxfaae7222013-05-22 15:29:54351func getImagesSearch(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
Victor Vieux954ecac2013-05-08 16:52:01352 if err := parseForm(r); err != nil {
Victor Vieux7cc08232013-05-10 18:20:49353 return err
Guillaume J. Charmesb56b2da2013-05-07 23:33:12354 }
355
356 term := r.Form.Get("term")
357 outs, err := srv.ImagesSearch(term)
358 if err != nil {
Victor Vieux7cc08232013-05-10 18:20:49359 return err
Guillaume J. Charmesb56b2da2013-05-07 23:33:12360 }
361 b, err := json.Marshal(outs)
362 if err != nil {
Victor Vieux7cc08232013-05-10 18:20:49363 return err
Guillaume J. Charmesb56b2da2013-05-07 23:33:12364 }
Victor Vieuxfd224ee2013-06-04 18:00:22365 writeJSON(w, b)
Victor Vieux7cc08232013-05-10 18:20:49366 return nil
Guillaume J. Charmesb56b2da2013-05-07 23:33:12367}
368
Victor Vieuxfaae7222013-05-22 15:29:54369func postImagesInsert(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
Victor Vieux954ecac2013-05-08 16:52:01370 if err := parseForm(r); err != nil {
Victor Vieux7cc08232013-05-10 18:20:49371 return err
Guillaume J. Charmesb56b2da2013-05-07 23:33:12372 }
373
374 url := r.Form.Get("url")
375 path := r.Form.Get("path")
Guillaume J. Charmesff67da92013-05-09 23:28:47376 if vars == nil {
Victor Vieux7cc08232013-05-10 18:20:49377 return fmt.Errorf("Missing parameter")
Guillaume J. Charmesff67da92013-05-09 23:28:47378 }
Guillaume J. Charmesb56b2da2013-05-07 23:33:12379 name := vars["name"]
Victor Vieuxc8c70942013-05-25 15:09:46380 if version > 1.0 {
381 w.Header().Set("Content-Type", "application/json")
382 }
383 sf := utils.NewStreamFormatter(version > 1.0)
Victor Vieuxfd224ee2013-06-04 18:00:22384 imgID, err := srv.ImageInsert(name, url, path, w, sf)
Guillaume J. Charmes0f135ad2013-05-23 03:07:26385 if err != nil {
Victor Vieuxc8c70942013-05-25 15:09:46386 if sf.Used() {
Victor Vieux5a36efb2013-05-26 23:45:45387 w.Write(sf.FormatError(err))
Victor Vieuxc8c70942013-05-25 15:09:46388 return nil
389 }
Guillaume J. Charmesb56b2da2013-05-07 23:33:12390 }
Victor Vieuxfd224ee2013-06-04 18:00:22391 b, err := json.Marshal(&APIID{ID: imgID})
Guillaume J. Charmes0f135ad2013-05-23 03:07:26392 if err != nil {
393 return err
394 }
Victor Vieuxfd224ee2013-06-04 18:00:22395 writeJSON(w, b)
Victor Vieux7cc08232013-05-10 18:20:49396 return nil
Guillaume J. Charmesb56b2da2013-05-07 23:33:12397}
398
Victor Vieuxfaae7222013-05-22 15:29:54399func postImagesPush(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
Victor Vieux49e65682013-05-30 15:39:43400 authConfig := &auth.AuthConfig{}
Victor Vieux3dd1e4d2013-06-03 12:09:16401 if version > 1.1 {
402 if err := json.NewDecoder(r.Body).Decode(authConfig); err != nil {
403 return err
404 }
405 } else {
406 localAuthConfig, err := auth.LoadConfig(srv.runtime.root)
407 if err != nil && err != auth.ErrConfigFileMissing {
408 return err
409 }
410 authConfig = localAuthConfig
Victor Vieux49e65682013-05-30 15:39:43411 }
Guillaume J. Charmes2f4de382013-05-15 19:21:37412 if err := parseForm(r); err != nil {
413 return err
414 }
415 registry := r.Form.Get("registry")
Guillaume J. Charmesb56b2da2013-05-07 23:33:12416
Guillaume J. Charmes2f4de382013-05-15 19:21:37417 if vars == nil {
418 return fmt.Errorf("Missing parameter")
419 }
420 name := vars["name"]
Victor Vieuxc8c70942013-05-25 15:09:46421 if version > 1.0 {
422 w.Header().Set("Content-Type", "application/json")
423 }
424 sf := utils.NewStreamFormatter(version > 1.0)
Victor Vieux62c78692013-06-03 11:06:13425 if err := srv.ImagePush(name, registry, w, sf, authConfig); err != nil {
Victor Vieuxc8c70942013-05-25 15:09:46426 if sf.Used() {
Victor Vieux5a36efb2013-05-26 23:45:45427 w.Write(sf.FormatError(err))
Victor Vieuxc8c70942013-05-25 15:09:46428 return nil
429 }
Guillaume J. Charmes2f4de382013-05-15 19:21:37430 return err
431 }
Victor Vieux7cc08232013-05-10 18:20:49432 return nil
Guillaume J. Charmesb56b2da2013-05-07 23:33:12433}
434
Victor Vieuxfaae7222013-05-22 15:29:54435func postContainersCreate(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
Guillaume J. Charmes152ebee2013-05-10 00:50:56436 config := &Config{}
Guillaume J. Charmesa3f60542013-06-06 18:01:09437 out := &APIRun{}
438
Guillaume J. Charmes152ebee2013-05-10 00:50:56439 if err := json.NewDecoder(r.Body).Decode(config); err != nil {
Victor Vieux7cc08232013-05-10 18:20:49440 return err
Guillaume J. Charmesb56b2da2013-05-07 23:33:12441 }
Guillaume J. Charmesa3f60542013-06-06 18:01:09442
443 if len(config.Dns) == 0 && len(srv.runtime.Dns) == 0 && utils.CheckLocalDns() {
Solomon Hykes7f118512013-06-14 21:46:08444 out.Warnings = append(out.Warnings, fmt.Sprintf("Docker detected local DNS server on resolv.conf. Using default external servers: %v", defaultDns))
Guillaume J. Charmesa3f60542013-06-06 18:01:09445 config.Dns = defaultDns
446 }
447
Guillaume J. Charmes152ebee2013-05-10 00:50:56448 id, err := srv.ContainerCreate(config)
Guillaume J. Charmesb56b2da2013-05-07 23:33:12449 if err != nil {
Victor Vieux7cc08232013-05-10 18:20:49450 return err
Guillaume J. Charmesb56b2da2013-05-07 23:33:12451 }
Guillaume J. Charmesa3f60542013-06-06 18:01:09452 out.ID = id
Guillaume J. Charmes152ebee2013-05-10 00:50:56453
Guillaume J. Charmes152ebee2013-05-10 00:50:56454 if config.Memory > 0 && !srv.runtime.capabilities.MemoryLimit {
455 log.Println("WARNING: Your kernel does not support memory limit capabilities. Limitation discarded.")
Guillaume J. Charmesb56b2da2013-05-07 23:33:12456 out.Warnings = append(out.Warnings, "Your kernel does not support memory limit capabilities. Limitation discarded.")
457 }
Guillaume J. Charmes152ebee2013-05-10 00:50:56458 if config.Memory > 0 && !srv.runtime.capabilities.SwapLimit {
459 log.Println("WARNING: Your kernel does not support swap limit capabilities. Limitation discarded.")
Guillaume J. Charmesb56b2da2013-05-07 23:33:12460 out.Warnings = append(out.Warnings, "Your kernel does not support memory swap capabilities. Limitation discarded.")
461 }
Guillaume J. Charmesa3f60542013-06-06 18:01:09462
Guillaume J. Charmesb56b2da2013-05-07 23:33:12463 b, err := json.Marshal(out)
464 if err != nil {
Victor Vieux7cc08232013-05-10 18:20:49465 return err
Guillaume J. Charmesb56b2da2013-05-07 23:33:12466 }
Victor Vieux08621832013-05-09 19:42:29467 w.WriteHeader(http.StatusCreated)
Victor Vieuxfd224ee2013-06-04 18:00:22468 writeJSON(w, b)
Victor Vieux7cc08232013-05-10 18:20:49469 return nil
Guillaume J. Charmesb56b2da2013-05-07 23:33:12470}
471
Victor Vieuxfaae7222013-05-22 15:29:54472func postContainersRestart(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
Victor Vieux954ecac2013-05-08 16:52:01473 if err := parseForm(r); err != nil {
Victor Vieux7cc08232013-05-10 18:20:49474 return err
Guillaume J. Charmesb56b2da2013-05-07 23:33:12475 }
476 t, err := strconv.Atoi(r.Form.Get("t"))
477 if err != nil || t < 0 {
478 t = 10
479 }
Guillaume J. Charmesff67da92013-05-09 23:28:47480 if vars == nil {
Victor Vieux7cc08232013-05-10 18:20:49481 return fmt.Errorf("Missing parameter")
Guillaume J. Charmesff67da92013-05-09 23:28:47482 }
Guillaume J. Charmesb56b2da2013-05-07 23:33:12483 name := vars["name"]
484 if err := srv.ContainerRestart(name, t); err != nil {
Victor Vieux7cc08232013-05-10 18:20:49485 return err
Guillaume J. Charmesb56b2da2013-05-07 23:33:12486 }
Victor Vieux08621832013-05-09 19:42:29487 w.WriteHeader(http.StatusNoContent)
Victor Vieux7cc08232013-05-10 18:20:49488 return nil
Guillaume J. Charmesb56b2da2013-05-07 23:33:12489}
490
Victor Vieuxfaae7222013-05-22 15:29:54491func deleteContainers(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
Victor Vieux954ecac2013-05-08 16:52:01492 if err := parseForm(r); err != nil {
Victor Vieux7cc08232013-05-10 18:20:49493 return err
Guillaume J. Charmesb56b2da2013-05-07 23:33:12494 }
Guillaume J. Charmesff67da92013-05-09 23:28:47495 if vars == nil {
Victor Vieux7cc08232013-05-10 18:20:49496 return fmt.Errorf("Missing parameter")
Guillaume J. Charmesff67da92013-05-09 23:28:47497 }
Guillaume J. Charmesb56b2da2013-05-07 23:33:12498 name := vars["name"]
Victor Vieux0c544352013-05-16 13:45:29499 removeVolume, err := getBoolParam(r.Form.Get("v"))
500 if err != nil {
501 return err
502 }
Guillaume J. Charmesab96da82013-05-07 23:47:43503
Guillaume J. Charmes0c6380c2013-05-10 02:19:55504 if err := srv.ContainerDestroy(name, removeVolume); err != nil {
Victor Vieux7cc08232013-05-10 18:20:49505 return err
Guillaume J. Charmesb56b2da2013-05-07 23:33:12506 }
Victor Vieux08621832013-05-09 19:42:29507 w.WriteHeader(http.StatusNoContent)
Victor Vieux7cc08232013-05-10 18:20:49508 return nil
Guillaume J. Charmesb56b2da2013-05-07 23:33:12509}
510
Victor Vieuxfaae7222013-05-22 15:29:54511func deleteImages(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
Victor Vieux67b20f22013-05-20 18:31:45512 if err := parseForm(r); err != nil {
513 return err
514 }
Guillaume J. Charmesff67da92013-05-09 23:28:47515 if vars == nil {
Victor Vieux7cc08232013-05-10 18:20:49516 return fmt.Errorf("Missing parameter")
Guillaume J. Charmesff67da92013-05-09 23:28:47517 }
Guillaume J. Charmesb56b2da2013-05-07 23:33:12518 name := vars["name"]
Victor Vieuxc46382b2013-06-13 17:58:06519 imgs, err := srv.ImageDelete(name, version > 1.1)
Victor Vieux9060b5c2013-05-31 14:37:02520 if err != nil {
Victor Vieux7cc08232013-05-10 18:20:49521 return err
Guillaume J. Charmesb56b2da2013-05-07 23:33:12522 }
Victor Vieux9060b5c2013-05-31 14:37:02523 if imgs != nil {
524 if len(*imgs) != 0 {
525 b, err := json.Marshal(imgs)
526 if err != nil {
527 return err
528 }
Victor Vieux66d9a732013-06-10 21:05:54529 writeJSON(w, b)
Victor Vieux9060b5c2013-05-31 14:37:02530 } else {
531 return fmt.Errorf("Conflict, %s wasn't deleted", name)
532 }
533 } else {
534 w.WriteHeader(http.StatusNoContent)
535 }
Victor Vieux7cc08232013-05-10 18:20:49536 return nil
Guillaume J. Charmesb56b2da2013-05-07 23:33:12537}
538
Victor Vieuxfaae7222013-05-22 15:29:54539func postContainersStart(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
Guillaume J. Charmesff67da92013-05-09 23:28:47540 if vars == nil {
Victor Vieux7cc08232013-05-10 18:20:49541 return fmt.Errorf("Missing parameter")
Guillaume J. Charmesff67da92013-05-09 23:28:47542 }
Guillaume J. Charmesb56b2da2013-05-07 23:33:12543 name := vars["name"]
544 if err := srv.ContainerStart(name); err != nil {
Victor Vieux7cc08232013-05-10 18:20:49545 return err
Guillaume J. Charmesb56b2da2013-05-07 23:33:12546 }
Victor Vieux08621832013-05-09 19:42:29547 w.WriteHeader(http.StatusNoContent)
Victor Vieux7cc08232013-05-10 18:20:49548 return nil
Guillaume J. Charmesb56b2da2013-05-07 23:33:12549}
550
Victor Vieuxfaae7222013-05-22 15:29:54551func postContainersStop(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
Victor Vieux954ecac2013-05-08 16:52:01552 if err := parseForm(r); err != nil {
Victor Vieux7cc08232013-05-10 18:20:49553 return err
Guillaume J. Charmesb56b2da2013-05-07 23:33:12554 }
555 t, err := strconv.Atoi(r.Form.Get("t"))
556 if err != nil || t < 0 {
557 t = 10
558 }
Guillaume J. Charmes2a303da2013-05-10 02:19:24559
Guillaume J. Charmesff67da92013-05-09 23:28:47560 if vars == nil {
Victor Vieux7cc08232013-05-10 18:20:49561 return fmt.Errorf("Missing parameter")
Guillaume J. Charmesff67da92013-05-09 23:28:47562 }
Guillaume J. Charmesb56b2da2013-05-07 23:33:12563 name := vars["name"]
564
565 if err := srv.ContainerStop(name, t); err != nil {
Victor Vieux7cc08232013-05-10 18:20:49566 return err
Guillaume J. Charmesb56b2da2013-05-07 23:33:12567 }
Victor Vieux08621832013-05-09 19:42:29568 w.WriteHeader(http.StatusNoContent)
Victor Vieux7cc08232013-05-10 18:20:49569 return nil
Guillaume J. Charmesb56b2da2013-05-07 23:33:12570}
571
Victor Vieuxfaae7222013-05-22 15:29:54572func postContainersWait(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
Guillaume J. Charmesff67da92013-05-09 23:28:47573 if vars == nil {
Victor Vieux7cc08232013-05-10 18:20:49574 return fmt.Errorf("Missing parameter")
Guillaume J. Charmesff67da92013-05-09 23:28:47575 }
Guillaume J. Charmesb56b2da2013-05-07 23:33:12576 name := vars["name"]
577 status, err := srv.ContainerWait(name)
578 if err != nil {
Victor Vieux7cc08232013-05-10 18:20:49579 return err
Guillaume J. Charmesb56b2da2013-05-07 23:33:12580 }
Victor Vieuxfd224ee2013-06-04 18:00:22581 b, err := json.Marshal(&APIWait{StatusCode: status})
Guillaume J. Charmesb56b2da2013-05-07 23:33:12582 if err != nil {
Victor Vieux7cc08232013-05-10 18:20:49583 return err
Guillaume J. Charmesb56b2da2013-05-07 23:33:12584 }
Victor Vieuxfd224ee2013-06-04 18:00:22585 writeJSON(w, b)
Victor Vieux7cc08232013-05-10 18:20:49586 return nil
Guillaume J. Charmesb56b2da2013-05-07 23:33:12587}
588
Guillaume J. Charmes70d21232013-05-24 02:33:28589func postContainersResize(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
590 if err := parseForm(r); err != nil {
591 return err
592 }
593 height, err := strconv.Atoi(r.Form.Get("h"))
594 if err != nil {
595 return err
596 }
597 width, err := strconv.Atoi(r.Form.Get("w"))
598 if err != nil {
599 return err
600 }
601 if vars == nil {
602 return fmt.Errorf("Missing parameter")
603 }
604 name := vars["name"]
605 if err := srv.ContainerResize(name, height, width); err != nil {
606 return err
607 }
608 return nil
609}
610
Victor Vieuxfaae7222013-05-22 15:29:54611func postContainersAttach(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
Victor Vieux954ecac2013-05-08 16:52:01612 if err := parseForm(r); err != nil {
Victor Vieux7cc08232013-05-10 18:20:49613 return err
Guillaume J. Charmesb56b2da2013-05-07 23:33:12614 }
Victor Vieux0c544352013-05-16 13:45:29615 logs, err := getBoolParam(r.Form.Get("logs"))
616 if err != nil {
617 return err
618 }
619 stream, err := getBoolParam(r.Form.Get("stream"))
620 if err != nil {
621 return err
622 }
623 stdin, err := getBoolParam(r.Form.Get("stdin"))
624 if err != nil {
625 return err
626 }
627 stdout, err := getBoolParam(r.Form.Get("stdout"))
628 if err != nil {
629 return err
630 }
631 stderr, err := getBoolParam(r.Form.Get("stderr"))
632 if err != nil {
633 return err
634 }
635
Guillaume J. Charmesff67da92013-05-09 23:28:47636 if vars == nil {
Victor Vieux7cc08232013-05-10 18:20:49637 return fmt.Errorf("Missing parameter")
Guillaume J. Charmesff67da92013-05-09 23:28:47638 }
Guillaume J. Charmesb56b2da2013-05-07 23:33:12639 name := vars["name"]
640
Victor Vieuxe5fa4a42013-05-28 16:19:12641 if _, err := srv.ContainerInspect(name); err != nil {
642 return err
643 }
644
Guillaume J. Charmes57cfe722013-05-08 01:06:49645 in, out, err := hijackServer(w)
Guillaume J. Charmesb56b2da2013-05-07 23:33:12646 if err != nil {
Victor Vieux7cc08232013-05-10 18:20:49647 return err
Guillaume J. Charmesb56b2da2013-05-07 23:33:12648 }
Guillaume J. Charmescacc7e52013-05-08 06:32:17649 defer in.Close()
Guillaume J. Charmesb56b2da2013-05-07 23:33:12650
Victor Vieux4a1e0d32013-05-08 16:36:37651 fmt.Fprintf(out, "HTTP/1.1 200 OK\r\nContent-Type: application/vnd.docker.raw-stream\r\n\r\n")
Guillaume J. Charmes57cfe722013-05-08 01:06:49652 if err := srv.ContainerAttach(name, logs, stream, stdin, stdout, stderr, in, out); err != nil {
653 fmt.Fprintf(out, "Error: %s\n", err)
Guillaume J. Charmesb56b2da2013-05-07 23:33:12654 }
Victor Vieux7cc08232013-05-10 18:20:49655 return nil
Guillaume J. Charmesb56b2da2013-05-07 23:33:12656}
657
Victor Vieuxfaae7222013-05-22 15:29:54658func getContainersByName(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
Guillaume J. Charmesff67da92013-05-09 23:28:47659 if vars == nil {
Victor Vieux7cc08232013-05-10 18:20:49660 return fmt.Errorf("Missing parameter")
Guillaume J. Charmesff67da92013-05-09 23:28:47661 }
Guillaume J. Charmesb56b2da2013-05-07 23:33:12662 name := vars["name"]
663
664 container, err := srv.ContainerInspect(name)
665 if err != nil {
Victor Vieux7cc08232013-05-10 18:20:49666 return err
Guillaume J. Charmesb56b2da2013-05-07 23:33:12667 }
668 b, err := json.Marshal(container)
669 if err != nil {
Victor Vieux7cc08232013-05-10 18:20:49670 return err
Guillaume J. Charmesb56b2da2013-05-07 23:33:12671 }
Victor Vieuxfd224ee2013-06-04 18:00:22672 writeJSON(w, b)
Victor Vieux7cc08232013-05-10 18:20:49673 return nil
Guillaume J. Charmesb56b2da2013-05-07 23:33:12674}
675
Victor Vieuxfaae7222013-05-22 15:29:54676func getImagesByName(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
Guillaume J. Charmesff67da92013-05-09 23:28:47677 if vars == nil {
Victor Vieux7cc08232013-05-10 18:20:49678 return fmt.Errorf("Missing parameter")
Guillaume J. Charmesff67da92013-05-09 23:28:47679 }
Guillaume J. Charmesb56b2da2013-05-07 23:33:12680 name := vars["name"]
681
682 image, err := srv.ImageInspect(name)
683 if err != nil {
Victor Vieux7cc08232013-05-10 18:20:49684 return err
Guillaume J. Charmesb56b2da2013-05-07 23:33:12685 }
686 b, err := json.Marshal(image)
687 if err != nil {
Victor Vieux7cc08232013-05-10 18:20:49688 return err
Guillaume J. Charmesb56b2da2013-05-07 23:33:12689 }
Victor Vieuxfd224ee2013-06-04 18:00:22690 writeJSON(w, b)
Victor Vieux7cc08232013-05-10 18:20:49691 return nil
Guillaume J. Charmesb56b2da2013-05-07 23:33:12692}
693
Victor Vieuxfaae7222013-05-22 15:29:54694func postImagesGetCache(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
Victor Vieuxfd224ee2013-06-04 18:00:22695 apiConfig := &APIImageConfig{}
Guillaume J. Charmes0f312112013-05-19 17:46:24696 if err := json.NewDecoder(r.Body).Decode(apiConfig); err != nil {
697 return err
698 }
699
Victor Vieuxfd224ee2013-06-04 18:00:22700 image, err := srv.ImageGetCached(apiConfig.ID, apiConfig.Config)
Guillaume J. Charmes0f312112013-05-19 17:46:24701 if err != nil {
702 return err
703 }
Guillaume J. Charmesc2a14bb2013-05-20 19:09:15704 if image == nil {
705 w.WriteHeader(http.StatusNotFound)
706 return nil
707 }
Victor Vieuxfd224ee2013-06-04 18:00:22708 apiID := &APIID{ID: image.ID}
709 b, err := json.Marshal(apiID)
Guillaume J. Charmes0f312112013-05-19 17:46:24710 if err != nil {
711 return err
712 }
Victor Vieuxfd224ee2013-06-04 18:00:22713 writeJSON(w, b)
Guillaume J. Charmes0f312112013-05-19 17:46:24714 return nil
715}
716
Guillaume J. Charmesa4879902013-05-28 20:46:52717func postBuild(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
Guillaume J. Charmesd42c10a2013-05-24 01:32:56718 if err := r.ParseMultipartForm(4096); err != nil {
Guillaume J. Charmes0f135ad2013-05-23 03:07:26719 return err
720 }
Guillaume J. Charmes56431d32013-05-30 19:08:21721 remote := r.FormValue("t")
722 tag := ""
723 if strings.Contains(remote, ":") {
724 remoteParts := strings.Split(remote, ":")
725 tag = remoteParts[1]
726 remote = remoteParts[0]
727 }
Guillaume J. Charmes0f135ad2013-05-23 03:07:26728
Guillaume J. Charmesfe0c0c22013-05-28 22:21:06729 dockerfile, _, err := r.FormFile("Dockerfile")
Guillaume J. Charmes0f135ad2013-05-23 03:07:26730 if err != nil {
731 return err
732 }
733
Guillaume J. Charmesd42c10a2013-05-24 01:32:56734 context, _, err := r.FormFile("Context")
Guillaume J. Charmes0f135ad2013-05-23 03:07:26735 if err != nil {
Guillaume J. Charmesd42c10a2013-05-24 01:32:56736 if err != http.ErrMissingFile {
737 return err
738 }
Guillaume J. Charmes0f135ad2013-05-23 03:07:26739 }
740
Guillaume J. Charmes582a9e02013-05-28 20:47:04741 b := NewBuildFile(srv, utils.NewWriteFlusher(w))
Guillaume J. Charmes56431d32013-05-30 19:08:21742 if id, err := b.Build(dockerfile, context); err != nil {
Guillaume J. Charmesfe0c0c22013-05-28 22:21:06743 fmt.Fprintf(w, "Error build: %s\n", err)
Guillaume J. Charmes56431d32013-05-30 19:08:21744 } else if remote != "" {
745 srv.runtime.repositories.Set(remote, tag, id, false)
Guillaume J. Charmes0f135ad2013-05-23 03:07:26746 }
747 return nil
748}
749
Michael Crosbydd53c452013-06-11 01:10:40750func optionsHandler(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
751 w.WriteHeader(http.StatusOK)
752 return nil
753}
Michael Crosby6d5bdff2013-06-04 01:39:00754func writeCorsHeaders(w http.ResponseWriter, r *http.Request) {
755 w.Header().Add("Access-Control-Allow-Origin", "*")
756 w.Header().Add("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept")
Michael Crosby393e8732013-06-10 02:17:35757 w.Header().Add("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT, OPTIONS")
Michael Crosby6d5bdff2013-06-04 01:39:00758}
759
Michael Crosby0a286282013-06-10 22:02:40760func createRouter(srv *Server, logging bool) (*mux.Router, error) {
Victor Vieuxc0d5d592013-04-18 01:13:43761 r := mux.NewRouter()
Solomon Hykesa11b3132013-04-11 02:48:21762
Victor Vieuxfaae7222013-05-22 15:29:54763 m := map[string]map[string]func(*Server, float64, http.ResponseWriter, *http.Request, map[string]string) error{
Guillaume J. Charmesb56b2da2013-05-07 23:33:12764 "GET": {
Victor Vieux3dd1e4d2013-06-03 12:09:16765 "/auth": getAuth,
Guillaume J. Charmesb56b2da2013-05-07 23:33:12766 "/version": getVersion,
Guillaume J. Charmes152ebee2013-05-10 00:50:56767 "/info": getInfo,
Victor Vieuxfd224ee2013-06-04 18:00:22768 "/images/json": getImagesJSON,
Victor Vieuxc423a792013-05-09 21:52:12769 "/images/viz": getImagesViz,
Victor Vieux60ddcaa2013-05-08 15:35:50770 "/images/search": getImagesSearch,
Guillaume J. Charmesb56b2da2013-05-07 23:33:12771 "/images/{name:.*}/history": getImagesHistory,
Victor Vieux60ddcaa2013-05-08 15:35:50772 "/images/{name:.*}/json": getImagesByName,
Victor Vieuxfd224ee2013-06-04 18:00:22773 "/containers/ps": getContainersJSON,
774 "/containers/json": getContainersJSON,
Guillaume J. Charmes152ebee2013-05-10 00:50:56775 "/containers/{name:.*}/export": getContainersExport,
776 "/containers/{name:.*}/changes": getContainersChanges,
Victor Vieux60ddcaa2013-05-08 15:35:50777 "/containers/{name:.*}/json": getContainersByName,
Guillaume J. Charmesb56b2da2013-05-07 23:33:12778 },
779 "POST": {
Guillaume J. Charmes152ebee2013-05-10 00:50:56780 "/auth": postAuth,
Guillaume J. Charmesb56b2da2013-05-07 23:33:12781 "/commit": postCommit,
Guillaume J. Charmes0f135ad2013-05-23 03:07:26782 "/build": postBuild,
Guillaume J. Charmes152ebee2013-05-10 00:50:56783 "/images/create": postImagesCreate,
Guillaume J. Charmes1941c792013-05-10 05:28:52784 "/images/{name:.*}/insert": postImagesInsert,
785 "/images/{name:.*}/push": postImagesPush,
Guillaume J. Charmes152ebee2013-05-10 00:50:56786 "/images/{name:.*}/tag": postImagesTag,
Guillaume J. Charmes0f312112013-05-19 17:46:24787 "/images/getCache": postImagesGetCache,
Guillaume J. Charmes152ebee2013-05-10 00:50:56788 "/containers/create": postContainersCreate,
789 "/containers/{name:.*}/kill": postContainersKill,
Guillaume J. Charmesb56b2da2013-05-07 23:33:12790 "/containers/{name:.*}/restart": postContainersRestart,
791 "/containers/{name:.*}/start": postContainersStart,
792 "/containers/{name:.*}/stop": postContainersStop,
793 "/containers/{name:.*}/wait": postContainersWait,
Guillaume J. Charmes70d21232013-05-24 02:33:28794 "/containers/{name:.*}/resize": postContainersResize,
Guillaume J. Charmesb56b2da2013-05-07 23:33:12795 "/containers/{name:.*}/attach": postContainersAttach,
796 },
797 "DELETE": {
798 "/containers/{name:.*}": deleteContainers,
799 "/images/{name:.*}": deleteImages,
800 },
Michael Crosbydd53c452013-06-11 01:10:40801 "OPTIONS": {
802 "": optionsHandler,
803 },
Guillaume J. Charmesb56b2da2013-05-07 23:33:12804 }
Victor Vieuxf37399d2013-05-06 11:34:31805
Guillaume J. Charmesb56b2da2013-05-07 23:33:12806 for method, routes := range m {
807 for route, fct := range routes {
Guillaume J. Charmes2e69e172013-05-14 22:37:35808 utils.Debugf("Registering %s, %s", method, route)
Guillaume J. Charmesb56b2da2013-05-07 23:33:12809 // NOTE: scope issue, make sure the variables are local and won't be changed
810 localRoute := route
811 localMethod := method
812 localFct := fct
Victor Vieuxfaae7222013-05-22 15:29:54813 f := func(w http.ResponseWriter, r *http.Request) {
Guillaume J. Charmes2e69e172013-05-14 22:37:35814 utils.Debugf("Calling %s %s", localMethod, localRoute)
Victor Vieuxc423a792013-05-09 21:52:12815 if logging {
816 log.Println(r.Method, r.RequestURI)
817 }
Victor Vieux7c7619e2013-05-09 18:24:49818 if strings.Contains(r.Header.Get("User-Agent"), "Docker-Client/") {
819 userAgent := strings.Split(r.Header.Get("User-Agent"), "/")
820 if len(userAgent) == 2 && userAgent[1] != VERSION {
Guillaume J. Charmes2e69e172013-05-14 22:37:35821 utils.Debugf("Warning: client and server don't have the same version (client: %s, server: %s)", userAgent[1], VERSION)
Victor Vieux7c7619e2013-05-09 18:24:49822 }
823 }
Victor Vieuxfaae7222013-05-22 15:29:54824 version, err := strconv.ParseFloat(mux.Vars(r)["version"], 64)
825 if err != nil {
Victor Vieuxfd224ee2013-06-04 18:00:22826 version = APIVERSION
Victor Vieuxfaae7222013-05-22 15:29:54827 }
Michael Crosby393e8732013-06-10 02:17:35828 if srv.enableCors {
829 writeCorsHeaders(w, r)
830 }
Victor Vieuxfd224ee2013-06-04 18:00:22831 if version == 0 || version > APIVERSION {
Victor Vieuxfaae7222013-05-22 15:29:54832 w.WriteHeader(http.StatusNotFound)
833 return
834 }
835 if err := localFct(srv, version, w, r, mux.Vars(r)); err != nil {
Guillaume J. Charmes891c5202013-05-08 00:27:09836 httpError(w, err)
837 }
Victor Vieuxfaae7222013-05-22 15:29:54838 }
Michael Crosbydd53c452013-06-11 01:10:40839
840 if localRoute == "" {
841 r.Methods(localMethod).HandlerFunc(f)
842 } else {
843 r.Path("/v{version:[0-9.]+}" + localRoute).Methods(localMethod).HandlerFunc(f)
844 r.Path(localRoute).Methods(localMethod).HandlerFunc(f)
845 }
Victor Vieuxf37399d2013-05-06 11:34:31846 }
Guillaume J. Charmesb56b2da2013-05-07 23:33:12847 }
Michael Crosby0a286282013-06-10 22:02:40848 return r, nil
849}
850
851func ListenAndServe(addr string, srv *Server, logging bool) error {
852 log.Printf("Listening for HTTP on %s\n", addr)
853
854 r, err := createRouter(srv, logging)
855 if err != nil {
856 return err
857 }
Victor Vieuxc0d5d592013-04-18 01:13:43858 return http.ListenAndServe(addr, r)
Solomon Hykesa11b3132013-04-11 02:48:21859}