... | ... |
@@ -40,86 +40,118 @@ func httpError(w http.ResponseWriter, err error) { |
40 | 40 |
} |
41 | 41 |
} |
42 | 42 |
|
43 |
-func ListenAndServe(addr string, srv *Server) error { |
|
44 |
- r := mux.NewRouter() |
|
45 |
- log.Printf("Listening for HTTP on %s\n", addr) |
|
43 |
+func getAuth(srv *Server, w http.ResponseWriter, r *http.Request) error { |
|
44 |
+ log.Println(r.Method, r.RequestURI) |
|
45 |
+ var out auth.AuthConfig |
|
46 |
+ out.Username = srv.runtime.authConfig.Username |
|
47 |
+ out.Email = srv.runtime.authConfig.Email |
|
48 |
+ b, err := json.Marshal(out) |
|
49 |
+ if err != nil { |
|
50 |
+ http.Error(w, err.Error(), http.StatusInternalServerError) |
|
51 |
+ return err |
|
52 |
+ } else { |
|
53 |
+ w.Header().Set("Content-Type", "application/json") |
|
54 |
+ w.Write(b) |
|
55 |
+ } |
|
56 |
+ return nil |
|
57 |
+} |
|
58 |
+ |
|
59 |
+func postAuth(srv *Server, w http.ResponseWriter, r *http.Request) error { |
|
60 |
+ log.Println(r.Method, r.RequestURI) |
|
61 |
+ var config auth.AuthConfig |
|
62 |
+ if err := json.NewDecoder(r.Body).Decode(&config); err != nil { |
|
63 |
+ http.Error(w, err.Error(), http.StatusInternalServerError) |
|
64 |
+ return err |
|
65 |
+ } |
|
46 | 66 |
|
47 |
- r.Path("/auth").Methods("GET").HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
|
48 |
- log.Println(r.Method, r.RequestURI) |
|
49 |
- var out auth.AuthConfig |
|
50 |
- out.Username = srv.runtime.authConfig.Username |
|
51 |
- out.Email = srv.runtime.authConfig.Email |
|
52 |
- b, err := json.Marshal(out) |
|
67 |
+ if config.Username == srv.runtime.authConfig.Username { |
|
68 |
+ config.Password = srv.runtime.authConfig.Password |
|
69 |
+ } |
|
70 |
+ |
|
71 |
+ newAuthConfig := auth.NewAuthConfig(config.Username, config.Password, config.Email, srv.runtime.root) |
|
72 |
+ status, err := auth.Login(newAuthConfig) |
|
73 |
+ if err != nil { |
|
74 |
+ http.Error(w, err.Error(), http.StatusInternalServerError) |
|
75 |
+ return err |
|
76 |
+ } else { |
|
77 |
+ srv.runtime.graph.getHttpClient().Jar = cookiejar.NewCookieJar() |
|
78 |
+ srv.runtime.authConfig = newAuthConfig |
|
79 |
+ } |
|
80 |
+ if status != "" { |
|
81 |
+ b, err := json.Marshal(ApiAuth{status}) |
|
53 | 82 |
if err != nil { |
54 | 83 |
http.Error(w, err.Error(), http.StatusInternalServerError) |
84 |
+ return err |
|
55 | 85 |
} else { |
56 | 86 |
w.Header().Set("Content-Type", "application/json") |
57 | 87 |
w.Write(b) |
58 | 88 |
} |
59 |
- }) |
|
60 |
- |
|
61 |
- r.Path("/auth").Methods("POST").HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
|
62 |
- log.Println(r.Method, r.RequestURI) |
|
63 |
- var config auth.AuthConfig |
|
64 |
- if err := json.NewDecoder(r.Body).Decode(&config); err != nil { |
|
65 |
- http.Error(w, err.Error(), http.StatusInternalServerError) |
|
66 |
- return |
|
67 |
- } |
|
89 |
+ } else { |
|
90 |
+ w.WriteHeader(http.StatusOK) |
|
91 |
+ } |
|
92 |
+ return nil |
|
93 |
+} |
|
68 | 94 |
|
69 |
- if config.Username == srv.runtime.authConfig.Username { |
|
70 |
- config.Password = srv.runtime.authConfig.Password |
|
71 |
- } |
|
95 |
+func getVersion(srv *Server, w http.ResponseWriter, r *http.Request) error { |
|
96 |
+ log.Println(r.Method, r.RequestURI) |
|
97 |
+ m := srv.DockerVersion() |
|
98 |
+ b, err := json.Marshal(m) |
|
99 |
+ if err != nil { |
|
100 |
+ http.Error(w, err.Error(), http.StatusInternalServerError) |
|
101 |
+ return err |
|
102 |
+ } else { |
|
103 |
+ w.Header().Set("Content-Type", "application/json") |
|
104 |
+ w.Write(b) |
|
105 |
+ } |
|
106 |
+ return nil |
|
107 |
+} |
|
72 | 108 |
|
73 |
- newAuthConfig := auth.NewAuthConfig(config.Username, config.Password, config.Email, srv.runtime.root) |
|
74 |
- status, err := auth.Login(newAuthConfig) |
|
75 |
- if err != nil { |
|
76 |
- http.Error(w, err.Error(), http.StatusInternalServerError) |
|
77 |
- return |
|
78 |
- } else { |
|
79 |
- srv.runtime.graph.getHttpClient().Jar = cookiejar.NewCookieJar() |
|
80 |
- srv.runtime.authConfig = newAuthConfig |
|
81 |
- } |
|
82 |
- if status != "" { |
|
83 |
- b, err := json.Marshal(ApiAuth{status}) |
|
84 |
- if err != nil { |
|
85 |
- http.Error(w, err.Error(), http.StatusInternalServerError) |
|
86 |
- } else { |
|
87 |
- w.Header().Set("Content-Type", "application/json") |
|
88 |
- w.Write(b) |
|
89 |
- } |
|
90 |
- } else { |
|
91 |
- w.WriteHeader(http.StatusOK) |
|
92 |
- } |
|
93 |
- }) |
|
109 |
+func postContainersKill(srv *Server, w http.ResponseWriter, r *http.Request) error { |
|
110 |
+ log.Println(r.Method, r.RequestURI) |
|
111 |
+ vars := mux.Vars(r) |
|
112 |
+ name := vars["name"] |
|
113 |
+ if err := srv.ContainerKill(name); err != nil { |
|
114 |
+ httpError(w, err) |
|
115 |
+ return err |
|
116 |
+ } else { |
|
117 |
+ w.WriteHeader(http.StatusOK) |
|
118 |
+ } |
|
119 |
+ return nil |
|
120 |
+} |
|
94 | 121 |
|
95 |
- r.Path("/version").Methods("GET").HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
|
96 |
- log.Println(r.Method, r.RequestURI) |
|
97 |
- m := srv.DockerVersion() |
|
98 |
- b, err := json.Marshal(m) |
|
99 |
- if err != nil { |
|
100 |
- http.Error(w, err.Error(), http.StatusInternalServerError) |
|
101 |
- } else { |
|
102 |
- w.Header().Set("Content-Type", "application/json") |
|
103 |
- w.Write(b) |
|
104 |
- } |
|
105 |
- }) |
|
122 |
+func getContainersExport(srv *Server, w http.ResponseWriter, r *http.Request) error { |
|
123 |
+ log.Println(r.Method, r.RequestURI) |
|
124 |
+ vars := mux.Vars(r) |
|
125 |
+ name := vars["name"] |
|
106 | 126 |
|
107 |
- r.Path("/containers/{name:.*}/kill").Methods("POST").HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
|
108 |
- log.Println(r.Method, r.RequestURI) |
|
109 |
- vars := mux.Vars(r) |
|
110 |
- name := vars["name"] |
|
111 |
- if err := srv.ContainerKill(name); err != nil { |
|
112 |
- httpError(w, err) |
|
113 |
- } else { |
|
114 |
- w.WriteHeader(http.StatusOK) |
|
115 |
- } |
|
116 |
- }) |
|
127 |
+ file, rwc, err := hijackServer(w) |
|
128 |
+ if file != nil { |
|
129 |
+ defer file.Close() |
|
130 |
+ } |
|
131 |
+ if rwc != nil { |
|
132 |
+ defer rwc.Close() |
|
133 |
+ } |
|
134 |
+ if err != nil { |
|
135 |
+ httpError(w, err) |
|
136 |
+ return err |
|
137 |
+ } |
|
138 |
+ fmt.Fprintf(file, "HTTP/1.1 200 OK\r\nContent-Type: raw-stream-hijack\r\n\r\n") |
|
139 |
+ if err := srv.ContainerExport(name, file); err != nil { |
|
140 |
+ fmt.Fprintf(file, "Error: %s\n", err) |
|
141 |
+ return err |
|
142 |
+ } |
|
143 |
+ return nil |
|
144 |
+} |
|
117 | 145 |
|
118 |
- r.Path("/containers/{name:.*}/export").Methods("GET").HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
|
119 |
- log.Println(r.Method, r.RequestURI) |
|
120 |
- vars := mux.Vars(r) |
|
121 |
- name := vars["name"] |
|
146 |
+func getImages(srv *Server, w http.ResponseWriter, r *http.Request) error { |
|
147 |
+ log.Println(r.Method, r.RequestURI) |
|
148 |
+ if err := r.ParseForm(); err != nil { |
|
149 |
+ http.Error(w, err.Error(), http.StatusInternalServerError) |
|
150 |
+ return err |
|
151 |
+ } |
|
122 | 152 |
|
153 |
+ viz := r.Form.Get("viz") |
|
154 |
+ if viz == "1" { |
|
123 | 155 |
file, rwc, err := hijackServer(w) |
124 | 156 |
if file != nil { |
125 | 157 |
defer file.Close() |
... | ... |
@@ -129,537 +161,615 @@ func ListenAndServe(addr string, srv *Server) error { |
129 | 129 |
} |
130 | 130 |
if err != nil { |
131 | 131 |
httpError(w, err) |
132 |
- return |
|
132 |
+ return err |
|
133 | 133 |
} |
134 | 134 |
fmt.Fprintf(file, "HTTP/1.1 200 OK\r\nContent-Type: raw-stream-hijack\r\n\r\n") |
135 |
- if err := srv.ContainerExport(name, file); err != nil { |
|
136 |
- fmt.Fprintln(file, "Error: "+err.Error()) |
|
135 |
+ if err := srv.ImagesViz(file); err != nil { |
|
136 |
+ fmt.Fprintf(file, "Error: %s\n", err) |
|
137 | 137 |
} |
138 |
- }) |
|
138 |
+ return nil |
|
139 |
+ } |
|
139 | 140 |
|
140 |
- r.Path("/images").Methods("GET").HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
|
141 |
- log.Println(r.Method, r.RequestURI) |
|
142 |
- if err := r.ParseForm(); err != nil { |
|
143 |
- http.Error(w, err.Error(), http.StatusInternalServerError) |
|
144 |
- return |
|
145 |
- } |
|
141 |
+ all := r.Form.Get("all") |
|
142 |
+ filter := r.Form.Get("filter") |
|
143 |
+ quiet := r.Form.Get("quiet") |
|
146 | 144 |
|
147 |
- viz := r.Form.Get("viz") |
|
148 |
- if viz == "1" { |
|
149 |
- file, rwc, err := hijackServer(w) |
|
150 |
- if file != nil { |
|
151 |
- defer file.Close() |
|
152 |
- } |
|
153 |
- if rwc != nil { |
|
154 |
- defer rwc.Close() |
|
155 |
- } |
|
156 |
- if err != nil { |
|
157 |
- httpError(w, err) |
|
158 |
- return |
|
159 |
- } |
|
160 |
- fmt.Fprintf(file, "HTTP/1.1 200 OK\r\nContent-Type: raw-stream-hijack\r\n\r\n") |
|
161 |
- if err := srv.ImagesViz(file); err != nil { |
|
162 |
- fmt.Fprintln(file, "Error: "+err.Error()) |
|
163 |
- } |
|
164 |
- return |
|
165 |
- } |
|
145 |
+ outs, err := srv.Images(all, filter, quiet) |
|
146 |
+ if err != nil { |
|
147 |
+ httpError(w, err) |
|
148 |
+ return err |
|
149 |
+ } |
|
150 |
+ b, err := json.Marshal(outs) |
|
151 |
+ if err != nil { |
|
152 |
+ http.Error(w, err.Error(), http.StatusInternalServerError) |
|
153 |
+ return err |
|
154 |
+ } else { |
|
155 |
+ w.Header().Set("Content-Type", "application/json") |
|
156 |
+ w.Write(b) |
|
157 |
+ } |
|
158 |
+ return nil |
|
159 |
+} |
|
166 | 160 |
|
167 |
- all := r.Form.Get("all") |
|
168 |
- filter := r.Form.Get("filter") |
|
169 |
- quiet := r.Form.Get("quiet") |
|
161 |
+func getInfo(srv *Server, w http.ResponseWriter, r *http.Request) error { |
|
162 |
+ log.Println(r.Method, r.RequestURI) |
|
163 |
+ out := srv.DockerInfo() |
|
164 |
+ b, err := json.Marshal(out) |
|
165 |
+ if err != nil { |
|
166 |
+ http.Error(w, err.Error(), http.StatusInternalServerError) |
|
167 |
+ return err |
|
168 |
+ } else { |
|
169 |
+ w.Header().Set("Content-Type", "application/json") |
|
170 |
+ w.Write(b) |
|
171 |
+ } |
|
172 |
+ return nil |
|
173 |
+} |
|
170 | 174 |
|
171 |
- outs, err := srv.Images(all, filter, quiet) |
|
172 |
- if err != nil { |
|
173 |
- httpError(w, err) |
|
174 |
- return |
|
175 |
- } |
|
176 |
- b, err := json.Marshal(outs) |
|
177 |
- if err != nil { |
|
178 |
- http.Error(w, err.Error(), http.StatusInternalServerError) |
|
179 |
- } else { |
|
180 |
- w.Header().Set("Content-Type", "application/json") |
|
181 |
- w.Write(b) |
|
182 |
- } |
|
183 |
- }) |
|
175 |
+func getImagesHistory(srv *Server, w http.ResponseWriter, r *http.Request) error { |
|
176 |
+ log.Println(r.Method, r.RequestURI) |
|
177 |
+ vars := mux.Vars(r) |
|
178 |
+ name := vars["name"] |
|
179 |
+ outs, err := srv.ImageHistory(name) |
|
180 |
+ if err != nil { |
|
181 |
+ httpError(w, err) |
|
182 |
+ return err |
|
183 |
+ } |
|
184 |
+ b, err := json.Marshal(outs) |
|
185 |
+ if err != nil { |
|
186 |
+ http.Error(w, err.Error(), http.StatusInternalServerError) |
|
187 |
+ return err |
|
188 |
+ } else { |
|
189 |
+ w.Header().Set("Content-Type", "application/json") |
|
190 |
+ w.Write(b) |
|
191 |
+ } |
|
192 |
+ return nil |
|
193 |
+} |
|
184 | 194 |
|
185 |
- r.Path("/info").Methods("GET").HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
|
186 |
- log.Println(r.Method, r.RequestURI) |
|
187 |
- out := srv.DockerInfo() |
|
188 |
- b, err := json.Marshal(out) |
|
189 |
- if err != nil { |
|
190 |
- http.Error(w, err.Error(), http.StatusInternalServerError) |
|
191 |
- } else { |
|
192 |
- w.Header().Set("Content-Type", "application/json") |
|
193 |
- w.Write(b) |
|
194 |
- } |
|
195 |
- }) |
|
195 |
+func getContainersChanges(srv *Server, w http.ResponseWriter, r *http.Request) error { |
|
196 |
+ log.Println(r.Method, r.RequestURI) |
|
197 |
+ vars := mux.Vars(r) |
|
198 |
+ name := vars["name"] |
|
199 |
+ changesStr, err := srv.ContainerChanges(name) |
|
200 |
+ if err != nil { |
|
201 |
+ httpError(w, err) |
|
202 |
+ return err |
|
203 |
+ } |
|
204 |
+ b, err := json.Marshal(changesStr) |
|
205 |
+ if err != nil { |
|
206 |
+ http.Error(w, err.Error(), http.StatusInternalServerError) |
|
207 |
+ return err |
|
208 |
+ } else { |
|
209 |
+ w.Header().Set("Content-Type", "application/json") |
|
210 |
+ w.Write(b) |
|
211 |
+ } |
|
212 |
+ return nil |
|
213 |
+} |
|
196 | 214 |
|
197 |
- r.Path("/images/{name:.*}/history").Methods("GET").HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
|
198 |
- log.Println(r.Method, r.RequestURI) |
|
199 |
- vars := mux.Vars(r) |
|
200 |
- name := vars["name"] |
|
201 |
- outs, err := srv.ImageHistory(name) |
|
202 |
- if err != nil { |
|
203 |
- httpError(w, err) |
|
204 |
- return |
|
205 |
- } |
|
206 |
- b, err := json.Marshal(outs) |
|
207 |
- if err != nil { |
|
208 |
- http.Error(w, err.Error(), http.StatusInternalServerError) |
|
209 |
- } else { |
|
210 |
- w.Header().Set("Content-Type", "application/json") |
|
211 |
- w.Write(b) |
|
212 |
- } |
|
213 |
- }) |
|
215 |
+func getContainersPort(srv *Server, w http.ResponseWriter, r *http.Request) error { |
|
216 |
+ log.Println(r.Method, r.RequestURI) |
|
217 |
+ if err := r.ParseForm(); err != nil { |
|
218 |
+ http.Error(w, err.Error(), http.StatusInternalServerError) |
|
219 |
+ return err |
|
220 |
+ } |
|
221 |
+ vars := mux.Vars(r) |
|
222 |
+ name := vars["name"] |
|
223 |
+ out, err := srv.ContainerPort(name, r.Form.Get("port")) |
|
224 |
+ if err != nil { |
|
225 |
+ httpError(w, err) |
|
226 |
+ return err |
|
227 |
+ } |
|
228 |
+ b, err := json.Marshal(ApiPort{out}) |
|
229 |
+ if err != nil { |
|
230 |
+ http.Error(w, err.Error(), http.StatusInternalServerError) |
|
231 |
+ return err |
|
232 |
+ } else { |
|
233 |
+ w.Header().Set("Content-Type", "application/json") |
|
234 |
+ w.Write(b) |
|
235 |
+ } |
|
236 |
+ return nil |
|
237 |
+} |
|
214 | 238 |
|
215 |
- r.Path("/containers/{name:.*}/changes").Methods("GET").HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
|
216 |
- log.Println(r.Method, r.RequestURI) |
|
217 |
- vars := mux.Vars(r) |
|
218 |
- name := vars["name"] |
|
219 |
- changesStr, err := srv.ContainerChanges(name) |
|
220 |
- if err != nil { |
|
221 |
- httpError(w, err) |
|
222 |
- return |
|
223 |
- } |
|
224 |
- b, err := json.Marshal(changesStr) |
|
225 |
- if err != nil { |
|
226 |
- http.Error(w, err.Error(), http.StatusInternalServerError) |
|
227 |
- } else { |
|
228 |
- w.Header().Set("Content-Type", "application/json") |
|
229 |
- w.Write(b) |
|
230 |
- } |
|
231 |
- }) |
|
239 |
+func getContainers(srv *Server, w http.ResponseWriter, r *http.Request) error { |
|
240 |
+ log.Println(r.Method, r.RequestURI) |
|
241 |
+ if err := r.ParseForm(); err != nil { |
|
242 |
+ http.Error(w, err.Error(), http.StatusInternalServerError) |
|
243 |
+ return err |
|
244 |
+ } |
|
245 |
+ all := r.Form.Get("all") |
|
246 |
+ notrunc := r.Form.Get("notrunc") |
|
247 |
+ quiet := r.Form.Get("quiet") |
|
248 |
+ n, err := strconv.Atoi(r.Form.Get("n")) |
|
249 |
+ if err != nil { |
|
250 |
+ n = -1 |
|
251 |
+ } |
|
232 | 252 |
|
233 |
- r.Path("/containers/{name:.*}/port").Methods("GET").HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
|
234 |
- log.Println(r.Method, r.RequestURI) |
|
235 |
- if err := r.ParseForm(); err != nil { |
|
236 |
- http.Error(w, err.Error(), http.StatusInternalServerError) |
|
237 |
- return |
|
238 |
- } |
|
239 |
- vars := mux.Vars(r) |
|
240 |
- name := vars["name"] |
|
241 |
- out, err := srv.ContainerPort(name, r.Form.Get("port")) |
|
242 |
- if err != nil { |
|
243 |
- httpError(w, err) |
|
244 |
- return |
|
245 |
- } |
|
246 |
- b, err := json.Marshal(ApiPort{out}) |
|
247 |
- if err != nil { |
|
248 |
- http.Error(w, err.Error(), http.StatusInternalServerError) |
|
249 |
- } else { |
|
250 |
- w.Header().Set("Content-Type", "application/json") |
|
251 |
- w.Write(b) |
|
252 |
- } |
|
253 |
+ outs := srv.Containers(all, notrunc, quiet, n) |
|
254 |
+ b, err := json.Marshal(outs) |
|
255 |
+ if err != nil { |
|
256 |
+ http.Error(w, err.Error(), http.StatusInternalServerError) |
|
257 |
+ return err |
|
258 |
+ } else { |
|
259 |
+ w.Header().Set("Content-Type", "application/json") |
|
260 |
+ w.Write(b) |
|
261 |
+ } |
|
262 |
+ return nil |
|
263 |
+} |
|
253 | 264 |
|
254 |
- }) |
|
265 |
+func postImagesTag(srv *Server, w http.ResponseWriter, r *http.Request) error { |
|
266 |
+ log.Println(r.Method, r.RequestURI) |
|
267 |
+ if err := r.ParseForm(); err != nil { |
|
268 |
+ http.Error(w, err.Error(), http.StatusInternalServerError) |
|
269 |
+ return err |
|
270 |
+ } |
|
271 |
+ repo := r.Form.Get("repo") |
|
272 |
+ tag := r.Form.Get("tag") |
|
273 |
+ vars := mux.Vars(r) |
|
274 |
+ name := vars["name"] |
|
275 |
+ var force bool |
|
276 |
+ if r.Form.Get("force") == "1" { |
|
277 |
+ force = true |
|
278 |
+ } |
|
255 | 279 |
|
256 |
- r.Path("/containers").Methods("GET").HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
|
257 |
- log.Println(r.Method, r.RequestURI) |
|
258 |
- if err := r.ParseForm(); err != nil { |
|
259 |
- http.Error(w, err.Error(), http.StatusInternalServerError) |
|
260 |
- return |
|
261 |
- } |
|
262 |
- all := r.Form.Get("all") |
|
263 |
- notrunc := r.Form.Get("notrunc") |
|
264 |
- quiet := r.Form.Get("quiet") |
|
265 |
- n, err := strconv.Atoi(r.Form.Get("n")) |
|
266 |
- if err != nil { |
|
267 |
- n = -1 |
|
268 |
- } |
|
280 |
+ if err := srv.ContainerTag(name, repo, tag, force); err != nil { |
|
281 |
+ http.Error(w, err.Error(), http.StatusInternalServerError) |
|
282 |
+ return err |
|
283 |
+ } |
|
284 |
+ w.WriteHeader(http.StatusCreated) |
|
285 |
+ return nil |
|
286 |
+} |
|
269 | 287 |
|
270 |
- outs := srv.Containers(all, notrunc, quiet, n) |
|
271 |
- b, err := json.Marshal(outs) |
|
272 |
- if err != nil { |
|
273 |
- http.Error(w, err.Error(), http.StatusInternalServerError) |
|
274 |
- } else { |
|
275 |
- w.Header().Set("Content-Type", "application/json") |
|
276 |
- w.Write(b) |
|
277 |
- } |
|
278 |
- }) |
|
288 |
+func postCommit(srv *Server, w http.ResponseWriter, r *http.Request) error { |
|
289 |
+ log.Println(r.Method, r.RequestURI) |
|
290 |
+ if err := r.ParseForm(); err != nil { |
|
291 |
+ http.Error(w, err.Error(), http.StatusInternalServerError) |
|
292 |
+ return err |
|
293 |
+ } |
|
294 |
+ var config Config |
|
295 |
+ if err := json.NewDecoder(r.Body).Decode(&config); err != nil { |
|
296 |
+ http.Error(w, err.Error(), http.StatusInternalServerError) |
|
297 |
+ return err |
|
298 |
+ } |
|
299 |
+ repo := r.Form.Get("repo") |
|
300 |
+ tag := r.Form.Get("tag") |
|
301 |
+ container := r.Form.Get("container") |
|
302 |
+ author := r.Form.Get("author") |
|
303 |
+ comment := r.Form.Get("comment") |
|
304 |
+ id, err := srv.ContainerCommit(container, repo, tag, author, comment, &config) |
|
305 |
+ if err != nil { |
|
306 |
+ httpError(w, err) |
|
307 |
+ return err |
|
308 |
+ } |
|
309 |
+ b, err := json.Marshal(ApiId{id}) |
|
310 |
+ if err != nil { |
|
311 |
+ http.Error(w, err.Error(), http.StatusInternalServerError) |
|
312 |
+ return err |
|
313 |
+ } else { |
|
314 |
+ w.Header().Set("Content-Type", "application/json") |
|
315 |
+ w.Write(b) |
|
316 |
+ } |
|
317 |
+ return nil |
|
318 |
+} |
|
279 | 319 |
|
280 |
- r.Path("/images/{name:.*}/tag").Methods("POST").HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
|
281 |
- log.Println(r.Method, r.RequestURI) |
|
282 |
- if err := r.ParseForm(); err != nil { |
|
283 |
- http.Error(w, err.Error(), http.StatusInternalServerError) |
|
284 |
- return |
|
285 |
- } |
|
286 |
- repo := r.Form.Get("repo") |
|
287 |
- tag := r.Form.Get("tag") |
|
288 |
- vars := mux.Vars(r) |
|
289 |
- name := vars["name"] |
|
290 |
- var force bool |
|
291 |
- if r.Form.Get("force") == "1" { |
|
292 |
- force = true |
|
293 |
- } |
|
320 |
+func postImages(srv *Server, w http.ResponseWriter, r *http.Request) error { |
|
321 |
+ log.Println(r.Method, r.RequestURI) |
|
322 |
+ if err := r.ParseForm(); err != nil { |
|
323 |
+ http.Error(w, err.Error(), http.StatusInternalServerError) |
|
324 |
+ return err |
|
325 |
+ } |
|
294 | 326 |
|
295 |
- if err := srv.ContainerTag(name, repo, tag, force); err != nil { |
|
296 |
- http.Error(w, err.Error(), http.StatusInternalServerError) |
|
297 |
- return |
|
298 |
- } |
|
299 |
- w.WriteHeader(http.StatusCreated) |
|
300 |
- }) |
|
327 |
+ src := r.Form.Get("fromSrc") |
|
328 |
+ image := r.Form.Get("fromImage") |
|
329 |
+ repo := r.Form.Get("repo") |
|
330 |
+ tag := r.Form.Get("tag") |
|
301 | 331 |
|
302 |
- r.Path("/commit").Methods("POST").HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
|
303 |
- log.Println(r.Method, r.RequestURI) |
|
304 |
- if err := r.ParseForm(); err != nil { |
|
305 |
- http.Error(w, err.Error(), http.StatusInternalServerError) |
|
306 |
- return |
|
307 |
- } |
|
308 |
- var config Config |
|
309 |
- if err := json.NewDecoder(r.Body).Decode(&config); err != nil { |
|
310 |
- http.Error(w, err.Error(), http.StatusInternalServerError) |
|
311 |
- return |
|
332 |
+ file, rwc, err := hijackServer(w) |
|
333 |
+ if file != nil { |
|
334 |
+ defer file.Close() |
|
335 |
+ } |
|
336 |
+ if rwc != nil { |
|
337 |
+ defer rwc.Close() |
|
338 |
+ } |
|
339 |
+ if err != nil { |
|
340 |
+ httpError(w, err) |
|
341 |
+ return err |
|
342 |
+ } |
|
343 |
+ fmt.Fprintf(file, "HTTP/1.1 200 OK\r\nContent-Type: raw-stream-hijack\r\n\r\n") |
|
344 |
+ if image != "" { //pull |
|
345 |
+ registry := r.Form.Get("registry") |
|
346 |
+ if err := srv.ImagePull(image, tag, registry, file); err != nil { |
|
347 |
+ fmt.Fprintf(file, "Error: %s\n", err) |
|
348 |
+ return err |
|
312 | 349 |
} |
313 |
- repo := r.Form.Get("repo") |
|
314 |
- tag := r.Form.Get("tag") |
|
315 |
- container := r.Form.Get("container") |
|
316 |
- author := r.Form.Get("author") |
|
317 |
- comment := r.Form.Get("comment") |
|
318 |
- id, err := srv.ContainerCommit(container, repo, tag, author, comment, &config) |
|
319 |
- if err != nil { |
|
320 |
- httpError(w, err) |
|
321 |
- return |
|
350 |
+ } else { //import |
|
351 |
+ if err := srv.ImageImport(src, repo, tag, file); err != nil { |
|
352 |
+ fmt.Fprintf(file, "Error: %s\n", err) |
|
353 |
+ return err |
|
322 | 354 |
} |
323 |
- b, err := json.Marshal(ApiId{id}) |
|
324 |
- if err != nil { |
|
325 |
- http.Error(w, err.Error(), http.StatusInternalServerError) |
|
326 |
- } else { |
|
327 |
- w.Header().Set("Content-Type", "application/json") |
|
328 |
- w.Write(b) |
|
329 |
- } |
|
330 |
- }) |
|
355 |
+ } |
|
356 |
+ return nil |
|
357 |
+} |
|
331 | 358 |
|
332 |
- r.Path("/images").Methods("POST").HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
|
333 |
- log.Println(r.Method, r.RequestURI) |
|
334 |
- if err := r.ParseForm(); err != nil { |
|
335 |
- http.Error(w, err.Error(), http.StatusInternalServerError) |
|
336 |
- return |
|
337 |
- } |
|
359 |
+func getImagesSearch(srv *Server, w http.ResponseWriter, r *http.Request) error { |
|
360 |
+ log.Println(r.Method, r.RequestURI) |
|
361 |
+ if err := r.ParseForm(); err != nil { |
|
362 |
+ http.Error(w, err.Error(), http.StatusInternalServerError) |
|
363 |
+ return err |
|
364 |
+ } |
|
338 | 365 |
|
339 |
- src := r.Form.Get("fromSrc") |
|
340 |
- image := r.Form.Get("fromImage") |
|
341 |
- repo := r.Form.Get("repo") |
|
342 |
- tag := r.Form.Get("tag") |
|
366 |
+ term := r.Form.Get("term") |
|
367 |
+ outs, err := srv.ImagesSearch(term) |
|
368 |
+ if err != nil { |
|
369 |
+ httpError(w, err) |
|
370 |
+ return err |
|
371 |
+ } |
|
372 |
+ b, err := json.Marshal(outs) |
|
373 |
+ if err != nil { |
|
374 |
+ http.Error(w, err.Error(), http.StatusInternalServerError) |
|
375 |
+ return err |
|
376 |
+ } else { |
|
377 |
+ w.Header().Set("Content-Type", "application/json") |
|
378 |
+ w.Write(b) |
|
379 |
+ } |
|
380 |
+ return nil |
|
381 |
+} |
|
343 | 382 |
|
344 |
- file, rwc, err := hijackServer(w) |
|
345 |
- if file != nil { |
|
346 |
- defer file.Close() |
|
347 |
- } |
|
348 |
- if rwc != nil { |
|
349 |
- defer rwc.Close() |
|
350 |
- } |
|
351 |
- if err != nil { |
|
352 |
- httpError(w, err) |
|
353 |
- return |
|
354 |
- } |
|
355 |
- fmt.Fprintf(file, "HTTP/1.1 200 OK\r\nContent-Type: raw-stream-hijack\r\n\r\n") |
|
356 |
- if image != "" { //pull |
|
357 |
- registry := r.Form.Get("registry") |
|
358 |
- if err := srv.ImagePull(image, tag, registry, file); err != nil { |
|
359 |
- fmt.Fprintln(file, "Error: "+err.Error()) |
|
360 |
- } |
|
361 |
- } else { //import |
|
362 |
- if err := srv.ImageImport(src, repo, tag, file); err != nil { |
|
363 |
- fmt.Fprintln(file, "Error: "+err.Error()) |
|
364 |
- } |
|
365 |
- } |
|
366 |
- }) |
|
383 |
+func postImagesInsert(srv *Server, w http.ResponseWriter, r *http.Request) error { |
|
384 |
+ log.Println(r.Method, r.RequestURI) |
|
385 |
+ if err := r.ParseForm(); err != nil { |
|
386 |
+ http.Error(w, err.Error(), http.StatusInternalServerError) |
|
387 |
+ return err |
|
388 |
+ } |
|
367 | 389 |
|
368 |
- r.Path("/images/search").Methods("GET").HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
|
369 |
- log.Println(r.Method, r.RequestURI) |
|
370 |
- if err := r.ParseForm(); err != nil { |
|
371 |
- http.Error(w, err.Error(), http.StatusInternalServerError) |
|
372 |
- return |
|
373 |
- } |
|
390 |
+ url := r.Form.Get("url") |
|
391 |
+ path := r.Form.Get("path") |
|
392 |
+ vars := mux.Vars(r) |
|
393 |
+ name := vars["name"] |
|
374 | 394 |
|
375 |
- term := r.Form.Get("term") |
|
376 |
- outs, err := srv.ImagesSearch(term) |
|
377 |
- if err != nil { |
|
378 |
- httpError(w, err) |
|
379 |
- return |
|
380 |
- } |
|
381 |
- b, err := json.Marshal(outs) |
|
382 |
- if err != nil { |
|
383 |
- http.Error(w, err.Error(), http.StatusInternalServerError) |
|
384 |
- } else { |
|
385 |
- w.Header().Set("Content-Type", "application/json") |
|
386 |
- w.Write(b) |
|
387 |
- } |
|
388 |
- }) |
|
395 |
+ file, rwc, err := hijackServer(w) |
|
396 |
+ if file != nil { |
|
397 |
+ defer file.Close() |
|
398 |
+ } |
|
399 |
+ if rwc != nil { |
|
400 |
+ defer rwc.Close() |
|
401 |
+ } |
|
402 |
+ if err != nil { |
|
403 |
+ httpError(w, err) |
|
404 |
+ return err |
|
405 |
+ } |
|
406 |
+ fmt.Fprintf(file, "HTTP/1.1 200 OK\r\nContent-Type: raw-stream-hijack\r\n\r\n") |
|
407 |
+ if err := srv.ImageInsert(name, url, path, file); err != nil { |
|
408 |
+ fmt.Fprintln(file, "Error: "+err.Error()) |
|
409 |
+ } |
|
410 |
+ return nil |
|
411 |
+} |
|
389 | 412 |
|
390 |
- r.Path("/images/{name:*.}/insert").Methods("POST").HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
|
391 |
- log.Println(r.Method, r.RequestURI) |
|
392 |
- if err := r.ParseForm(); err != nil { |
|
393 |
- http.Error(w, err.Error(), http.StatusInternalServerError) |
|
394 |
- return |
|
395 |
- } |
|
413 |
+func postImagesPush(srv *Server, w http.ResponseWriter, r *http.Request) error { |
|
414 |
+ log.Println(r.Method, r.RequestURI) |
|
415 |
+ if err := r.ParseForm(); err != nil { |
|
416 |
+ http.Error(w, err.Error(), http.StatusInternalServerError) |
|
417 |
+ return err |
|
418 |
+ } |
|
396 | 419 |
|
397 |
- url := r.Form.Get("url") |
|
398 |
- path := r.Form.Get("path") |
|
399 |
- vars := mux.Vars(r) |
|
400 |
- name := vars["name"] |
|
420 |
+ registry := r.Form.Get("registry") |
|
401 | 421 |
|
402 |
- file, rwc, err := hijackServer(w) |
|
403 |
- if file != nil { |
|
404 |
- defer file.Close() |
|
405 |
- } |
|
406 |
- if rwc != nil { |
|
407 |
- defer rwc.Close() |
|
408 |
- } |
|
409 |
- if err != nil { |
|
410 |
- httpError(w, err) |
|
411 |
- return |
|
412 |
- } |
|
413 |
- fmt.Fprintf(file, "HTTP/1.1 200 OK\r\nContent-Type: raw-stream-hijack\r\n\r\n") |
|
414 |
- if err := srv.ImageInsert(name, url, path, file); err != nil { |
|
415 |
- fmt.Fprintln(file, "Error: "+err.Error()) |
|
416 |
- } |
|
417 |
- }) |
|
418 |
- r.Path("/images/{name:*.}/push").Methods("POST").HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
|
419 |
- log.Println(r.Method, r.RequestURI) |
|
420 |
- if err := r.ParseForm(); err != nil { |
|
421 |
- http.Error(w, err.Error(), http.StatusInternalServerError) |
|
422 |
- return |
|
423 |
- } |
|
422 |
+ vars := mux.Vars(r) |
|
423 |
+ name := vars["name"] |
|
424 | 424 |
|
425 |
- registry := r.Form.Get("registry") |
|
425 |
+ file, rwc, err := hijackServer(w) |
|
426 |
+ if file != nil { |
|
427 |
+ defer file.Close() |
|
428 |
+ } |
|
429 |
+ if rwc != nil { |
|
430 |
+ defer rwc.Close() |
|
431 |
+ } |
|
432 |
+ if err != nil { |
|
433 |
+ httpError(w, err) |
|
434 |
+ return err |
|
435 |
+ } |
|
436 |
+ fmt.Fprintf(file, "HTTP/1.1 200 OK\r\nContent-Type: raw-stream-hijack\r\n\r\n") |
|
437 |
+ if err := srv.ImagePush(name, registry, file); err != nil { |
|
438 |
+ fmt.Fprintln(file, "Error: "+err.Error()) |
|
439 |
+ } |
|
440 |
+ return nil |
|
441 |
+} |
|
426 | 442 |
|
427 |
- vars := mux.Vars(r) |
|
428 |
- name := vars["name"] |
|
443 |
+func postBuild(srv *Server, w http.ResponseWriter, r *http.Request) error { |
|
444 |
+ log.Println(r.Method, r.RequestURI) |
|
429 | 445 |
|
430 |
- file, rwc, err := hijackServer(w) |
|
431 |
- if file != nil { |
|
432 |
- defer file.Close() |
|
433 |
- } |
|
434 |
- if rwc != nil { |
|
435 |
- defer rwc.Close() |
|
436 |
- } |
|
437 |
- if err != nil { |
|
438 |
- httpError(w, err) |
|
439 |
- return |
|
440 |
- } |
|
441 |
- fmt.Fprintf(file, "HTTP/1.1 200 OK\r\nContent-Type: raw-stream-hijack\r\n\r\n") |
|
442 |
- if err := srv.ImagePush(name, registry, file); err != nil { |
|
443 |
- fmt.Fprintln(file, "Error: "+err.Error()) |
|
444 |
- } |
|
445 |
- }) |
|
446 |
+ file, rwc, err := hijackServer(w) |
|
447 |
+ if file != nil { |
|
448 |
+ defer file.Close() |
|
449 |
+ } |
|
450 |
+ if rwc != nil { |
|
451 |
+ defer rwc.Close() |
|
452 |
+ } |
|
453 |
+ if err != nil { |
|
454 |
+ httpError(w, err) |
|
455 |
+ return err |
|
456 |
+ } |
|
457 |
+ fmt.Fprintf(file, "HTTP/1.1 200 OK\r\nContent-Type: raw-stream-hijack\r\n\r\n") |
|
458 |
+ if err := srv.ImageCreateFormFile(file); err != nil { |
|
459 |
+ fmt.Fprintln(file, "Error: "+err.Error()) |
|
460 |
+ } |
|
461 |
+ return nil |
|
462 |
+} |
|
446 | 463 |
|
447 |
- r.Path("/build").Methods("POST").HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
|
448 |
- log.Println(r.Method, r.RequestURI) |
|
464 |
+func postContainers(srv *Server, w http.ResponseWriter, r *http.Request) error { |
|
465 |
+ log.Println(r.Method, r.RequestURI) |
|
466 |
+ var config Config |
|
467 |
+ if err := json.NewDecoder(r.Body).Decode(&config); err != nil { |
|
468 |
+ http.Error(w, err.Error(), http.StatusInternalServerError) |
|
469 |
+ return err |
|
470 |
+ } |
|
471 |
+ id, memoryW, swapW, err := srv.ContainerCreate(config) |
|
472 |
+ if err != nil { |
|
473 |
+ httpError(w, err) |
|
474 |
+ return err |
|
475 |
+ } |
|
476 |
+ var out ApiRun |
|
477 |
+ out.Id = id |
|
478 |
+ if memoryW { |
|
479 |
+ out.Warnings = append(out.Warnings, "Your kernel does not support memory limit capabilities. Limitation discarded.") |
|
480 |
+ } |
|
481 |
+ if swapW { |
|
482 |
+ out.Warnings = append(out.Warnings, "Your kernel does not support memory swap capabilities. Limitation discarded.") |
|
483 |
+ } |
|
484 |
+ b, err := json.Marshal(out) |
|
485 |
+ if err != nil { |
|
486 |
+ http.Error(w, err.Error(), http.StatusInternalServerError) |
|
487 |
+ return err |
|
488 |
+ } else { |
|
489 |
+ w.Header().Set("Content-Type", "application/json") |
|
490 |
+ w.Write(b) |
|
491 |
+ } |
|
492 |
+ return nil |
|
493 |
+} |
|
449 | 494 |
|
450 |
- file, rwc, err := hijackServer(w) |
|
451 |
- if file != nil { |
|
452 |
- defer file.Close() |
|
453 |
- } |
|
454 |
- if rwc != nil { |
|
455 |
- defer rwc.Close() |
|
456 |
- } |
|
457 |
- if err != nil { |
|
458 |
- httpError(w, err) |
|
459 |
- return |
|
460 |
- } |
|
461 |
- fmt.Fprintf(file, "HTTP/1.1 200 OK\r\nContent-Type: raw-stream-hijack\r\n\r\n") |
|
462 |
- if err := srv.ImageCreateFormFile(file); err != nil { |
|
463 |
- fmt.Fprintln(file, "Error: "+err.Error()) |
|
464 |
- } |
|
465 |
- }) |
|
495 |
+func postContainersRestart(srv *Server, w http.ResponseWriter, r *http.Request) error { |
|
496 |
+ log.Println(r.Method, r.RequestURI) |
|
497 |
+ if err := r.ParseForm(); err != nil { |
|
498 |
+ http.Error(w, err.Error(), http.StatusInternalServerError) |
|
499 |
+ return err |
|
500 |
+ } |
|
501 |
+ t, err := strconv.Atoi(r.Form.Get("t")) |
|
502 |
+ if err != nil || t < 0 { |
|
503 |
+ t = 10 |
|
504 |
+ } |
|
505 |
+ vars := mux.Vars(r) |
|
506 |
+ name := vars["name"] |
|
507 |
+ if err := srv.ContainerRestart(name, t); err != nil { |
|
508 |
+ httpError(w, err) |
|
509 |
+ return err |
|
510 |
+ } else { |
|
511 |
+ w.WriteHeader(http.StatusOK) |
|
512 |
+ } |
|
513 |
+ return nil |
|
514 |
+} |
|
466 | 515 |
|
467 |
- r.Path("/containers").Methods("POST").HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
|
468 |
- log.Println(r.Method, r.RequestURI) |
|
469 |
- var config Config |
|
470 |
- if err := json.NewDecoder(r.Body).Decode(&config); err != nil { |
|
471 |
- http.Error(w, err.Error(), http.StatusInternalServerError) |
|
472 |
- return |
|
473 |
- } |
|
474 |
- id, memoryW, swapW, err := srv.ContainerCreate(config) |
|
475 |
- if err != nil { |
|
476 |
- httpError(w, err) |
|
477 |
- return |
|
478 |
- } |
|
479 |
- var out ApiRun |
|
480 |
- out.Id = id |
|
481 |
- if memoryW { |
|
482 |
- out.Warnings = append(out.Warnings, "Your kernel does not support memory limit capabilities. Limitation discarded.") |
|
483 |
- } |
|
484 |
- if swapW { |
|
485 |
- out.Warnings = append(out.Warnings, "Your kernel does not support memory swap capabilities. Limitation discarded.") |
|
486 |
- } |
|
487 |
- b, err := json.Marshal(out) |
|
488 |
- if err != nil { |
|
489 |
- http.Error(w, err.Error(), http.StatusInternalServerError) |
|
490 |
- } else { |
|
491 |
- w.Header().Set("Content-Type", "application/json") |
|
492 |
- w.Write(b) |
|
493 |
- } |
|
494 |
- }) |
|
516 |
+func deleteContainers(srv *Server, w http.ResponseWriter, r *http.Request) error { |
|
517 |
+ log.Println(r.Method, r.RequestURI) |
|
518 |
+ if err := r.ParseForm(); err != nil { |
|
519 |
+ http.Error(w, err.Error(), http.StatusInternalServerError) |
|
520 |
+ return err |
|
521 |
+ } |
|
522 |
+ vars := mux.Vars(r) |
|
523 |
+ name := vars["name"] |
|
524 |
+ var v bool |
|
525 |
+ if r.Form.Get("v") == "1" { |
|
526 |
+ v = true |
|
527 |
+ } |
|
528 |
+ if err := srv.ContainerDestroy(name, v); err != nil { |
|
529 |
+ httpError(w, err) |
|
530 |
+ return err |
|
531 |
+ } else { |
|
532 |
+ w.WriteHeader(http.StatusOK) |
|
533 |
+ } |
|
534 |
+ return nil |
|
535 |
+} |
|
495 | 536 |
|
496 |
- r.Path("/containers/{name:.*}/restart").Methods("POST").HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
|
497 |
- log.Println(r.Method, r.RequestURI) |
|
498 |
- if err := r.ParseForm(); err != nil { |
|
499 |
- http.Error(w, err.Error(), http.StatusInternalServerError) |
|
500 |
- return |
|
501 |
- } |
|
502 |
- t, err := strconv.Atoi(r.Form.Get("t")) |
|
503 |
- if err != nil || t < 0 { |
|
504 |
- t = 10 |
|
505 |
- } |
|
506 |
- vars := mux.Vars(r) |
|
507 |
- name := vars["name"] |
|
508 |
- if err := srv.ContainerRestart(name, t); err != nil { |
|
509 |
- httpError(w, err) |
|
510 |
- } else { |
|
511 |
- w.WriteHeader(http.StatusOK) |
|
512 |
- } |
|
513 |
- }) |
|
537 |
+func deleteImages(srv *Server, w http.ResponseWriter, r *http.Request) error { |
|
538 |
+ log.Println(r.Method, r.RequestURI) |
|
539 |
+ vars := mux.Vars(r) |
|
540 |
+ name := vars["name"] |
|
541 |
+ if err := srv.ImageDelete(name); err != nil { |
|
542 |
+ httpError(w, err) |
|
543 |
+ return err |
|
544 |
+ } else { |
|
545 |
+ w.WriteHeader(http.StatusOK) |
|
546 |
+ } |
|
547 |
+ return nil |
|
548 |
+} |
|
514 | 549 |
|
515 |
- r.Path("/containers/{name:.*}").Methods("DELETE").HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
|
516 |
- log.Println(r.Method, r.RequestURI) |
|
517 |
- if err := r.ParseForm(); err != nil { |
|
518 |
- http.Error(w, err.Error(), http.StatusInternalServerError) |
|
519 |
- return |
|
520 |
- } |
|
521 |
- vars := mux.Vars(r) |
|
522 |
- name := vars["name"] |
|
523 |
- var v bool |
|
524 |
- if r.Form.Get("v") == "1" { |
|
525 |
- v = true |
|
526 |
- } |
|
527 |
- if err := srv.ContainerDestroy(name, v); err != nil { |
|
528 |
- httpError(w, err) |
|
529 |
- } else { |
|
530 |
- w.WriteHeader(http.StatusOK) |
|
531 |
- } |
|
532 |
- }) |
|
550 |
+func postContainersStart(srv *Server, w http.ResponseWriter, r *http.Request) error { |
|
551 |
+ log.Println(r.Method, r.RequestURI) |
|
552 |
+ vars := mux.Vars(r) |
|
553 |
+ name := vars["name"] |
|
554 |
+ if err := srv.ContainerStart(name); err != nil { |
|
555 |
+ httpError(w, err) |
|
556 |
+ return err |
|
557 |
+ } else { |
|
558 |
+ w.WriteHeader(http.StatusOK) |
|
559 |
+ } |
|
560 |
+ return nil |
|
561 |
+} |
|
533 | 562 |
|
534 |
- r.Path("/images/{name:.*}").Methods("DELETE").HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
|
535 |
- log.Println(r.Method, r.RequestURI) |
|
536 |
- vars := mux.Vars(r) |
|
537 |
- name := vars["name"] |
|
538 |
- if err := srv.ImageDelete(name); err != nil { |
|
539 |
- httpError(w, err) |
|
540 |
- } else { |
|
541 |
- w.WriteHeader(http.StatusOK) |
|
542 |
- } |
|
543 |
- }) |
|
563 |
+func postContainersStop(srv *Server, w http.ResponseWriter, r *http.Request) error { |
|
564 |
+ log.Println(r.Method, r.RequestURI) |
|
565 |
+ if err := r.ParseForm(); err != nil { |
|
566 |
+ http.Error(w, err.Error(), http.StatusInternalServerError) |
|
567 |
+ return err |
|
568 |
+ } |
|
569 |
+ t, err := strconv.Atoi(r.Form.Get("t")) |
|
570 |
+ if err != nil || t < 0 { |
|
571 |
+ t = 10 |
|
572 |
+ } |
|
573 |
+ vars := mux.Vars(r) |
|
574 |
+ name := vars["name"] |
|
544 | 575 |
|
545 |
- r.Path("/containers/{name:.*}/start").Methods("POST").HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
|
546 |
- log.Println(r.Method, r.RequestURI) |
|
547 |
- vars := mux.Vars(r) |
|
548 |
- name := vars["name"] |
|
549 |
- if err := srv.ContainerStart(name); err != nil { |
|
550 |
- httpError(w, err) |
|
551 |
- } else { |
|
552 |
- w.WriteHeader(http.StatusOK) |
|
553 |
- } |
|
554 |
- }) |
|
576 |
+ if err := srv.ContainerStop(name, t); err != nil { |
|
577 |
+ httpError(w, err) |
|
578 |
+ return err |
|
579 |
+ } else { |
|
580 |
+ w.WriteHeader(http.StatusOK) |
|
581 |
+ } |
|
582 |
+ return nil |
|
583 |
+} |
|
555 | 584 |
|
556 |
- r.Path("/containers/{name:.*}/stop").Methods("POST").HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
|
557 |
- log.Println(r.Method, r.RequestURI) |
|
558 |
- if err := r.ParseForm(); err != nil { |
|
559 |
- http.Error(w, err.Error(), http.StatusInternalServerError) |
|
560 |
- return |
|
561 |
- } |
|
562 |
- t, err := strconv.Atoi(r.Form.Get("t")) |
|
563 |
- if err != nil || t < 0 { |
|
564 |
- t = 10 |
|
565 |
- } |
|
566 |
- vars := mux.Vars(r) |
|
567 |
- name := vars["name"] |
|
585 |
+func postContainersWait(srv *Server, w http.ResponseWriter, r *http.Request) error { |
|
586 |
+ log.Println(r.Method, r.RequestURI) |
|
587 |
+ vars := mux.Vars(r) |
|
588 |
+ name := vars["name"] |
|
589 |
+ status, err := srv.ContainerWait(name) |
|
590 |
+ if err != nil { |
|
591 |
+ httpError(w, err) |
|
592 |
+ return err |
|
593 |
+ } |
|
594 |
+ b, err := json.Marshal(ApiWait{status}) |
|
595 |
+ if err != nil { |
|
596 |
+ http.Error(w, err.Error(), http.StatusInternalServerError) |
|
597 |
+ return err |
|
598 |
+ } else { |
|
599 |
+ w.Header().Set("Content-Type", "application/json") |
|
600 |
+ w.Write(b) |
|
601 |
+ } |
|
602 |
+ return nil |
|
603 |
+} |
|
568 | 604 |
|
569 |
- if err := srv.ContainerStop(name, t); err != nil { |
|
570 |
- httpError(w, err) |
|
571 |
- } else { |
|
572 |
- w.WriteHeader(http.StatusOK) |
|
573 |
- } |
|
574 |
- }) |
|
605 |
+func postContainersAttach(srv *Server, w http.ResponseWriter, r *http.Request) error { |
|
606 |
+ log.Println(r.Method, r.RequestURI) |
|
607 |
+ if err := r.ParseForm(); err != nil { |
|
608 |
+ http.Error(w, err.Error(), http.StatusInternalServerError) |
|
609 |
+ return err |
|
610 |
+ } |
|
611 |
+ logs := r.Form.Get("logs") |
|
612 |
+ stream := r.Form.Get("stream") |
|
613 |
+ stdin := r.Form.Get("stdin") |
|
614 |
+ stdout := r.Form.Get("stdout") |
|
615 |
+ stderr := r.Form.Get("stderr") |
|
616 |
+ vars := mux.Vars(r) |
|
617 |
+ name := vars["name"] |
|
618 |
+ |
|
619 |
+ file, rwc, err := hijackServer(w) |
|
620 |
+ if file != nil { |
|
621 |
+ defer file.Close() |
|
622 |
+ } |
|
623 |
+ if rwc != nil { |
|
624 |
+ defer rwc.Close() |
|
625 |
+ } |
|
626 |
+ if err != nil { |
|
627 |
+ httpError(w, err) |
|
628 |
+ return err |
|
629 |
+ } |
|
575 | 630 |
|
576 |
- r.Path("/containers/{name:.*}/wait").Methods("POST").HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
|
577 |
- log.Println(r.Method, r.RequestURI) |
|
578 |
- vars := mux.Vars(r) |
|
579 |
- name := vars["name"] |
|
580 |
- status, err := srv.ContainerWait(name) |
|
581 |
- if err != nil { |
|
582 |
- httpError(w, err) |
|
583 |
- return |
|
584 |
- } |
|
585 |
- b, err := json.Marshal(ApiWait{status}) |
|
586 |
- if err != nil { |
|
587 |
- http.Error(w, err.Error(), http.StatusInternalServerError) |
|
588 |
- } else { |
|
589 |
- w.Header().Set("Content-Type", "application/json") |
|
590 |
- w.Write(b) |
|
591 |
- } |
|
592 |
- }) |
|
631 |
+ fmt.Fprintf(file, "HTTP/1.1 200 OK\r\nContent-Type: raw-stream-hijack\r\n\r\n") |
|
632 |
+ if err := srv.ContainerAttach(name, logs, stream, stdin, stdout, stderr, file); err != nil { |
|
633 |
+ fmt.Fprintf(file, "Error: %s\n", err) |
|
634 |
+ return err |
|
635 |
+ } |
|
636 |
+ return nil |
|
637 |
+} |
|
593 | 638 |
|
594 |
- r.Path("/containers/{name:.*}/attach").Methods("POST").HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
|
595 |
- log.Println(r.Method, r.RequestURI) |
|
596 |
- if err := r.ParseForm(); err != nil { |
|
597 |
- http.Error(w, err.Error(), http.StatusInternalServerError) |
|
598 |
- return |
|
599 |
- } |
|
600 |
- logs := r.Form.Get("logs") |
|
601 |
- stream := r.Form.Get("stream") |
|
602 |
- stdin := r.Form.Get("stdin") |
|
603 |
- stdout := r.Form.Get("stdout") |
|
604 |
- stderr := r.Form.Get("stderr") |
|
605 |
- vars := mux.Vars(r) |
|
606 |
- name := vars["name"] |
|
639 |
+func getContainersByName(srv *Server, w http.ResponseWriter, r *http.Request) error { |
|
640 |
+ log.Println(r.Method, r.RequestURI) |
|
641 |
+ vars := mux.Vars(r) |
|
642 |
+ name := vars["name"] |
|
607 | 643 |
|
608 |
- file, rwc, err := hijackServer(w) |
|
609 |
- if file != nil { |
|
610 |
- defer file.Close() |
|
611 |
- } |
|
612 |
- if rwc != nil { |
|
613 |
- defer rwc.Close() |
|
614 |
- } |
|
615 |
- if err != nil { |
|
616 |
- httpError(w, err) |
|
617 |
- return |
|
618 |
- } |
|
644 |
+ container, err := srv.ContainerInspect(name) |
|
645 |
+ if err != nil { |
|
646 |
+ httpError(w, err) |
|
647 |
+ return err |
|
648 |
+ } |
|
649 |
+ b, err := json.Marshal(container) |
|
650 |
+ if err != nil { |
|
651 |
+ http.Error(w, err.Error(), http.StatusInternalServerError) |
|
652 |
+ return err |
|
653 |
+ } else { |
|
654 |
+ w.Header().Set("Content-Type", "application/json") |
|
655 |
+ w.Write(b) |
|
656 |
+ } |
|
657 |
+ return nil |
|
658 |
+} |
|
619 | 659 |
|
620 |
- fmt.Fprintf(file, "HTTP/1.1 200 OK\r\nContent-Type: raw-stream-hijack\r\n\r\n") |
|
621 |
- if err := srv.ContainerAttach(name, logs, stream, stdin, stdout, stderr, file); err != nil { |
|
622 |
- fmt.Fprintln(file, "Error: "+err.Error()) |
|
623 |
- } |
|
624 |
- }) |
|
660 |
+func getImagesByName(srv *Server, w http.ResponseWriter, r *http.Request) error { |
|
661 |
+ log.Println(r.Method, r.RequestURI) |
|
662 |
+ vars := mux.Vars(r) |
|
663 |
+ name := vars["name"] |
|
625 | 664 |
|
626 |
- r.Path("/containers/{name:.*}").Methods("GET").HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
|
627 |
- log.Println(r.Method, r.RequestURI) |
|
628 |
- vars := mux.Vars(r) |
|
629 |
- name := vars["name"] |
|
665 |
+ image, err := srv.ImageInspect(name) |
|
666 |
+ if err != nil { |
|
667 |
+ httpError(w, err) |
|
668 |
+ return err |
|
669 |
+ } |
|
670 |
+ b, err := json.Marshal(image) |
|
671 |
+ if err != nil { |
|
672 |
+ http.Error(w, err.Error(), http.StatusInternalServerError) |
|
673 |
+ return err |
|
674 |
+ } else { |
|
675 |
+ w.Header().Set("Content-Type", "application/json") |
|
676 |
+ w.Write(b) |
|
677 |
+ } |
|
678 |
+ return nil |
|
679 |
+} |
|
630 | 680 |
|
631 |
- container, err := srv.ContainerInspect(name) |
|
632 |
- if err != nil { |
|
633 |
- httpError(w, err) |
|
634 |
- return |
|
635 |
- } |
|
636 |
- b, err := json.Marshal(container) |
|
637 |
- if err != nil { |
|
638 |
- http.Error(w, err.Error(), http.StatusInternalServerError) |
|
639 |
- } else { |
|
640 |
- w.Header().Set("Content-Type", "application/json") |
|
641 |
- w.Write(b) |
|
642 |
- } |
|
643 |
- }) |
|
681 |
+func wrap(fct func(*Server, http.ResponseWriter, *http.Request) error, w http.ResponseWriter, r *http.Request, srv *Server, method, route string) { |
|
682 |
+ if err := fct(srv, w, r); err != nil { |
|
683 |
+ Debugf("Error: %s %s: %s", method, route, err) |
|
684 |
+ } |
|
685 |
+} |
|
644 | 686 |
|
645 |
- r.Path("/images/{name:.*}").Methods("GET").HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
|
646 |
- log.Println(r.Method, r.RequestURI) |
|
647 |
- vars := mux.Vars(r) |
|
648 |
- name := vars["name"] |
|
687 |
+func ListenAndServe(addr string, srv *Server) error { |
|
688 |
+ r := mux.NewRouter() |
|
689 |
+ log.Printf("Listening for HTTP on %s\n", addr) |
|
649 | 690 |
|
650 |
- image, err := srv.ImageInspect(name) |
|
651 |
- if err != nil { |
|
652 |
- httpError(w, err) |
|
653 |
- return |
|
654 |
- } |
|
655 |
- b, err := json.Marshal(image) |
|
656 |
- if err != nil { |
|
657 |
- http.Error(w, err.Error(), http.StatusInternalServerError) |
|
658 |
- } else { |
|
659 |
- w.Header().Set("Content-Type", "application/json") |
|
660 |
- w.Write(b) |
|
691 |
+ m := map[string]map[string]func(*Server, http.ResponseWriter, *http.Request) error{ |
|
692 |
+ "GET": { |
|
693 |
+ "/auth": getAuth, |
|
694 |
+ "/version": getVersion, |
|
695 |
+ "/containers/{name:.*}/export": getContainersExport, |
|
696 |
+ "/images": getImages, |
|
697 |
+ "/info": getInfo, |
|
698 |
+ "/images/{name:.*}/history": getImagesHistory, |
|
699 |
+ "/containers/{name:.*}/changes": getContainersChanges, |
|
700 |
+ "/containers/{name:.*}/port": getContainersPort, |
|
701 |
+ "/containers": getContainers, |
|
702 |
+ "/images/search": getImagesSearch, |
|
703 |
+ "/containers/{name:.*}": getContainersByName, |
|
704 |
+ "/images/{name:.*}": getImagesByName, |
|
705 |
+ }, |
|
706 |
+ "POST": { |
|
707 |
+ "/auth": postAuth, |
|
708 |
+ "/containers/{name:.*}/kill": postContainersKill, |
|
709 |
+ "/images/{name:.*}/tag": postImagesTag, |
|
710 |
+ "/commit": postCommit, |
|
711 |
+ "/images": postImages, |
|
712 |
+ "/images/{name:*.}/insert": postImagesInsert, |
|
713 |
+ "/images/{name:*.}/push": postImagesPush, |
|
714 |
+ "/postBuild": postBuild, |
|
715 |
+ "/postContainers": postContainers, |
|
716 |
+ "/containers/{name:.*}/restart": postContainersRestart, |
|
717 |
+ "/containers/{name:.*}/start": postContainersStart, |
|
718 |
+ "/containers/{name:.*}/stop": postContainersStop, |
|
719 |
+ "/containers/{name:.*}/wait": postContainersWait, |
|
720 |
+ "/containers/{name:.*}/attach": postContainersAttach, |
|
721 |
+ }, |
|
722 |
+ "DELETE": { |
|
723 |
+ "/containers/{name:.*}": deleteContainers, |
|
724 |
+ "/images/{name:.*}": deleteImages, |
|
725 |
+ }, |
|
726 |
+ } |
|
727 |
+ |
|
728 |
+ for method, routes := range m { |
|
729 |
+ for route, fct := range routes { |
|
730 |
+ Debugf("Registering %s, %s", method, route) |
|
731 |
+ // NOTE: scope issue, make sure the variables are local and won't be changed |
|
732 |
+ localRoute := route |
|
733 |
+ localMethod := method |
|
734 |
+ localFct := fct |
|
735 |
+ r.Path(localRoute).Methods(localMethod).HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
|
736 |
+ Debugf("Calling %s %s", localMethod, localRoute) |
|
737 |
+ localFct(srv, w, r) |
|
738 |
+ }) |
|
661 | 739 |
} |
662 |
- }) |
|
740 |
+ } |
|
663 | 741 |
|
664 | 742 |
return http.ListenAndServe(addr, r) |
665 | 743 |
} |
... | ... |
@@ -35,8 +35,10 @@ func checkRemoteVersion() error { |
35 | 35 |
} |
36 | 36 |
|
37 | 37 |
var out ApiVersion |
38 |
+ |
|
38 | 39 |
err = json.Unmarshal(body, &out) |
39 | 40 |
if err != nil { |
41 |
+ Debugf("Error unmarshal: body: %s, err: %s\n", body, err) |
|
40 | 42 |
return err |
41 | 43 |
} |
42 | 44 |
if out.Version != VERSION { |
... | ... |
@@ -323,6 +325,7 @@ func CmdVersion(args ...string) error { |
323 | 323 |
var out ApiVersion |
324 | 324 |
err = json.Unmarshal(body, &out) |
325 | 325 |
if err != nil { |
326 |
+ Debugf("Error unmarshal: body: %s, err: %s\n", body, err) |
|
326 | 327 |
return err |
327 | 328 |
} |
328 | 329 |
fmt.Println("Version:", out.Version) |
... | ... |
@@ -1213,7 +1216,7 @@ func hijack(method, path string, setRawTerminal bool) error { |
1213 | 1213 |
sendStdin := Go(func() error { |
1214 | 1214 |
_, err := io.Copy(rwc, os.Stdin) |
1215 | 1215 |
if err := rwc.(*net.TCPConn).CloseWrite(); err != nil { |
1216 |
- fmt.Fprintf(os.Stderr, "Couldn't send EOF: "+err.Error()) |
|
1216 |
+ fmt.Fprintf(os.Stderr, "Couldn't send EOF: %s\n", err) |
|
1217 | 1217 |
} |
1218 | 1218 |
return err |
1219 | 1219 |
}) |
... | ... |
@@ -316,7 +316,7 @@ func (srv *Server) ImagePush(name, registry string, file *os.File) error { |
316 | 316 |
img, err := srv.runtime.graph.Get(name) |
317 | 317 |
if err != nil { |
318 | 318 |
Debugf("The push refers to a repository [%s] (len: %d)\n", name, len(srv.runtime.repositories.Repositories[name])) |
319 |
- // If it fails, try to get the repository |
|
319 |
+ // If it fails, try to get the repository |
|
320 | 320 |
if localRepo, exists := srv.runtime.repositories.Repositories[name]; exists { |
321 | 321 |
if err := srv.runtime.graph.PushRepository(file, name, localRepo, srv.runtime.authConfig); err != nil { |
322 | 322 |
return err |
... | ... |
@@ -350,8 +350,8 @@ func (srv *Server) ImageImport(src, repo, tag string, file *os.File) error { |
350 | 350 |
u.Path = "" |
351 | 351 |
} |
352 | 352 |
fmt.Fprintln(file, "Downloading from", u) |
353 |
- // Download with curl (pretty progress bar) |
|
354 |
- // If curl is not available, fallback to http.Get() |
|
353 |
+ // Download with curl (pretty progress bar) |
|
354 |
+ // If curl is not available, fallback to http.Get() |
|
355 | 355 |
resp, err = Download(u.String(), file) |
356 | 356 |
if err != nil { |
357 | 357 |
return err |
... | ... |
@@ -362,7 +362,7 @@ func (srv *Server) ImageImport(src, repo, tag string, file *os.File) error { |
362 | 362 |
if err != nil { |
363 | 363 |
return err |
364 | 364 |
} |
365 |
- // Optionally register the image at REPO/TAG |
|
365 |
+ // Optionally register the image at REPO/TAG |
|
366 | 366 |
if repo != "" { |
367 | 367 |
if err := srv.runtime.repositories.Set(repo, tag, img.Id, true); err != nil { |
368 | 368 |
return err |