| Solomon Hykes | a11b313 | 2013-04-11 02:48:21 | [diff] [blame] | 1 | package docker |
| 2 | |
| 3 | import ( |
| Victor Vieux | c0d5d59 | 2013-04-18 01:13:43 | [diff] [blame] | 4 | "encoding/json" |
| Victor Vieux | b295239 | 2013-04-19 13:24:37 | [diff] [blame] | 5 | "fmt" |
| Victor Vieux | f37399d | 2013-05-06 11:34:31 | [diff] [blame] | 6 | "github.com/dotcloud/docker/auth" |
| Guillaume J. Charmes | 2e69e17 | 2013-05-14 22:37:35 | [diff] [blame] | 7 | "github.com/dotcloud/docker/utils" |
| Solomon Hykes | a11b313 | 2013-04-11 02:48:21 | [diff] [blame] | 8 | "github.com/gorilla/mux" |
| Guillaume J. Charmes | 57cfe72 | 2013-05-08 01:06:49 | [diff] [blame] | 9 | "io" |
| Victor Vieux | 79e9105 | 2013-04-18 16:56:22 | [diff] [blame] | 10 | "log" |
| Solomon Hykes | a11b313 | 2013-04-11 02:48:21 | [diff] [blame] | 11 | "net/http" |
| Victor Vieux | 1aa7f13 | 2013-04-22 16:17:47 | [diff] [blame] | 12 | "strconv" |
| Victor Vieux | b295239 | 2013-04-19 13:24:37 | [diff] [blame] | 13 | "strings" |
| Solomon Hykes | a11b313 | 2013-04-11 02:48:21 | [diff] [blame] | 14 | ) |
| 15 | |
| Victor Vieux | c906239 | 2013-06-05 10:23:45 | [diff] [blame] | 16 | const APIVERSION = 1.2 |
| Victor Vieux | faae722 | 2013-05-22 15:29:54 | [diff] [blame] | 17 | |
| Guillaume J. Charmes | 57cfe72 | 2013-05-08 01:06:49 | [diff] [blame] | 18 | func hijackServer(w http.ResponseWriter) (io.ReadCloser, io.Writer, error) { |
| 19 | conn, _, err := w.(http.Hijacker).Hijack() |
| Victor Vieux | 04cd20f | 2013-05-06 09:31:22 | [diff] [blame] | 20 | if err != nil { |
| 21 | return nil, nil, err |
| 22 | } |
| Victor Vieux | 04cd20f | 2013-05-06 09:31:22 | [diff] [blame] | 23 | // Flush the options to make sure the client sets the raw mode |
| Guillaume J. Charmes | 57cfe72 | 2013-05-08 01:06:49 | [diff] [blame] | 24 | conn.Write([]byte{}) |
| 25 | return conn, conn, nil |
| Victor Vieux | 04cd20f | 2013-05-06 09:31:22 | [diff] [blame] | 26 | } |
| 27 | |
| Victor Vieux | 954ecac | 2013-05-08 16:52:01 | [diff] [blame] | 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 | |
| Guillaume J. Charmes | 0f135ad | 2013-05-23 03:07:26 | [diff] [blame] | 36 | func 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 Vieux | 04cd20f | 2013-05-06 09:31:22 | [diff] [blame] | 43 | func httpError(w http.ResponseWriter, err error) { |
| 44 | if strings.HasPrefix(err.Error(), "No such") { |
| 45 | http.Error(w, err.Error(), http.StatusNotFound) |
| Victor Vieux | 0c54435 | 2013-05-16 13:45:29 | [diff] [blame] | 46 | } else if strings.HasPrefix(err.Error(), "Bad parameter") { |
| 47 | http.Error(w, err.Error(), http.StatusBadRequest) |
| Victor Vieux | 67b20f2 | 2013-05-20 18:31:45 | [diff] [blame] | 48 | } else if strings.HasPrefix(err.Error(), "Conflict") { |
| 49 | http.Error(w, err.Error(), http.StatusConflict) |
| Victor Vieux | 468e4c4 | 2013-05-31 15:34:23 | [diff] [blame] | 50 | } else if strings.HasPrefix(err.Error(), "Impossible") { |
| 51 | http.Error(w, err.Error(), http.StatusNotAcceptable) |
| Victor Vieux | 04cd20f | 2013-05-06 09:31:22 | [diff] [blame] | 52 | } else { |
| 53 | http.Error(w, err.Error(), http.StatusInternalServerError) |
| 54 | } |
| 55 | } |
| 56 | |
| Victor Vieux | fd224ee | 2013-06-04 18:00:22 | [diff] [blame] | 57 | func writeJSON(w http.ResponseWriter, b []byte) { |
| Victor Vieux | f7beba3 | 2013-05-10 19:11:59 | [diff] [blame] | 58 | w.Header().Set("Content-Type", "application/json") |
| 59 | w.Write(b) |
| 60 | } |
| 61 | |
| Guillaume J. Charmes | 70d2123 | 2013-05-24 02:33:28 | [diff] [blame] | 62 | // FIXME: Use stvconv.ParseBool() instead? |
| Victor Vieux | 0c54435 | 2013-05-16 13:45:29 | [diff] [blame] | 63 | func 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 Vieux | 3dd1e4d | 2013-06-03 12:09:16 | [diff] [blame] | 73 | func 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. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 77 | } |
| Victor Vieux | 3dd1e4d | 2013-06-03 12:09:16 | [diff] [blame] | 78 | 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. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 86 | if err != nil { |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 87 | return err |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 88 | } |
| Victor Vieux | fd224ee | 2013-06-04 18:00:22 | [diff] [blame] | 89 | writeJSON(w, b) |
| Victor Vieux | 3dd1e4d | 2013-06-03 12:09:16 | [diff] [blame] | 90 | return nil |
| 91 | } |
| 92 | |
| 93 | func 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. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 122 | if status != "" { |
| Victor Vieux | fd224ee | 2013-06-04 18:00:22 | [diff] [blame] | 123 | b, err := json.Marshal(&APIAuth{Status: status}) |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 124 | if err != nil { |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 125 | return err |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 126 | } |
| Victor Vieux | fd224ee | 2013-06-04 18:00:22 | [diff] [blame] | 127 | writeJSON(w, b) |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 128 | return nil |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 129 | } |
| Victor Vieux | 0862183 | 2013-05-09 19:42:29 | [diff] [blame] | 130 | w.WriteHeader(http.StatusNoContent) |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 131 | return nil |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 132 | } |
| 133 | |
| Victor Vieux | faae722 | 2013-05-22 15:29:54 | [diff] [blame] | 134 | func getVersion(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error { |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 135 | m := srv.DockerVersion() |
| 136 | b, err := json.Marshal(m) |
| 137 | if err != nil { |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 138 | return err |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 139 | } |
| Victor Vieux | fd224ee | 2013-06-04 18:00:22 | [diff] [blame] | 140 | writeJSON(w, b) |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 141 | return nil |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 142 | } |
| 143 | |
| Victor Vieux | faae722 | 2013-05-22 15:29:54 | [diff] [blame] | 144 | func postContainersKill(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error { |
| Guillaume J. Charmes | ff67da9 | 2013-05-09 23:28:47 | [diff] [blame] | 145 | if vars == nil { |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 146 | return fmt.Errorf("Missing parameter") |
| Guillaume J. Charmes | ff67da9 | 2013-05-09 23:28:47 | [diff] [blame] | 147 | } |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 148 | name := vars["name"] |
| 149 | if err := srv.ContainerKill(name); err != nil { |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 150 | return err |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 151 | } |
| Victor Vieux | 0862183 | 2013-05-09 19:42:29 | [diff] [blame] | 152 | w.WriteHeader(http.StatusNoContent) |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 153 | return nil |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 154 | } |
| 155 | |
| Victor Vieux | faae722 | 2013-05-22 15:29:54 | [diff] [blame] | 156 | func getContainersExport(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error { |
| Guillaume J. Charmes | ff67da9 | 2013-05-09 23:28:47 | [diff] [blame] | 157 | if vars == nil { |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 158 | return fmt.Errorf("Missing parameter") |
| Guillaume J. Charmes | ff67da9 | 2013-05-09 23:28:47 | [diff] [blame] | 159 | } |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 160 | name := vars["name"] |
| 161 | |
| Victor Vieux | 93dc2c3 | 2013-05-09 21:28:03 | [diff] [blame] | 162 | if err := srv.ContainerExport(name, w); err != nil { |
| Guillaume J. Charmes | 2e69e17 | 2013-05-14 22:37:35 | [diff] [blame] | 163 | utils.Debugf("%s", err.Error()) |
| Victor Vieux | 8b31d30 | 2013-05-13 09:38:13 | [diff] [blame] | 164 | return err |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 165 | } |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 166 | return nil |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 167 | } |
| 168 | |
| Victor Vieux | fd224ee | 2013-06-04 18:00:22 | [diff] [blame] | 169 | func getImagesJSON(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error { |
| Victor Vieux | 954ecac | 2013-05-08 16:52:01 | [diff] [blame] | 170 | if err := parseForm(r); err != nil { |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 171 | return err |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 172 | } |
| 173 | |
| Victor Vieux | 0c54435 | 2013-05-16 13:45:29 | [diff] [blame] | 174 | all, err := getBoolParam(r.Form.Get("all")) |
| 175 | if err != nil { |
| 176 | return err |
| 177 | } |
| Victor Vieux | c423a79 | 2013-05-09 21:52:12 | [diff] [blame] | 178 | filter := r.Form.Get("filter") |
| Victor Vieux | 0ecf5e2 | 2013-05-09 21:10:26 | [diff] [blame] | 179 | |
| Victor Vieux | 1990c49 | 2013-05-13 10:18:55 | [diff] [blame] | 180 | outs, err := srv.Images(all, filter) |
| Victor Vieux | c423a79 | 2013-05-09 21:52:12 | [diff] [blame] | 181 | if err != nil { |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 182 | return err |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 183 | } |
| Victor Vieux | c423a79 | 2013-05-09 21:52:12 | [diff] [blame] | 184 | b, err := json.Marshal(outs) |
| 185 | if err != nil { |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 186 | return err |
| Victor Vieux | c423a79 | 2013-05-09 21:52:12 | [diff] [blame] | 187 | } |
| Victor Vieux | fd224ee | 2013-06-04 18:00:22 | [diff] [blame] | 188 | writeJSON(w, b) |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 189 | return nil |
| Victor Vieux | c423a79 | 2013-05-09 21:52:12 | [diff] [blame] | 190 | } |
| 191 | |
| Victor Vieux | faae722 | 2013-05-22 15:29:54 | [diff] [blame] | 192 | func getImagesViz(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error { |
| Victor Vieux | c423a79 | 2013-05-09 21:52:12 | [diff] [blame] | 193 | if err := srv.ImagesViz(w); err != nil { |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 194 | return err |
| Victor Vieux | c423a79 | 2013-05-09 21:52:12 | [diff] [blame] | 195 | } |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 196 | return nil |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 197 | } |
| 198 | |
| Victor Vieux | faae722 | 2013-05-22 15:29:54 | [diff] [blame] | 199 | func getInfo(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error { |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 200 | out := srv.DockerInfo() |
| 201 | b, err := json.Marshal(out) |
| 202 | if err != nil { |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 203 | return err |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 204 | } |
| Victor Vieux | fd224ee | 2013-06-04 18:00:22 | [diff] [blame] | 205 | writeJSON(w, b) |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 206 | return nil |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 207 | } |
| 208 | |
| Victor Vieux | faae722 | 2013-05-22 15:29:54 | [diff] [blame] | 209 | func getImagesHistory(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error { |
| Guillaume J. Charmes | ff67da9 | 2013-05-09 23:28:47 | [diff] [blame] | 210 | if vars == nil { |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 211 | return fmt.Errorf("Missing parameter") |
| Guillaume J. Charmes | ff67da9 | 2013-05-09 23:28:47 | [diff] [blame] | 212 | } |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 213 | name := vars["name"] |
| 214 | outs, err := srv.ImageHistory(name) |
| 215 | if err != nil { |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 216 | return err |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 217 | } |
| 218 | b, err := json.Marshal(outs) |
| 219 | if err != nil { |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 220 | return err |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 221 | } |
| Victor Vieux | fd224ee | 2013-06-04 18:00:22 | [diff] [blame] | 222 | writeJSON(w, b) |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 223 | return nil |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 224 | } |
| 225 | |
| Victor Vieux | faae722 | 2013-05-22 15:29:54 | [diff] [blame] | 226 | func getContainersChanges(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error { |
| Guillaume J. Charmes | ff67da9 | 2013-05-09 23:28:47 | [diff] [blame] | 227 | if vars == nil { |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 228 | return fmt.Errorf("Missing parameter") |
| Guillaume J. Charmes | ff67da9 | 2013-05-09 23:28:47 | [diff] [blame] | 229 | } |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 230 | name := vars["name"] |
| 231 | changesStr, err := srv.ContainerChanges(name) |
| 232 | if err != nil { |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 233 | return err |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 234 | } |
| 235 | b, err := json.Marshal(changesStr) |
| 236 | if err != nil { |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 237 | return err |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 238 | } |
| Victor Vieux | fd224ee | 2013-06-04 18:00:22 | [diff] [blame] | 239 | writeJSON(w, b) |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 240 | return nil |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 241 | } |
| 242 | |
| Victor Vieux | fd224ee | 2013-06-04 18:00:22 | [diff] [blame] | 243 | func getContainersJSON(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error { |
| Victor Vieux | 954ecac | 2013-05-08 16:52:01 | [diff] [blame] | 244 | if err := parseForm(r); err != nil { |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 245 | return err |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 246 | } |
| Victor Vieux | 0c54435 | 2013-05-16 13:45:29 | [diff] [blame] | 247 | all, err := getBoolParam(r.Form.Get("all")) |
| 248 | if err != nil { |
| 249 | return err |
| 250 | } |
| Victor Vieux | bc3fa50 | 2013-05-08 16:28:11 | [diff] [blame] | 251 | since := r.Form.Get("since") |
| 252 | before := r.Form.Get("before") |
| Victor Vieux | 60ddcaa | 2013-05-08 15:35:50 | [diff] [blame] | 253 | n, err := strconv.Atoi(r.Form.Get("limit")) |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 254 | if err != nil { |
| 255 | n = -1 |
| 256 | } |
| 257 | |
| Victor Vieux | 1990c49 | 2013-05-13 10:18:55 | [diff] [blame] | 258 | outs := srv.Containers(all, n, since, before) |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 259 | b, err := json.Marshal(outs) |
| 260 | if err != nil { |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 261 | return err |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 262 | } |
| Victor Vieux | fd224ee | 2013-06-04 18:00:22 | [diff] [blame] | 263 | writeJSON(w, b) |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 264 | return nil |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 265 | } |
| 266 | |
| Victor Vieux | faae722 | 2013-05-22 15:29:54 | [diff] [blame] | 267 | func postImagesTag(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error { |
| Victor Vieux | 954ecac | 2013-05-08 16:52:01 | [diff] [blame] | 268 | if err := parseForm(r); err != nil { |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 269 | return err |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 270 | } |
| 271 | repo := r.Form.Get("repo") |
| 272 | tag := r.Form.Get("tag") |
| Guillaume J. Charmes | ff67da9 | 2013-05-09 23:28:47 | [diff] [blame] | 273 | if vars == nil { |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 274 | return fmt.Errorf("Missing parameter") |
| Guillaume J. Charmes | ff67da9 | 2013-05-09 23:28:47 | [diff] [blame] | 275 | } |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 276 | name := vars["name"] |
| Victor Vieux | 0c54435 | 2013-05-16 13:45:29 | [diff] [blame] | 277 | force, err := getBoolParam(r.Form.Get("force")) |
| 278 | if err != nil { |
| 279 | return err |
| 280 | } |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 281 | |
| 282 | if err := srv.ContainerTag(name, repo, tag, force); err != nil { |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 283 | return err |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 284 | } |
| 285 | w.WriteHeader(http.StatusCreated) |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 286 | return nil |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 287 | } |
| 288 | |
| Victor Vieux | faae722 | 2013-05-22 15:29:54 | [diff] [blame] | 289 | func postCommit(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error { |
| Victor Vieux | 954ecac | 2013-05-08 16:52:01 | [diff] [blame] | 290 | if err := parseForm(r); err != nil { |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 291 | return err |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 292 | } |
| Guillaume J. Charmes | 5bec927 | 2013-05-10 19:28:07 | [diff] [blame] | 293 | config := &Config{} |
| 294 | if err := json.NewDecoder(r.Body).Decode(config); err != nil { |
| Guillaume J. Charmes | 2e69e17 | 2013-05-14 22:37:35 | [diff] [blame] | 295 | utils.Debugf("%s", err.Error()) |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 296 | } |
| 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. Charmes | 5bec927 | 2013-05-10 19:28:07 | [diff] [blame] | 302 | id, err := srv.ContainerCommit(container, repo, tag, author, comment, config) |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 303 | if err != nil { |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 304 | return err |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 305 | } |
| Victor Vieux | fd224ee | 2013-06-04 18:00:22 | [diff] [blame] | 306 | b, err := json.Marshal(&APIID{id}) |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 307 | if err != nil { |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 308 | return err |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 309 | } |
| Victor Vieux | 0862183 | 2013-05-09 19:42:29 | [diff] [blame] | 310 | w.WriteHeader(http.StatusCreated) |
| Victor Vieux | fd224ee | 2013-06-04 18:00:22 | [diff] [blame] | 311 | writeJSON(w, b) |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 312 | return nil |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 313 | } |
| 314 | |
| Guillaume J. Charmes | 152ebee | 2013-05-10 00:50:56 | [diff] [blame] | 315 | // Creates an image from Pull or from Import |
| Victor Vieux | faae722 | 2013-05-22 15:29:54 | [diff] [blame] | 316 | func postImagesCreate(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error { |
| Victor Vieux | 954ecac | 2013-05-08 16:52:01 | [diff] [blame] | 317 | if err := parseForm(r); err != nil { |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 318 | return err |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 319 | } |
| 320 | |
| 321 | src := r.Form.Get("fromSrc") |
| 322 | image := r.Form.Get("fromImage") |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 323 | tag := r.Form.Get("tag") |
| Guillaume J. Charmes | f29e5dc | 2013-05-16 19:09:06 | [diff] [blame] | 324 | repo := r.Form.Get("repo") |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 325 | |
| Victor Vieux | c8c7094 | 2013-05-25 15:09:46 | [diff] [blame] | 326 | if version > 1.0 { |
| 327 | w.Header().Set("Content-Type", "application/json") |
| 328 | } |
| 329 | sf := utils.NewStreamFormatter(version > 1.0) |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 330 | if image != "" { //pull |
| 331 | registry := r.Form.Get("registry") |
| Victor Vieux | 7e59b83 | 2013-06-03 17:51:52 | [diff] [blame] | 332 | if err := srv.ImagePull(image, tag, registry, w, sf, &auth.AuthConfig{}); err != nil { |
| Victor Vieux | c8c7094 | 2013-05-25 15:09:46 | [diff] [blame] | 333 | if sf.Used() { |
| Victor Vieux | 5a36efb | 2013-05-26 23:45:45 | [diff] [blame] | 334 | w.Write(sf.FormatError(err)) |
| Victor Vieux | c8c7094 | 2013-05-25 15:09:46 | [diff] [blame] | 335 | return nil |
| 336 | } |
| Guillaume J. Charmes | f29e5dc | 2013-05-16 19:09:06 | [diff] [blame] | 337 | return err |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 338 | } |
| 339 | } else { //import |
| Victor Vieux | c8c7094 | 2013-05-25 15:09:46 | [diff] [blame] | 340 | if err := srv.ImageImport(src, repo, tag, r.Body, w, sf); err != nil { |
| 341 | if sf.Used() { |
| Victor Vieux | 5a36efb | 2013-05-26 23:45:45 | [diff] [blame] | 342 | w.Write(sf.FormatError(err)) |
| Victor Vieux | c8c7094 | 2013-05-25 15:09:46 | [diff] [blame] | 343 | return nil |
| 344 | } |
| Guillaume J. Charmes | f29e5dc | 2013-05-16 19:09:06 | [diff] [blame] | 345 | return err |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 346 | } |
| 347 | } |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 348 | return nil |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 349 | } |
| 350 | |
| Victor Vieux | faae722 | 2013-05-22 15:29:54 | [diff] [blame] | 351 | func getImagesSearch(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error { |
| Victor Vieux | 954ecac | 2013-05-08 16:52:01 | [diff] [blame] | 352 | if err := parseForm(r); err != nil { |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 353 | return err |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 354 | } |
| 355 | |
| 356 | term := r.Form.Get("term") |
| 357 | outs, err := srv.ImagesSearch(term) |
| 358 | if err != nil { |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 359 | return err |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 360 | } |
| 361 | b, err := json.Marshal(outs) |
| 362 | if err != nil { |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 363 | return err |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 364 | } |
| Victor Vieux | fd224ee | 2013-06-04 18:00:22 | [diff] [blame] | 365 | writeJSON(w, b) |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 366 | return nil |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 367 | } |
| 368 | |
| Victor Vieux | faae722 | 2013-05-22 15:29:54 | [diff] [blame] | 369 | func postImagesInsert(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error { |
| Victor Vieux | 954ecac | 2013-05-08 16:52:01 | [diff] [blame] | 370 | if err := parseForm(r); err != nil { |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 371 | return err |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 372 | } |
| 373 | |
| 374 | url := r.Form.Get("url") |
| 375 | path := r.Form.Get("path") |
| Guillaume J. Charmes | ff67da9 | 2013-05-09 23:28:47 | [diff] [blame] | 376 | if vars == nil { |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 377 | return fmt.Errorf("Missing parameter") |
| Guillaume J. Charmes | ff67da9 | 2013-05-09 23:28:47 | [diff] [blame] | 378 | } |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 379 | name := vars["name"] |
| Victor Vieux | c8c7094 | 2013-05-25 15:09:46 | [diff] [blame] | 380 | if version > 1.0 { |
| 381 | w.Header().Set("Content-Type", "application/json") |
| 382 | } |
| 383 | sf := utils.NewStreamFormatter(version > 1.0) |
| Victor Vieux | fd224ee | 2013-06-04 18:00:22 | [diff] [blame] | 384 | imgID, err := srv.ImageInsert(name, url, path, w, sf) |
| Guillaume J. Charmes | 0f135ad | 2013-05-23 03:07:26 | [diff] [blame] | 385 | if err != nil { |
| Victor Vieux | c8c7094 | 2013-05-25 15:09:46 | [diff] [blame] | 386 | if sf.Used() { |
| Victor Vieux | 5a36efb | 2013-05-26 23:45:45 | [diff] [blame] | 387 | w.Write(sf.FormatError(err)) |
| Victor Vieux | c8c7094 | 2013-05-25 15:09:46 | [diff] [blame] | 388 | return nil |
| 389 | } |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 390 | } |
| Victor Vieux | fd224ee | 2013-06-04 18:00:22 | [diff] [blame] | 391 | b, err := json.Marshal(&APIID{ID: imgID}) |
| Guillaume J. Charmes | 0f135ad | 2013-05-23 03:07:26 | [diff] [blame] | 392 | if err != nil { |
| 393 | return err |
| 394 | } |
| Victor Vieux | fd224ee | 2013-06-04 18:00:22 | [diff] [blame] | 395 | writeJSON(w, b) |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 396 | return nil |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 397 | } |
| 398 | |
| Victor Vieux | faae722 | 2013-05-22 15:29:54 | [diff] [blame] | 399 | func postImagesPush(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error { |
| Victor Vieux | 49e6568 | 2013-05-30 15:39:43 | [diff] [blame] | 400 | authConfig := &auth.AuthConfig{} |
| Victor Vieux | 3dd1e4d | 2013-06-03 12:09:16 | [diff] [blame] | 401 | 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 Vieux | 49e6568 | 2013-05-30 15:39:43 | [diff] [blame] | 411 | } |
| Guillaume J. Charmes | 2f4de38 | 2013-05-15 19:21:37 | [diff] [blame] | 412 | if err := parseForm(r); err != nil { |
| 413 | return err |
| 414 | } |
| 415 | registry := r.Form.Get("registry") |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 416 | |
| Guillaume J. Charmes | 2f4de38 | 2013-05-15 19:21:37 | [diff] [blame] | 417 | if vars == nil { |
| 418 | return fmt.Errorf("Missing parameter") |
| 419 | } |
| 420 | name := vars["name"] |
| Victor Vieux | c8c7094 | 2013-05-25 15:09:46 | [diff] [blame] | 421 | if version > 1.0 { |
| 422 | w.Header().Set("Content-Type", "application/json") |
| 423 | } |
| 424 | sf := utils.NewStreamFormatter(version > 1.0) |
| Victor Vieux | 62c7869 | 2013-06-03 11:06:13 | [diff] [blame] | 425 | if err := srv.ImagePush(name, registry, w, sf, authConfig); err != nil { |
| Victor Vieux | c8c7094 | 2013-05-25 15:09:46 | [diff] [blame] | 426 | if sf.Used() { |
| Victor Vieux | 5a36efb | 2013-05-26 23:45:45 | [diff] [blame] | 427 | w.Write(sf.FormatError(err)) |
| Victor Vieux | c8c7094 | 2013-05-25 15:09:46 | [diff] [blame] | 428 | return nil |
| 429 | } |
| Guillaume J. Charmes | 2f4de38 | 2013-05-15 19:21:37 | [diff] [blame] | 430 | return err |
| 431 | } |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 432 | return nil |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 433 | } |
| 434 | |
| Victor Vieux | faae722 | 2013-05-22 15:29:54 | [diff] [blame] | 435 | func postContainersCreate(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error { |
| Guillaume J. Charmes | 152ebee | 2013-05-10 00:50:56 | [diff] [blame] | 436 | config := &Config{} |
| Guillaume J. Charmes | a3f6054 | 2013-06-06 18:01:09 | [diff] [blame] | 437 | out := &APIRun{} |
| 438 | |
| Guillaume J. Charmes | 152ebee | 2013-05-10 00:50:56 | [diff] [blame] | 439 | if err := json.NewDecoder(r.Body).Decode(config); err != nil { |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 440 | return err |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 441 | } |
| Guillaume J. Charmes | a3f6054 | 2013-06-06 18:01:09 | [diff] [blame] | 442 | |
| 443 | if len(config.Dns) == 0 && len(srv.runtime.Dns) == 0 && utils.CheckLocalDns() { |
| Solomon Hykes | 7f11851 | 2013-06-14 21:46:08 | [diff] [blame] | 444 | out.Warnings = append(out.Warnings, fmt.Sprintf("Docker detected local DNS server on resolv.conf. Using default external servers: %v", defaultDns)) |
| Guillaume J. Charmes | a3f6054 | 2013-06-06 18:01:09 | [diff] [blame] | 445 | config.Dns = defaultDns |
| 446 | } |
| 447 | |
| Guillaume J. Charmes | 152ebee | 2013-05-10 00:50:56 | [diff] [blame] | 448 | id, err := srv.ContainerCreate(config) |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 449 | if err != nil { |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 450 | return err |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 451 | } |
| Guillaume J. Charmes | a3f6054 | 2013-06-06 18:01:09 | [diff] [blame] | 452 | out.ID = id |
| Guillaume J. Charmes | 152ebee | 2013-05-10 00:50:56 | [diff] [blame] | 453 | |
| Guillaume J. Charmes | 152ebee | 2013-05-10 00:50:56 | [diff] [blame] | 454 | if config.Memory > 0 && !srv.runtime.capabilities.MemoryLimit { |
| 455 | log.Println("WARNING: Your kernel does not support memory limit capabilities. Limitation discarded.") |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 456 | out.Warnings = append(out.Warnings, "Your kernel does not support memory limit capabilities. Limitation discarded.") |
| 457 | } |
| Guillaume J. Charmes | 152ebee | 2013-05-10 00:50:56 | [diff] [blame] | 458 | if config.Memory > 0 && !srv.runtime.capabilities.SwapLimit { |
| 459 | log.Println("WARNING: Your kernel does not support swap limit capabilities. Limitation discarded.") |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 460 | out.Warnings = append(out.Warnings, "Your kernel does not support memory swap capabilities. Limitation discarded.") |
| 461 | } |
| Guillaume J. Charmes | a3f6054 | 2013-06-06 18:01:09 | [diff] [blame] | 462 | |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 463 | b, err := json.Marshal(out) |
| 464 | if err != nil { |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 465 | return err |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 466 | } |
| Victor Vieux | 0862183 | 2013-05-09 19:42:29 | [diff] [blame] | 467 | w.WriteHeader(http.StatusCreated) |
| Victor Vieux | fd224ee | 2013-06-04 18:00:22 | [diff] [blame] | 468 | writeJSON(w, b) |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 469 | return nil |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 470 | } |
| 471 | |
| Victor Vieux | faae722 | 2013-05-22 15:29:54 | [diff] [blame] | 472 | func postContainersRestart(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error { |
| Victor Vieux | 954ecac | 2013-05-08 16:52:01 | [diff] [blame] | 473 | if err := parseForm(r); err != nil { |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 474 | return err |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 475 | } |
| 476 | t, err := strconv.Atoi(r.Form.Get("t")) |
| 477 | if err != nil || t < 0 { |
| 478 | t = 10 |
| 479 | } |
| Guillaume J. Charmes | ff67da9 | 2013-05-09 23:28:47 | [diff] [blame] | 480 | if vars == nil { |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 481 | return fmt.Errorf("Missing parameter") |
| Guillaume J. Charmes | ff67da9 | 2013-05-09 23:28:47 | [diff] [blame] | 482 | } |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 483 | name := vars["name"] |
| 484 | if err := srv.ContainerRestart(name, t); err != nil { |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 485 | return err |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 486 | } |
| Victor Vieux | 0862183 | 2013-05-09 19:42:29 | [diff] [blame] | 487 | w.WriteHeader(http.StatusNoContent) |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 488 | return nil |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 489 | } |
| 490 | |
| Victor Vieux | faae722 | 2013-05-22 15:29:54 | [diff] [blame] | 491 | func deleteContainers(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error { |
| Victor Vieux | 954ecac | 2013-05-08 16:52:01 | [diff] [blame] | 492 | if err := parseForm(r); err != nil { |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 493 | return err |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 494 | } |
| Guillaume J. Charmes | ff67da9 | 2013-05-09 23:28:47 | [diff] [blame] | 495 | if vars == nil { |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 496 | return fmt.Errorf("Missing parameter") |
| Guillaume J. Charmes | ff67da9 | 2013-05-09 23:28:47 | [diff] [blame] | 497 | } |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 498 | name := vars["name"] |
| Victor Vieux | 0c54435 | 2013-05-16 13:45:29 | [diff] [blame] | 499 | removeVolume, err := getBoolParam(r.Form.Get("v")) |
| 500 | if err != nil { |
| 501 | return err |
| 502 | } |
| Guillaume J. Charmes | ab96da8 | 2013-05-07 23:47:43 | [diff] [blame] | 503 | |
| Guillaume J. Charmes | 0c6380c | 2013-05-10 02:19:55 | [diff] [blame] | 504 | if err := srv.ContainerDestroy(name, removeVolume); err != nil { |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 505 | return err |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 506 | } |
| Victor Vieux | 0862183 | 2013-05-09 19:42:29 | [diff] [blame] | 507 | w.WriteHeader(http.StatusNoContent) |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 508 | return nil |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 509 | } |
| 510 | |
| Victor Vieux | faae722 | 2013-05-22 15:29:54 | [diff] [blame] | 511 | func deleteImages(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error { |
| Victor Vieux | 67b20f2 | 2013-05-20 18:31:45 | [diff] [blame] | 512 | if err := parseForm(r); err != nil { |
| 513 | return err |
| 514 | } |
| Guillaume J. Charmes | ff67da9 | 2013-05-09 23:28:47 | [diff] [blame] | 515 | if vars == nil { |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 516 | return fmt.Errorf("Missing parameter") |
| Guillaume J. Charmes | ff67da9 | 2013-05-09 23:28:47 | [diff] [blame] | 517 | } |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 518 | name := vars["name"] |
| Victor Vieux | c46382b | 2013-06-13 17:58:06 | [diff] [blame] | 519 | imgs, err := srv.ImageDelete(name, version > 1.1) |
| Victor Vieux | 9060b5c | 2013-05-31 14:37:02 | [diff] [blame] | 520 | if err != nil { |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 521 | return err |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 522 | } |
| Victor Vieux | 9060b5c | 2013-05-31 14:37:02 | [diff] [blame] | 523 | if imgs != nil { |
| 524 | if len(*imgs) != 0 { |
| 525 | b, err := json.Marshal(imgs) |
| 526 | if err != nil { |
| 527 | return err |
| 528 | } |
| Victor Vieux | 66d9a73 | 2013-06-10 21:05:54 | [diff] [blame] | 529 | writeJSON(w, b) |
| Victor Vieux | 9060b5c | 2013-05-31 14:37:02 | [diff] [blame] | 530 | } else { |
| 531 | return fmt.Errorf("Conflict, %s wasn't deleted", name) |
| 532 | } |
| 533 | } else { |
| 534 | w.WriteHeader(http.StatusNoContent) |
| 535 | } |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 536 | return nil |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 537 | } |
| 538 | |
| Victor Vieux | faae722 | 2013-05-22 15:29:54 | [diff] [blame] | 539 | func postContainersStart(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error { |
| Guillaume J. Charmes | ff67da9 | 2013-05-09 23:28:47 | [diff] [blame] | 540 | if vars == nil { |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 541 | return fmt.Errorf("Missing parameter") |
| Guillaume J. Charmes | ff67da9 | 2013-05-09 23:28:47 | [diff] [blame] | 542 | } |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 543 | name := vars["name"] |
| 544 | if err := srv.ContainerStart(name); err != nil { |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 545 | return err |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 546 | } |
| Victor Vieux | 0862183 | 2013-05-09 19:42:29 | [diff] [blame] | 547 | w.WriteHeader(http.StatusNoContent) |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 548 | return nil |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 549 | } |
| 550 | |
| Victor Vieux | faae722 | 2013-05-22 15:29:54 | [diff] [blame] | 551 | func postContainersStop(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error { |
| Victor Vieux | 954ecac | 2013-05-08 16:52:01 | [diff] [blame] | 552 | if err := parseForm(r); err != nil { |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 553 | return err |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 554 | } |
| 555 | t, err := strconv.Atoi(r.Form.Get("t")) |
| 556 | if err != nil || t < 0 { |
| 557 | t = 10 |
| 558 | } |
| Guillaume J. Charmes | 2a303da | 2013-05-10 02:19:24 | [diff] [blame] | 559 | |
| Guillaume J. Charmes | ff67da9 | 2013-05-09 23:28:47 | [diff] [blame] | 560 | if vars == nil { |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 561 | return fmt.Errorf("Missing parameter") |
| Guillaume J. Charmes | ff67da9 | 2013-05-09 23:28:47 | [diff] [blame] | 562 | } |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 563 | name := vars["name"] |
| 564 | |
| 565 | if err := srv.ContainerStop(name, t); err != nil { |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 566 | return err |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 567 | } |
| Victor Vieux | 0862183 | 2013-05-09 19:42:29 | [diff] [blame] | 568 | w.WriteHeader(http.StatusNoContent) |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 569 | return nil |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 570 | } |
| 571 | |
| Victor Vieux | faae722 | 2013-05-22 15:29:54 | [diff] [blame] | 572 | func postContainersWait(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error { |
| Guillaume J. Charmes | ff67da9 | 2013-05-09 23:28:47 | [diff] [blame] | 573 | if vars == nil { |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 574 | return fmt.Errorf("Missing parameter") |
| Guillaume J. Charmes | ff67da9 | 2013-05-09 23:28:47 | [diff] [blame] | 575 | } |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 576 | name := vars["name"] |
| 577 | status, err := srv.ContainerWait(name) |
| 578 | if err != nil { |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 579 | return err |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 580 | } |
| Victor Vieux | fd224ee | 2013-06-04 18:00:22 | [diff] [blame] | 581 | b, err := json.Marshal(&APIWait{StatusCode: status}) |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 582 | if err != nil { |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 583 | return err |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 584 | } |
| Victor Vieux | fd224ee | 2013-06-04 18:00:22 | [diff] [blame] | 585 | writeJSON(w, b) |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 586 | return nil |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 587 | } |
| 588 | |
| Guillaume J. Charmes | 70d2123 | 2013-05-24 02:33:28 | [diff] [blame] | 589 | func 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 Vieux | faae722 | 2013-05-22 15:29:54 | [diff] [blame] | 611 | func postContainersAttach(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error { |
| Victor Vieux | 954ecac | 2013-05-08 16:52:01 | [diff] [blame] | 612 | if err := parseForm(r); err != nil { |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 613 | return err |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 614 | } |
| Victor Vieux | 0c54435 | 2013-05-16 13:45:29 | [diff] [blame] | 615 | 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. Charmes | ff67da9 | 2013-05-09 23:28:47 | [diff] [blame] | 636 | if vars == nil { |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 637 | return fmt.Errorf("Missing parameter") |
| Guillaume J. Charmes | ff67da9 | 2013-05-09 23:28:47 | [diff] [blame] | 638 | } |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 639 | name := vars["name"] |
| 640 | |
| Victor Vieux | e5fa4a4 | 2013-05-28 16:19:12 | [diff] [blame] | 641 | if _, err := srv.ContainerInspect(name); err != nil { |
| 642 | return err |
| 643 | } |
| 644 | |
| Guillaume J. Charmes | 57cfe72 | 2013-05-08 01:06:49 | [diff] [blame] | 645 | in, out, err := hijackServer(w) |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 646 | if err != nil { |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 647 | return err |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 648 | } |
| Guillaume J. Charmes | cacc7e5 | 2013-05-08 06:32:17 | [diff] [blame] | 649 | defer in.Close() |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 650 | |
| Victor Vieux | 4a1e0d3 | 2013-05-08 16:36:37 | [diff] [blame] | 651 | fmt.Fprintf(out, "HTTP/1.1 200 OK\r\nContent-Type: application/vnd.docker.raw-stream\r\n\r\n") |
| Guillaume J. Charmes | 57cfe72 | 2013-05-08 01:06:49 | [diff] [blame] | 652 | if err := srv.ContainerAttach(name, logs, stream, stdin, stdout, stderr, in, out); err != nil { |
| 653 | fmt.Fprintf(out, "Error: %s\n", err) |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 654 | } |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 655 | return nil |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 656 | } |
| 657 | |
| Victor Vieux | faae722 | 2013-05-22 15:29:54 | [diff] [blame] | 658 | func getContainersByName(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error { |
| Guillaume J. Charmes | ff67da9 | 2013-05-09 23:28:47 | [diff] [blame] | 659 | if vars == nil { |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 660 | return fmt.Errorf("Missing parameter") |
| Guillaume J. Charmes | ff67da9 | 2013-05-09 23:28:47 | [diff] [blame] | 661 | } |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 662 | name := vars["name"] |
| 663 | |
| 664 | container, err := srv.ContainerInspect(name) |
| 665 | if err != nil { |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 666 | return err |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 667 | } |
| 668 | b, err := json.Marshal(container) |
| 669 | if err != nil { |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 670 | return err |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 671 | } |
| Victor Vieux | fd224ee | 2013-06-04 18:00:22 | [diff] [blame] | 672 | writeJSON(w, b) |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 673 | return nil |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 674 | } |
| 675 | |
| Victor Vieux | faae722 | 2013-05-22 15:29:54 | [diff] [blame] | 676 | func getImagesByName(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error { |
| Guillaume J. Charmes | ff67da9 | 2013-05-09 23:28:47 | [diff] [blame] | 677 | if vars == nil { |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 678 | return fmt.Errorf("Missing parameter") |
| Guillaume J. Charmes | ff67da9 | 2013-05-09 23:28:47 | [diff] [blame] | 679 | } |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 680 | name := vars["name"] |
| 681 | |
| 682 | image, err := srv.ImageInspect(name) |
| 683 | if err != nil { |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 684 | return err |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 685 | } |
| 686 | b, err := json.Marshal(image) |
| 687 | if err != nil { |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 688 | return err |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 689 | } |
| Victor Vieux | fd224ee | 2013-06-04 18:00:22 | [diff] [blame] | 690 | writeJSON(w, b) |
| Victor Vieux | 7cc0823 | 2013-05-10 18:20:49 | [diff] [blame] | 691 | return nil |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 692 | } |
| 693 | |
| Victor Vieux | faae722 | 2013-05-22 15:29:54 | [diff] [blame] | 694 | func postImagesGetCache(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error { |
| Victor Vieux | fd224ee | 2013-06-04 18:00:22 | [diff] [blame] | 695 | apiConfig := &APIImageConfig{} |
| Guillaume J. Charmes | 0f31211 | 2013-05-19 17:46:24 | [diff] [blame] | 696 | if err := json.NewDecoder(r.Body).Decode(apiConfig); err != nil { |
| 697 | return err |
| 698 | } |
| 699 | |
| Victor Vieux | fd224ee | 2013-06-04 18:00:22 | [diff] [blame] | 700 | image, err := srv.ImageGetCached(apiConfig.ID, apiConfig.Config) |
| Guillaume J. Charmes | 0f31211 | 2013-05-19 17:46:24 | [diff] [blame] | 701 | if err != nil { |
| 702 | return err |
| 703 | } |
| Guillaume J. Charmes | c2a14bb | 2013-05-20 19:09:15 | [diff] [blame] | 704 | if image == nil { |
| 705 | w.WriteHeader(http.StatusNotFound) |
| 706 | return nil |
| 707 | } |
| Victor Vieux | fd224ee | 2013-06-04 18:00:22 | [diff] [blame] | 708 | apiID := &APIID{ID: image.ID} |
| 709 | b, err := json.Marshal(apiID) |
| Guillaume J. Charmes | 0f31211 | 2013-05-19 17:46:24 | [diff] [blame] | 710 | if err != nil { |
| 711 | return err |
| 712 | } |
| Victor Vieux | fd224ee | 2013-06-04 18:00:22 | [diff] [blame] | 713 | writeJSON(w, b) |
| Guillaume J. Charmes | 0f31211 | 2013-05-19 17:46:24 | [diff] [blame] | 714 | return nil |
| 715 | } |
| 716 | |
| Guillaume J. Charmes | a487990 | 2013-05-28 20:46:52 | [diff] [blame] | 717 | func postBuild(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error { |
| Guillaume J. Charmes | d42c10a | 2013-05-24 01:32:56 | [diff] [blame] | 718 | if err := r.ParseMultipartForm(4096); err != nil { |
| Guillaume J. Charmes | 0f135ad | 2013-05-23 03:07:26 | [diff] [blame] | 719 | return err |
| 720 | } |
| Guillaume J. Charmes | 56431d3 | 2013-05-30 19:08:21 | [diff] [blame] | 721 | 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. Charmes | 0f135ad | 2013-05-23 03:07:26 | [diff] [blame] | 728 | |
| Guillaume J. Charmes | fe0c0c2 | 2013-05-28 22:21:06 | [diff] [blame] | 729 | dockerfile, _, err := r.FormFile("Dockerfile") |
| Guillaume J. Charmes | 0f135ad | 2013-05-23 03:07:26 | [diff] [blame] | 730 | if err != nil { |
| 731 | return err |
| 732 | } |
| 733 | |
| Guillaume J. Charmes | d42c10a | 2013-05-24 01:32:56 | [diff] [blame] | 734 | context, _, err := r.FormFile("Context") |
| Guillaume J. Charmes | 0f135ad | 2013-05-23 03:07:26 | [diff] [blame] | 735 | if err != nil { |
| Guillaume J. Charmes | d42c10a | 2013-05-24 01:32:56 | [diff] [blame] | 736 | if err != http.ErrMissingFile { |
| 737 | return err |
| 738 | } |
| Guillaume J. Charmes | 0f135ad | 2013-05-23 03:07:26 | [diff] [blame] | 739 | } |
| 740 | |
| Guillaume J. Charmes | 582a9e0 | 2013-05-28 20:47:04 | [diff] [blame] | 741 | b := NewBuildFile(srv, utils.NewWriteFlusher(w)) |
| Guillaume J. Charmes | 56431d3 | 2013-05-30 19:08:21 | [diff] [blame] | 742 | if id, err := b.Build(dockerfile, context); err != nil { |
| Guillaume J. Charmes | fe0c0c2 | 2013-05-28 22:21:06 | [diff] [blame] | 743 | fmt.Fprintf(w, "Error build: %s\n", err) |
| Guillaume J. Charmes | 56431d3 | 2013-05-30 19:08:21 | [diff] [blame] | 744 | } else if remote != "" { |
| 745 | srv.runtime.repositories.Set(remote, tag, id, false) |
| Guillaume J. Charmes | 0f135ad | 2013-05-23 03:07:26 | [diff] [blame] | 746 | } |
| 747 | return nil |
| 748 | } |
| 749 | |
| Michael Crosby | dd53c45 | 2013-06-11 01:10:40 | [diff] [blame] | 750 | func 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 Crosby | 6d5bdff | 2013-06-04 01:39:00 | [diff] [blame] | 754 | func 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 Crosby | 393e873 | 2013-06-10 02:17:35 | [diff] [blame] | 757 | w.Header().Add("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT, OPTIONS") |
| Michael Crosby | 6d5bdff | 2013-06-04 01:39:00 | [diff] [blame] | 758 | } |
| 759 | |
| Michael Crosby | 0a28628 | 2013-06-10 22:02:40 | [diff] [blame] | 760 | func createRouter(srv *Server, logging bool) (*mux.Router, error) { |
| Victor Vieux | c0d5d59 | 2013-04-18 01:13:43 | [diff] [blame] | 761 | r := mux.NewRouter() |
| Solomon Hykes | a11b313 | 2013-04-11 02:48:21 | [diff] [blame] | 762 | |
| Victor Vieux | faae722 | 2013-05-22 15:29:54 | [diff] [blame] | 763 | m := map[string]map[string]func(*Server, float64, http.ResponseWriter, *http.Request, map[string]string) error{ |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 764 | "GET": { |
| Victor Vieux | 3dd1e4d | 2013-06-03 12:09:16 | [diff] [blame] | 765 | "/auth": getAuth, |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 766 | "/version": getVersion, |
| Guillaume J. Charmes | 152ebee | 2013-05-10 00:50:56 | [diff] [blame] | 767 | "/info": getInfo, |
| Victor Vieux | fd224ee | 2013-06-04 18:00:22 | [diff] [blame] | 768 | "/images/json": getImagesJSON, |
| Victor Vieux | c423a79 | 2013-05-09 21:52:12 | [diff] [blame] | 769 | "/images/viz": getImagesViz, |
| Victor Vieux | 60ddcaa | 2013-05-08 15:35:50 | [diff] [blame] | 770 | "/images/search": getImagesSearch, |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 771 | "/images/{name:.*}/history": getImagesHistory, |
| Victor Vieux | 60ddcaa | 2013-05-08 15:35:50 | [diff] [blame] | 772 | "/images/{name:.*}/json": getImagesByName, |
| Victor Vieux | fd224ee | 2013-06-04 18:00:22 | [diff] [blame] | 773 | "/containers/ps": getContainersJSON, |
| 774 | "/containers/json": getContainersJSON, |
| Guillaume J. Charmes | 152ebee | 2013-05-10 00:50:56 | [diff] [blame] | 775 | "/containers/{name:.*}/export": getContainersExport, |
| 776 | "/containers/{name:.*}/changes": getContainersChanges, |
| Victor Vieux | 60ddcaa | 2013-05-08 15:35:50 | [diff] [blame] | 777 | "/containers/{name:.*}/json": getContainersByName, |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 778 | }, |
| 779 | "POST": { |
| Guillaume J. Charmes | 152ebee | 2013-05-10 00:50:56 | [diff] [blame] | 780 | "/auth": postAuth, |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 781 | "/commit": postCommit, |
| Guillaume J. Charmes | 0f135ad | 2013-05-23 03:07:26 | [diff] [blame] | 782 | "/build": postBuild, |
| Guillaume J. Charmes | 152ebee | 2013-05-10 00:50:56 | [diff] [blame] | 783 | "/images/create": postImagesCreate, |
| Guillaume J. Charmes | 1941c79 | 2013-05-10 05:28:52 | [diff] [blame] | 784 | "/images/{name:.*}/insert": postImagesInsert, |
| 785 | "/images/{name:.*}/push": postImagesPush, |
| Guillaume J. Charmes | 152ebee | 2013-05-10 00:50:56 | [diff] [blame] | 786 | "/images/{name:.*}/tag": postImagesTag, |
| Guillaume J. Charmes | 0f31211 | 2013-05-19 17:46:24 | [diff] [blame] | 787 | "/images/getCache": postImagesGetCache, |
| Guillaume J. Charmes | 152ebee | 2013-05-10 00:50:56 | [diff] [blame] | 788 | "/containers/create": postContainersCreate, |
| 789 | "/containers/{name:.*}/kill": postContainersKill, |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 790 | "/containers/{name:.*}/restart": postContainersRestart, |
| 791 | "/containers/{name:.*}/start": postContainersStart, |
| 792 | "/containers/{name:.*}/stop": postContainersStop, |
| 793 | "/containers/{name:.*}/wait": postContainersWait, |
| Guillaume J. Charmes | 70d2123 | 2013-05-24 02:33:28 | [diff] [blame] | 794 | "/containers/{name:.*}/resize": postContainersResize, |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 795 | "/containers/{name:.*}/attach": postContainersAttach, |
| 796 | }, |
| 797 | "DELETE": { |
| 798 | "/containers/{name:.*}": deleteContainers, |
| 799 | "/images/{name:.*}": deleteImages, |
| 800 | }, |
| Michael Crosby | dd53c45 | 2013-06-11 01:10:40 | [diff] [blame] | 801 | "OPTIONS": { |
| 802 | "": optionsHandler, |
| 803 | }, |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 804 | } |
| Victor Vieux | f37399d | 2013-05-06 11:34:31 | [diff] [blame] | 805 | |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 806 | for method, routes := range m { |
| 807 | for route, fct := range routes { |
| Guillaume J. Charmes | 2e69e17 | 2013-05-14 22:37:35 | [diff] [blame] | 808 | utils.Debugf("Registering %s, %s", method, route) |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 809 | // NOTE: scope issue, make sure the variables are local and won't be changed |
| 810 | localRoute := route |
| 811 | localMethod := method |
| 812 | localFct := fct |
| Victor Vieux | faae722 | 2013-05-22 15:29:54 | [diff] [blame] | 813 | f := func(w http.ResponseWriter, r *http.Request) { |
| Guillaume J. Charmes | 2e69e17 | 2013-05-14 22:37:35 | [diff] [blame] | 814 | utils.Debugf("Calling %s %s", localMethod, localRoute) |
| Victor Vieux | c423a79 | 2013-05-09 21:52:12 | [diff] [blame] | 815 | if logging { |
| 816 | log.Println(r.Method, r.RequestURI) |
| 817 | } |
| Victor Vieux | 7c7619e | 2013-05-09 18:24:49 | [diff] [blame] | 818 | 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. Charmes | 2e69e17 | 2013-05-14 22:37:35 | [diff] [blame] | 821 | utils.Debugf("Warning: client and server don't have the same version (client: %s, server: %s)", userAgent[1], VERSION) |
| Victor Vieux | 7c7619e | 2013-05-09 18:24:49 | [diff] [blame] | 822 | } |
| 823 | } |
| Victor Vieux | faae722 | 2013-05-22 15:29:54 | [diff] [blame] | 824 | version, err := strconv.ParseFloat(mux.Vars(r)["version"], 64) |
| 825 | if err != nil { |
| Victor Vieux | fd224ee | 2013-06-04 18:00:22 | [diff] [blame] | 826 | version = APIVERSION |
| Victor Vieux | faae722 | 2013-05-22 15:29:54 | [diff] [blame] | 827 | } |
| Michael Crosby | 393e873 | 2013-06-10 02:17:35 | [diff] [blame] | 828 | if srv.enableCors { |
| 829 | writeCorsHeaders(w, r) |
| 830 | } |
| Victor Vieux | fd224ee | 2013-06-04 18:00:22 | [diff] [blame] | 831 | if version == 0 || version > APIVERSION { |
| Victor Vieux | faae722 | 2013-05-22 15:29:54 | [diff] [blame] | 832 | w.WriteHeader(http.StatusNotFound) |
| 833 | return |
| 834 | } |
| 835 | if err := localFct(srv, version, w, r, mux.Vars(r)); err != nil { |
| Guillaume J. Charmes | 891c520 | 2013-05-08 00:27:09 | [diff] [blame] | 836 | httpError(w, err) |
| 837 | } |
| Victor Vieux | faae722 | 2013-05-22 15:29:54 | [diff] [blame] | 838 | } |
| Michael Crosby | dd53c45 | 2013-06-11 01:10:40 | [diff] [blame] | 839 | |
| 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 Vieux | f37399d | 2013-05-06 11:34:31 | [diff] [blame] | 846 | } |
| Guillaume J. Charmes | b56b2da | 2013-05-07 23:33:12 | [diff] [blame] | 847 | } |
| Michael Crosby | 0a28628 | 2013-06-10 22:02:40 | [diff] [blame] | 848 | return r, nil |
| 849 | } |
| 850 | |
| 851 | func 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 Vieux | c0d5d59 | 2013-04-18 01:13:43 | [diff] [blame] | 858 | return http.ListenAndServe(addr, r) |
| Solomon Hykes | a11b313 | 2013-04-11 02:48:21 | [diff] [blame] | 859 | } |