Browse code

move container files to a separate folder. Following changes will update them.

Signed-off-by: Dong Chen <dongluo.chen@docker.com>

Dong Chen authored on 2015/11/05 10:27:21
Showing 8 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,469 @@
0
+package local
1
+
2
+import (
3
+	"fmt"
4
+	"io"
5
+	"net/http"
6
+	"strconv"
7
+	"strings"
8
+	"syscall"
9
+	"time"
10
+
11
+	"github.com/Sirupsen/logrus"
12
+	"github.com/docker/distribution/registry/api/errcode"
13
+	"github.com/docker/docker/api/server/httputils"
14
+	"github.com/docker/docker/api/types"
15
+	"github.com/docker/docker/daemon"
16
+	derr "github.com/docker/docker/errors"
17
+	"github.com/docker/docker/pkg/ioutils"
18
+	"github.com/docker/docker/pkg/signal"
19
+	"github.com/docker/docker/pkg/timeutils"
20
+	"github.com/docker/docker/runconfig"
21
+	"github.com/docker/docker/utils"
22
+	"golang.org/x/net/context"
23
+	"golang.org/x/net/websocket"
24
+)
25
+
26
+func (s *router) getContainersJSON(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
27
+	if err := httputils.ParseForm(r); err != nil {
28
+		return err
29
+	}
30
+
31
+	config := &daemon.ContainersConfig{
32
+		All:     httputils.BoolValue(r, "all"),
33
+		Size:    httputils.BoolValue(r, "size"),
34
+		Since:   r.Form.Get("since"),
35
+		Before:  r.Form.Get("before"),
36
+		Filters: r.Form.Get("filters"),
37
+	}
38
+
39
+	if tmpLimit := r.Form.Get("limit"); tmpLimit != "" {
40
+		limit, err := strconv.Atoi(tmpLimit)
41
+		if err != nil {
42
+			return err
43
+		}
44
+		config.Limit = limit
45
+	}
46
+
47
+	containers, err := s.daemon.Containers(config)
48
+	if err != nil {
49
+		return err
50
+	}
51
+
52
+	return httputils.WriteJSON(w, http.StatusOK, containers)
53
+}
54
+
55
+func (s *router) getContainersStats(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
56
+	if err := httputils.ParseForm(r); err != nil {
57
+		return err
58
+	}
59
+
60
+	stream := httputils.BoolValueOrDefault(r, "stream", true)
61
+	var out io.Writer
62
+	if !stream {
63
+		w.Header().Set("Content-Type", "application/json")
64
+		out = w
65
+	} else {
66
+		wf := ioutils.NewWriteFlusher(w)
67
+		out = wf
68
+		defer wf.Close()
69
+	}
70
+
71
+	var closeNotifier <-chan bool
72
+	if notifier, ok := w.(http.CloseNotifier); ok {
73
+		closeNotifier = notifier.CloseNotify()
74
+	}
75
+
76
+	config := &daemon.ContainerStatsConfig{
77
+		Stream:    stream,
78
+		OutStream: out,
79
+		Stop:      closeNotifier,
80
+		Version:   httputils.VersionFromContext(ctx),
81
+	}
82
+
83
+	return s.daemon.ContainerStats(vars["name"], config)
84
+}
85
+
86
+func (s *router) getContainersLogs(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
87
+	if err := httputils.ParseForm(r); err != nil {
88
+		return err
89
+	}
90
+
91
+	// Args are validated before the stream starts because when it starts we're
92
+	// sending HTTP 200 by writing an empty chunk of data to tell the client that
93
+	// daemon is going to stream. By sending this initial HTTP 200 we can't report
94
+	// any error after the stream starts (i.e. container not found, wrong parameters)
95
+	// with the appropriate status code.
96
+	stdout, stderr := httputils.BoolValue(r, "stdout"), httputils.BoolValue(r, "stderr")
97
+	if !(stdout || stderr) {
98
+		return fmt.Errorf("Bad parameters: you must choose at least one stream")
99
+	}
100
+
101
+	var since time.Time
102
+	if r.Form.Get("since") != "" {
103
+		s, n, err := timeutils.ParseTimestamps(r.Form.Get("since"), 0)
104
+		if err != nil {
105
+			return err
106
+		}
107
+		since = time.Unix(s, n)
108
+	}
109
+
110
+	var closeNotifier <-chan bool
111
+	if notifier, ok := w.(http.CloseNotifier); ok {
112
+		closeNotifier = notifier.CloseNotify()
113
+	}
114
+
115
+	containerName := vars["name"]
116
+
117
+	if !s.daemon.Exists(containerName) {
118
+		return derr.ErrorCodeNoSuchContainer.WithArgs(containerName)
119
+	}
120
+
121
+	// write an empty chunk of data (this is to ensure that the
122
+	// HTTP Response is sent immediately, even if the container has
123
+	// not yet produced any data)
124
+	w.WriteHeader(http.StatusOK)
125
+	if flusher, ok := w.(http.Flusher); ok {
126
+		flusher.Flush()
127
+	}
128
+
129
+	output := ioutils.NewWriteFlusher(w)
130
+	defer output.Close()
131
+
132
+	logsConfig := &daemon.ContainerLogsConfig{
133
+		Follow:     httputils.BoolValue(r, "follow"),
134
+		Timestamps: httputils.BoolValue(r, "timestamps"),
135
+		Since:      since,
136
+		Tail:       r.Form.Get("tail"),
137
+		UseStdout:  stdout,
138
+		UseStderr:  stderr,
139
+		OutStream:  output,
140
+		Stop:       closeNotifier,
141
+	}
142
+
143
+	if err := s.daemon.ContainerLogs(containerName, logsConfig); err != nil {
144
+		// The client may be expecting all of the data we're sending to
145
+		// be multiplexed, so send it through OutStream, which will
146
+		// have been set up to handle that if needed.
147
+		fmt.Fprintf(logsConfig.OutStream, "Error running logs job: %s\n", utils.GetErrorMessage(err))
148
+	}
149
+
150
+	return nil
151
+}
152
+
153
+func (s *router) getContainersExport(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
154
+	return s.daemon.ContainerExport(vars["name"], w)
155
+}
156
+
157
+func (s *router) postContainersStart(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
158
+	// If contentLength is -1, we can assumed chunked encoding
159
+	// or more technically that the length is unknown
160
+	// https://golang.org/src/pkg/net/http/request.go#L139
161
+	// net/http otherwise seems to swallow any headers related to chunked encoding
162
+	// including r.TransferEncoding
163
+	// allow a nil body for backwards compatibility
164
+	var hostConfig *runconfig.HostConfig
165
+	if r.Body != nil && (r.ContentLength > 0 || r.ContentLength == -1) {
166
+		if err := httputils.CheckForJSON(r); err != nil {
167
+			return err
168
+		}
169
+
170
+		c, err := runconfig.DecodeHostConfig(r.Body)
171
+		if err != nil {
172
+			return err
173
+		}
174
+
175
+		hostConfig = c
176
+	}
177
+
178
+	if err := s.daemon.ContainerStart(vars["name"], hostConfig); err != nil {
179
+		return err
180
+	}
181
+	w.WriteHeader(http.StatusNoContent)
182
+	return nil
183
+}
184
+
185
+func (s *router) postContainersStop(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
186
+	if err := httputils.ParseForm(r); err != nil {
187
+		return err
188
+	}
189
+
190
+	seconds, _ := strconv.Atoi(r.Form.Get("t"))
191
+
192
+	if err := s.daemon.ContainerStop(vars["name"], seconds); err != nil {
193
+		return err
194
+	}
195
+	w.WriteHeader(http.StatusNoContent)
196
+
197
+	return nil
198
+}
199
+
200
+func (s *router) postContainersKill(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
201
+	if err := httputils.ParseForm(r); err != nil {
202
+		return err
203
+	}
204
+
205
+	var sig syscall.Signal
206
+	name := vars["name"]
207
+
208
+	// If we have a signal, look at it. Otherwise, do nothing
209
+	if sigStr := r.Form.Get("signal"); sigStr != "" {
210
+		var err error
211
+		if sig, err = signal.ParseSignal(sigStr); err != nil {
212
+			return err
213
+		}
214
+	}
215
+
216
+	if err := s.daemon.ContainerKill(name, uint64(sig)); err != nil {
217
+		theErr, isDerr := err.(errcode.ErrorCoder)
218
+		isStopped := isDerr && theErr.ErrorCode() == derr.ErrorCodeNotRunning
219
+
220
+		// Return error that's not caused because the container is stopped.
221
+		// Return error if the container is not running and the api is >= 1.20
222
+		// to keep backwards compatibility.
223
+		version := httputils.VersionFromContext(ctx)
224
+		if version.GreaterThanOrEqualTo("1.20") || !isStopped {
225
+			return fmt.Errorf("Cannot kill container %s: %v", name, err)
226
+		}
227
+	}
228
+
229
+	w.WriteHeader(http.StatusNoContent)
230
+	return nil
231
+}
232
+
233
+func (s *router) postContainersRestart(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
234
+	if err := httputils.ParseForm(r); err != nil {
235
+		return err
236
+	}
237
+
238
+	timeout, _ := strconv.Atoi(r.Form.Get("t"))
239
+
240
+	if err := s.daemon.ContainerRestart(vars["name"], timeout); err != nil {
241
+		return err
242
+	}
243
+
244
+	w.WriteHeader(http.StatusNoContent)
245
+
246
+	return nil
247
+}
248
+
249
+func (s *router) postContainersPause(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
250
+	if err := httputils.ParseForm(r); err != nil {
251
+		return err
252
+	}
253
+
254
+	if err := s.daemon.ContainerPause(vars["name"]); err != nil {
255
+		return err
256
+	}
257
+
258
+	w.WriteHeader(http.StatusNoContent)
259
+
260
+	return nil
261
+}
262
+
263
+func (s *router) postContainersUnpause(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
264
+	if err := httputils.ParseForm(r); err != nil {
265
+		return err
266
+	}
267
+
268
+	if err := s.daemon.ContainerUnpause(vars["name"]); err != nil {
269
+		return err
270
+	}
271
+
272
+	w.WriteHeader(http.StatusNoContent)
273
+
274
+	return nil
275
+}
276
+
277
+func (s *router) postContainersWait(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
278
+	status, err := s.daemon.ContainerWait(vars["name"], -1*time.Second)
279
+	if err != nil {
280
+		return err
281
+	}
282
+
283
+	return httputils.WriteJSON(w, http.StatusOK, &types.ContainerWaitResponse{
284
+		StatusCode: status,
285
+	})
286
+}
287
+
288
+func (s *router) getContainersChanges(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
289
+	changes, err := s.daemon.ContainerChanges(vars["name"])
290
+	if err != nil {
291
+		return err
292
+	}
293
+
294
+	return httputils.WriteJSON(w, http.StatusOK, changes)
295
+}
296
+
297
+func (s *router) getContainersTop(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
298
+	if err := httputils.ParseForm(r); err != nil {
299
+		return err
300
+	}
301
+
302
+	procList, err := s.daemon.ContainerTop(vars["name"], r.Form.Get("ps_args"))
303
+	if err != nil {
304
+		return err
305
+	}
306
+
307
+	return httputils.WriteJSON(w, http.StatusOK, procList)
308
+}
309
+
310
+func (s *router) postContainerRename(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
311
+	if err := httputils.ParseForm(r); err != nil {
312
+		return err
313
+	}
314
+
315
+	name := vars["name"]
316
+	newName := r.Form.Get("name")
317
+	if err := s.daemon.ContainerRename(name, newName); err != nil {
318
+		return err
319
+	}
320
+	w.WriteHeader(http.StatusNoContent)
321
+	return nil
322
+}
323
+
324
+func (s *router) postContainersCreate(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
325
+	if err := httputils.ParseForm(r); err != nil {
326
+		return err
327
+	}
328
+	if err := httputils.CheckForJSON(r); err != nil {
329
+		return err
330
+	}
331
+
332
+	name := r.Form.Get("name")
333
+
334
+	config, hostConfig, err := runconfig.DecodeContainerConfig(r.Body)
335
+	if err != nil {
336
+		return err
337
+	}
338
+	version := httputils.VersionFromContext(ctx)
339
+	adjustCPUShares := version.LessThan("1.19")
340
+
341
+	ccr, err := s.daemon.ContainerCreate(&daemon.ContainerCreateConfig{
342
+		Name:            name,
343
+		Config:          config,
344
+		HostConfig:      hostConfig,
345
+		AdjustCPUShares: adjustCPUShares,
346
+	})
347
+	if err != nil {
348
+		return err
349
+	}
350
+
351
+	return httputils.WriteJSON(w, http.StatusCreated, ccr)
352
+}
353
+
354
+func (s *router) deleteContainers(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
355
+	if err := httputils.ParseForm(r); err != nil {
356
+		return err
357
+	}
358
+
359
+	name := vars["name"]
360
+	config := &daemon.ContainerRmConfig{
361
+		ForceRemove:  httputils.BoolValue(r, "force"),
362
+		RemoveVolume: httputils.BoolValue(r, "v"),
363
+		RemoveLink:   httputils.BoolValue(r, "link"),
364
+	}
365
+
366
+	if err := s.daemon.ContainerRm(name, config); err != nil {
367
+		// Force a 404 for the empty string
368
+		if strings.Contains(strings.ToLower(err.Error()), "prefix can't be empty") {
369
+			return fmt.Errorf("no such id: \"\"")
370
+		}
371
+		return err
372
+	}
373
+
374
+	w.WriteHeader(http.StatusNoContent)
375
+
376
+	return nil
377
+}
378
+
379
+func (s *router) postContainersResize(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
380
+	if err := httputils.ParseForm(r); err != nil {
381
+		return err
382
+	}
383
+
384
+	height, err := strconv.Atoi(r.Form.Get("h"))
385
+	if err != nil {
386
+		return err
387
+	}
388
+	width, err := strconv.Atoi(r.Form.Get("w"))
389
+	if err != nil {
390
+		return err
391
+	}
392
+
393
+	return s.daemon.ContainerResize(vars["name"], height, width)
394
+}
395
+
396
+func (s *router) postContainersAttach(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
397
+	if err := httputils.ParseForm(r); err != nil {
398
+		return err
399
+	}
400
+	containerName := vars["name"]
401
+
402
+	if !s.daemon.Exists(containerName) {
403
+		return derr.ErrorCodeNoSuchContainer.WithArgs(containerName)
404
+	}
405
+
406
+	if s.daemon.IsPaused(containerName) {
407
+		return derr.ErrorCodePausedContainer.WithArgs(containerName)
408
+	}
409
+
410
+	inStream, outStream, err := httputils.HijackConnection(w)
411
+	if err != nil {
412
+		return err
413
+	}
414
+	defer httputils.CloseStreams(inStream, outStream)
415
+
416
+	if _, ok := r.Header["Upgrade"]; ok {
417
+		fmt.Fprintf(outStream, "HTTP/1.1 101 UPGRADED\r\nContent-Type: application/vnd.docker.raw-stream\r\nConnection: Upgrade\r\nUpgrade: tcp\r\n\r\n")
418
+	} else {
419
+		fmt.Fprintf(outStream, "HTTP/1.1 200 OK\r\nContent-Type: application/vnd.docker.raw-stream\r\n\r\n")
420
+	}
421
+
422
+	attachWithLogsConfig := &daemon.ContainerAttachWithLogsConfig{
423
+		InStream:  inStream,
424
+		OutStream: outStream,
425
+		UseStdin:  httputils.BoolValue(r, "stdin"),
426
+		UseStdout: httputils.BoolValue(r, "stdout"),
427
+		UseStderr: httputils.BoolValue(r, "stderr"),
428
+		Logs:      httputils.BoolValue(r, "logs"),
429
+		Stream:    httputils.BoolValue(r, "stream"),
430
+	}
431
+
432
+	if err := s.daemon.ContainerAttachWithLogs(containerName, attachWithLogsConfig); err != nil {
433
+		fmt.Fprintf(outStream, "Error attaching: %s\n", err)
434
+	}
435
+
436
+	return nil
437
+}
438
+
439
+func (s *router) wsContainersAttach(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
440
+	if err := httputils.ParseForm(r); err != nil {
441
+		return err
442
+	}
443
+	containerName := vars["name"]
444
+
445
+	if !s.daemon.Exists(containerName) {
446
+		return derr.ErrorCodeNoSuchContainer.WithArgs(containerName)
447
+	}
448
+
449
+	h := websocket.Handler(func(ws *websocket.Conn) {
450
+		defer ws.Close()
451
+
452
+		wsAttachWithLogsConfig := &daemon.ContainerWsAttachWithLogsConfig{
453
+			InStream:  ws,
454
+			OutStream: ws,
455
+			ErrStream: ws,
456
+			Logs:      httputils.BoolValue(r, "logs"),
457
+			Stream:    httputils.BoolValue(r, "stream"),
458
+		}
459
+
460
+		if err := s.daemon.ContainerWsAttachWithLogs(containerName, wsAttachWithLogsConfig); err != nil {
461
+			logrus.Errorf("Error attaching websocket: %s", err)
462
+		}
463
+	})
464
+	ws := websocket.Server{Handler: h, Handshake: nil}
465
+	ws.ServeHTTP(w, r)
466
+
467
+	return nil
468
+}
0 469
new file mode 100644
... ...
@@ -0,0 +1,112 @@
0
+package local
1
+
2
+import (
3
+	"encoding/base64"
4
+	"encoding/json"
5
+	"fmt"
6
+	"io"
7
+	"net/http"
8
+	"os"
9
+	"strings"
10
+
11
+	"github.com/docker/docker/api/server/httputils"
12
+	"github.com/docker/docker/api/types"
13
+	"golang.org/x/net/context"
14
+)
15
+
16
+// postContainersCopy is deprecated in favor of getContainersArchive.
17
+func (s *router) postContainersCopy(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
18
+	if err := httputils.CheckForJSON(r); err != nil {
19
+		return err
20
+	}
21
+
22
+	cfg := types.CopyConfig{}
23
+	if err := json.NewDecoder(r.Body).Decode(&cfg); err != nil {
24
+		return err
25
+	}
26
+
27
+	if cfg.Resource == "" {
28
+		return fmt.Errorf("Path cannot be empty")
29
+	}
30
+
31
+	data, err := s.daemon.ContainerCopy(vars["name"], cfg.Resource)
32
+	if err != nil {
33
+		if strings.Contains(strings.ToLower(err.Error()), "no such id") {
34
+			w.WriteHeader(http.StatusNotFound)
35
+			return nil
36
+		}
37
+		if os.IsNotExist(err) {
38
+			return fmt.Errorf("Could not find the file %s in container %s", cfg.Resource, vars["name"])
39
+		}
40
+		return err
41
+	}
42
+	defer data.Close()
43
+
44
+	w.Header().Set("Content-Type", "application/x-tar")
45
+	if _, err := io.Copy(w, data); err != nil {
46
+		return err
47
+	}
48
+
49
+	return nil
50
+}
51
+
52
+// // Encode the stat to JSON, base64 encode, and place in a header.
53
+func setContainerPathStatHeader(stat *types.ContainerPathStat, header http.Header) error {
54
+	statJSON, err := json.Marshal(stat)
55
+	if err != nil {
56
+		return err
57
+	}
58
+
59
+	header.Set(
60
+		"X-Docker-Container-Path-Stat",
61
+		base64.StdEncoding.EncodeToString(statJSON),
62
+	)
63
+
64
+	return nil
65
+}
66
+
67
+func (s *router) headContainersArchive(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
68
+	v, err := httputils.ArchiveFormValues(r, vars)
69
+	if err != nil {
70
+		return err
71
+	}
72
+
73
+	stat, err := s.daemon.ContainerStatPath(v.Name, v.Path)
74
+	if err != nil {
75
+		return err
76
+	}
77
+
78
+	return setContainerPathStatHeader(stat, w.Header())
79
+}
80
+
81
+func (s *router) getContainersArchive(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
82
+	v, err := httputils.ArchiveFormValues(r, vars)
83
+	if err != nil {
84
+		return err
85
+	}
86
+
87
+	tarArchive, stat, err := s.daemon.ContainerArchivePath(v.Name, v.Path)
88
+	if err != nil {
89
+		return err
90
+	}
91
+	defer tarArchive.Close()
92
+
93
+	if err := setContainerPathStatHeader(stat, w.Header()); err != nil {
94
+		return err
95
+	}
96
+
97
+	w.Header().Set("Content-Type", "application/x-tar")
98
+	_, err = io.Copy(w, tarArchive)
99
+
100
+	return err
101
+}
102
+
103
+func (s *router) putContainersArchive(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
104
+	v, err := httputils.ArchiveFormValues(r, vars)
105
+	if err != nil {
106
+		return err
107
+	}
108
+
109
+	noOverwriteDirNonDir := httputils.BoolValue(r, "noOverwriteDirNonDir")
110
+	return s.daemon.ContainerExtractToDir(v.Name, v.Path, noOverwriteDirNonDir, r.Body)
111
+}
0 112
new file mode 100644
... ...
@@ -0,0 +1,135 @@
0
+package local
1
+
2
+import (
3
+	"encoding/json"
4
+	"fmt"
5
+	"io"
6
+	"net/http"
7
+	"strconv"
8
+
9
+	"github.com/Sirupsen/logrus"
10
+	"github.com/docker/docker/api/server/httputils"
11
+	"github.com/docker/docker/api/types"
12
+	"github.com/docker/docker/pkg/stdcopy"
13
+	"github.com/docker/docker/runconfig"
14
+	"golang.org/x/net/context"
15
+)
16
+
17
+func (s *router) getExecByID(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
18
+	eConfig, err := s.daemon.ContainerExecInspect(vars["id"])
19
+	if err != nil {
20
+		return err
21
+	}
22
+
23
+	return httputils.WriteJSON(w, http.StatusOK, eConfig)
24
+}
25
+
26
+func (s *router) postContainerExecCreate(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
27
+	if err := httputils.ParseForm(r); err != nil {
28
+		return err
29
+	}
30
+	if err := httputils.CheckForJSON(r); err != nil {
31
+		return err
32
+	}
33
+	name := vars["name"]
34
+
35
+	execConfig := &runconfig.ExecConfig{}
36
+	if err := json.NewDecoder(r.Body).Decode(execConfig); err != nil {
37
+		return err
38
+	}
39
+	execConfig.Container = name
40
+
41
+	if len(execConfig.Cmd) == 0 {
42
+		return fmt.Errorf("No exec command specified")
43
+	}
44
+
45
+	// Register an instance of Exec in container.
46
+	id, err := s.daemon.ContainerExecCreate(execConfig)
47
+	if err != nil {
48
+		logrus.Errorf("Error setting up exec command in container %s: %s", name, err)
49
+		return err
50
+	}
51
+
52
+	return httputils.WriteJSON(w, http.StatusCreated, &types.ContainerExecCreateResponse{
53
+		ID: id,
54
+	})
55
+}
56
+
57
+// TODO(vishh): Refactor the code to avoid having to specify stream config as part of both create and start.
58
+func (s *router) postContainerExecStart(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
59
+	if err := httputils.ParseForm(r); err != nil {
60
+		return err
61
+	}
62
+
63
+	version := httputils.VersionFromContext(ctx)
64
+	if version.GreaterThan("1.21") {
65
+		if err := httputils.CheckForJSON(r); err != nil {
66
+			return err
67
+		}
68
+	}
69
+
70
+	var (
71
+		execName                  = vars["name"]
72
+		stdin, inStream           io.ReadCloser
73
+		stdout, stderr, outStream io.Writer
74
+	)
75
+
76
+	execStartCheck := &types.ExecStartCheck{}
77
+	if err := json.NewDecoder(r.Body).Decode(execStartCheck); err != nil {
78
+		return err
79
+	}
80
+
81
+	if exists, err := s.daemon.ExecExists(execName); !exists {
82
+		return err
83
+	}
84
+
85
+	if !execStartCheck.Detach {
86
+		var err error
87
+		// Setting up the streaming http interface.
88
+		inStream, outStream, err = httputils.HijackConnection(w)
89
+		if err != nil {
90
+			return err
91
+		}
92
+		defer httputils.CloseStreams(inStream, outStream)
93
+
94
+		if _, ok := r.Header["Upgrade"]; ok {
95
+			fmt.Fprintf(outStream, "HTTP/1.1 101 UPGRADED\r\nContent-Type: application/vnd.docker.raw-stream\r\nConnection: Upgrade\r\nUpgrade: tcp\r\n\r\n")
96
+		} else {
97
+			fmt.Fprintf(outStream, "HTTP/1.1 200 OK\r\nContent-Type: application/vnd.docker.raw-stream\r\n\r\n")
98
+		}
99
+
100
+		stdin = inStream
101
+		stdout = outStream
102
+		if !execStartCheck.Tty {
103
+			stderr = stdcopy.NewStdWriter(outStream, stdcopy.Stderr)
104
+			stdout = stdcopy.NewStdWriter(outStream, stdcopy.Stdout)
105
+		}
106
+	} else {
107
+		outStream = w
108
+	}
109
+
110
+	// Now run the user process in container.
111
+	if err := s.daemon.ContainerExecStart(execName, stdin, stdout, stderr); err != nil {
112
+		if execStartCheck.Detach {
113
+			return err
114
+		}
115
+		logrus.Errorf("Error running exec in container: %v\n", err)
116
+	}
117
+	return nil
118
+}
119
+
120
+func (s *router) postContainerExecResize(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
121
+	if err := httputils.ParseForm(r); err != nil {
122
+		return err
123
+	}
124
+	height, err := strconv.Atoi(r.Form.Get("h"))
125
+	if err != nil {
126
+		return err
127
+	}
128
+	width, err := strconv.Atoi(r.Form.Get("w"))
129
+	if err != nil {
130
+		return err
131
+	}
132
+
133
+	return s.daemon.ContainerExecResize(vars["name"], height, width)
134
+}
0 135
new file mode 100644
... ...
@@ -0,0 +1,33 @@
0
+package local
1
+
2
+import (
3
+	"net/http"
4
+
5
+	"github.com/docker/docker/api/server/httputils"
6
+	"golang.org/x/net/context"
7
+)
8
+
9
+// getContainersByName inspects containers configuration and serializes it as json.
10
+func (s *router) getContainersByName(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
11
+	displaySize := httputils.BoolValue(r, "size")
12
+
13
+	var json interface{}
14
+	var err error
15
+
16
+	version := httputils.VersionFromContext(ctx)
17
+
18
+	switch {
19
+	case version.LessThan("1.20"):
20
+		json, err = s.daemon.ContainerInspectPre120(vars["name"])
21
+	case version.Equal("1.20"):
22
+		json, err = s.daemon.ContainerInspect120(vars["name"])
23
+	default:
24
+		json, err = s.daemon.ContainerInspect(vars["name"], displaySize)
25
+	}
26
+
27
+	if err != nil {
28
+		return err
29
+	}
30
+
31
+	return httputils.WriteJSON(w, http.StatusOK, json)
32
+}
0 33
deleted file mode 100644
... ...
@@ -1,469 +0,0 @@
1
-package local
2
-
3
-import (
4
-	"fmt"
5
-	"io"
6
-	"net/http"
7
-	"strconv"
8
-	"strings"
9
-	"syscall"
10
-	"time"
11
-
12
-	"github.com/Sirupsen/logrus"
13
-	"github.com/docker/distribution/registry/api/errcode"
14
-	"github.com/docker/docker/api/server/httputils"
15
-	"github.com/docker/docker/api/types"
16
-	"github.com/docker/docker/daemon"
17
-	derr "github.com/docker/docker/errors"
18
-	"github.com/docker/docker/pkg/ioutils"
19
-	"github.com/docker/docker/pkg/signal"
20
-	"github.com/docker/docker/pkg/timeutils"
21
-	"github.com/docker/docker/runconfig"
22
-	"github.com/docker/docker/utils"
23
-	"golang.org/x/net/context"
24
-	"golang.org/x/net/websocket"
25
-)
26
-
27
-func (s *router) getContainersJSON(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
28
-	if err := httputils.ParseForm(r); err != nil {
29
-		return err
30
-	}
31
-
32
-	config := &daemon.ContainersConfig{
33
-		All:     httputils.BoolValue(r, "all"),
34
-		Size:    httputils.BoolValue(r, "size"),
35
-		Since:   r.Form.Get("since"),
36
-		Before:  r.Form.Get("before"),
37
-		Filters: r.Form.Get("filters"),
38
-	}
39
-
40
-	if tmpLimit := r.Form.Get("limit"); tmpLimit != "" {
41
-		limit, err := strconv.Atoi(tmpLimit)
42
-		if err != nil {
43
-			return err
44
-		}
45
-		config.Limit = limit
46
-	}
47
-
48
-	containers, err := s.daemon.Containers(config)
49
-	if err != nil {
50
-		return err
51
-	}
52
-
53
-	return httputils.WriteJSON(w, http.StatusOK, containers)
54
-}
55
-
56
-func (s *router) getContainersStats(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
57
-	if err := httputils.ParseForm(r); err != nil {
58
-		return err
59
-	}
60
-
61
-	stream := httputils.BoolValueOrDefault(r, "stream", true)
62
-	var out io.Writer
63
-	if !stream {
64
-		w.Header().Set("Content-Type", "application/json")
65
-		out = w
66
-	} else {
67
-		wf := ioutils.NewWriteFlusher(w)
68
-		out = wf
69
-		defer wf.Close()
70
-	}
71
-
72
-	var closeNotifier <-chan bool
73
-	if notifier, ok := w.(http.CloseNotifier); ok {
74
-		closeNotifier = notifier.CloseNotify()
75
-	}
76
-
77
-	config := &daemon.ContainerStatsConfig{
78
-		Stream:    stream,
79
-		OutStream: out,
80
-		Stop:      closeNotifier,
81
-		Version:   httputils.VersionFromContext(ctx),
82
-	}
83
-
84
-	return s.daemon.ContainerStats(vars["name"], config)
85
-}
86
-
87
-func (s *router) getContainersLogs(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
88
-	if err := httputils.ParseForm(r); err != nil {
89
-		return err
90
-	}
91
-
92
-	// Args are validated before the stream starts because when it starts we're
93
-	// sending HTTP 200 by writing an empty chunk of data to tell the client that
94
-	// daemon is going to stream. By sending this initial HTTP 200 we can't report
95
-	// any error after the stream starts (i.e. container not found, wrong parameters)
96
-	// with the appropriate status code.
97
-	stdout, stderr := httputils.BoolValue(r, "stdout"), httputils.BoolValue(r, "stderr")
98
-	if !(stdout || stderr) {
99
-		return fmt.Errorf("Bad parameters: you must choose at least one stream")
100
-	}
101
-
102
-	var since time.Time
103
-	if r.Form.Get("since") != "" {
104
-		s, n, err := timeutils.ParseTimestamps(r.Form.Get("since"), 0)
105
-		if err != nil {
106
-			return err
107
-		}
108
-		since = time.Unix(s, n)
109
-	}
110
-
111
-	var closeNotifier <-chan bool
112
-	if notifier, ok := w.(http.CloseNotifier); ok {
113
-		closeNotifier = notifier.CloseNotify()
114
-	}
115
-
116
-	containerName := vars["name"]
117
-
118
-	if !s.daemon.Exists(containerName) {
119
-		return derr.ErrorCodeNoSuchContainer.WithArgs(containerName)
120
-	}
121
-
122
-	// write an empty chunk of data (this is to ensure that the
123
-	// HTTP Response is sent immediately, even if the container has
124
-	// not yet produced any data)
125
-	w.WriteHeader(http.StatusOK)
126
-	if flusher, ok := w.(http.Flusher); ok {
127
-		flusher.Flush()
128
-	}
129
-
130
-	output := ioutils.NewWriteFlusher(w)
131
-	defer output.Close()
132
-
133
-	logsConfig := &daemon.ContainerLogsConfig{
134
-		Follow:     httputils.BoolValue(r, "follow"),
135
-		Timestamps: httputils.BoolValue(r, "timestamps"),
136
-		Since:      since,
137
-		Tail:       r.Form.Get("tail"),
138
-		UseStdout:  stdout,
139
-		UseStderr:  stderr,
140
-		OutStream:  output,
141
-		Stop:       closeNotifier,
142
-	}
143
-
144
-	if err := s.daemon.ContainerLogs(containerName, logsConfig); err != nil {
145
-		// The client may be expecting all of the data we're sending to
146
-		// be multiplexed, so send it through OutStream, which will
147
-		// have been set up to handle that if needed.
148
-		fmt.Fprintf(logsConfig.OutStream, "Error running logs job: %s\n", utils.GetErrorMessage(err))
149
-	}
150
-
151
-	return nil
152
-}
153
-
154
-func (s *router) getContainersExport(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
155
-	return s.daemon.ContainerExport(vars["name"], w)
156
-}
157
-
158
-func (s *router) postContainersStart(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
159
-	// If contentLength is -1, we can assumed chunked encoding
160
-	// or more technically that the length is unknown
161
-	// https://golang.org/src/pkg/net/http/request.go#L139
162
-	// net/http otherwise seems to swallow any headers related to chunked encoding
163
-	// including r.TransferEncoding
164
-	// allow a nil body for backwards compatibility
165
-	var hostConfig *runconfig.HostConfig
166
-	if r.Body != nil && (r.ContentLength > 0 || r.ContentLength == -1) {
167
-		if err := httputils.CheckForJSON(r); err != nil {
168
-			return err
169
-		}
170
-
171
-		c, err := runconfig.DecodeHostConfig(r.Body)
172
-		if err != nil {
173
-			return err
174
-		}
175
-
176
-		hostConfig = c
177
-	}
178
-
179
-	if err := s.daemon.ContainerStart(vars["name"], hostConfig); err != nil {
180
-		return err
181
-	}
182
-	w.WriteHeader(http.StatusNoContent)
183
-	return nil
184
-}
185
-
186
-func (s *router) postContainersStop(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
187
-	if err := httputils.ParseForm(r); err != nil {
188
-		return err
189
-	}
190
-
191
-	seconds, _ := strconv.Atoi(r.Form.Get("t"))
192
-
193
-	if err := s.daemon.ContainerStop(vars["name"], seconds); err != nil {
194
-		return err
195
-	}
196
-	w.WriteHeader(http.StatusNoContent)
197
-
198
-	return nil
199
-}
200
-
201
-func (s *router) postContainersKill(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
202
-	if err := httputils.ParseForm(r); err != nil {
203
-		return err
204
-	}
205
-
206
-	var sig syscall.Signal
207
-	name := vars["name"]
208
-
209
-	// If we have a signal, look at it. Otherwise, do nothing
210
-	if sigStr := r.Form.Get("signal"); sigStr != "" {
211
-		var err error
212
-		if sig, err = signal.ParseSignal(sigStr); err != nil {
213
-			return err
214
-		}
215
-	}
216
-
217
-	if err := s.daemon.ContainerKill(name, uint64(sig)); err != nil {
218
-		theErr, isDerr := err.(errcode.ErrorCoder)
219
-		isStopped := isDerr && theErr.ErrorCode() == derr.ErrorCodeNotRunning
220
-
221
-		// Return error that's not caused because the container is stopped.
222
-		// Return error if the container is not running and the api is >= 1.20
223
-		// to keep backwards compatibility.
224
-		version := httputils.VersionFromContext(ctx)
225
-		if version.GreaterThanOrEqualTo("1.20") || !isStopped {
226
-			return fmt.Errorf("Cannot kill container %s: %v", name, err)
227
-		}
228
-	}
229
-
230
-	w.WriteHeader(http.StatusNoContent)
231
-	return nil
232
-}
233
-
234
-func (s *router) postContainersRestart(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
235
-	if err := httputils.ParseForm(r); err != nil {
236
-		return err
237
-	}
238
-
239
-	timeout, _ := strconv.Atoi(r.Form.Get("t"))
240
-
241
-	if err := s.daemon.ContainerRestart(vars["name"], timeout); err != nil {
242
-		return err
243
-	}
244
-
245
-	w.WriteHeader(http.StatusNoContent)
246
-
247
-	return nil
248
-}
249
-
250
-func (s *router) postContainersPause(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
251
-	if err := httputils.ParseForm(r); err != nil {
252
-		return err
253
-	}
254
-
255
-	if err := s.daemon.ContainerPause(vars["name"]); err != nil {
256
-		return err
257
-	}
258
-
259
-	w.WriteHeader(http.StatusNoContent)
260
-
261
-	return nil
262
-}
263
-
264
-func (s *router) postContainersUnpause(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
265
-	if err := httputils.ParseForm(r); err != nil {
266
-		return err
267
-	}
268
-
269
-	if err := s.daemon.ContainerUnpause(vars["name"]); err != nil {
270
-		return err
271
-	}
272
-
273
-	w.WriteHeader(http.StatusNoContent)
274
-
275
-	return nil
276
-}
277
-
278
-func (s *router) postContainersWait(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
279
-	status, err := s.daemon.ContainerWait(vars["name"], -1*time.Second)
280
-	if err != nil {
281
-		return err
282
-	}
283
-
284
-	return httputils.WriteJSON(w, http.StatusOK, &types.ContainerWaitResponse{
285
-		StatusCode: status,
286
-	})
287
-}
288
-
289
-func (s *router) getContainersChanges(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
290
-	changes, err := s.daemon.ContainerChanges(vars["name"])
291
-	if err != nil {
292
-		return err
293
-	}
294
-
295
-	return httputils.WriteJSON(w, http.StatusOK, changes)
296
-}
297
-
298
-func (s *router) getContainersTop(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
299
-	if err := httputils.ParseForm(r); err != nil {
300
-		return err
301
-	}
302
-
303
-	procList, err := s.daemon.ContainerTop(vars["name"], r.Form.Get("ps_args"))
304
-	if err != nil {
305
-		return err
306
-	}
307
-
308
-	return httputils.WriteJSON(w, http.StatusOK, procList)
309
-}
310
-
311
-func (s *router) postContainerRename(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
312
-	if err := httputils.ParseForm(r); err != nil {
313
-		return err
314
-	}
315
-
316
-	name := vars["name"]
317
-	newName := r.Form.Get("name")
318
-	if err := s.daemon.ContainerRename(name, newName); err != nil {
319
-		return err
320
-	}
321
-	w.WriteHeader(http.StatusNoContent)
322
-	return nil
323
-}
324
-
325
-func (s *router) postContainersCreate(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
326
-	if err := httputils.ParseForm(r); err != nil {
327
-		return err
328
-	}
329
-	if err := httputils.CheckForJSON(r); err != nil {
330
-		return err
331
-	}
332
-
333
-	name := r.Form.Get("name")
334
-
335
-	config, hostConfig, err := runconfig.DecodeContainerConfig(r.Body)
336
-	if err != nil {
337
-		return err
338
-	}
339
-	version := httputils.VersionFromContext(ctx)
340
-	adjustCPUShares := version.LessThan("1.19")
341
-
342
-	ccr, err := s.daemon.ContainerCreate(&daemon.ContainerCreateConfig{
343
-		Name:            name,
344
-		Config:          config,
345
-		HostConfig:      hostConfig,
346
-		AdjustCPUShares: adjustCPUShares,
347
-	})
348
-	if err != nil {
349
-		return err
350
-	}
351
-
352
-	return httputils.WriteJSON(w, http.StatusCreated, ccr)
353
-}
354
-
355
-func (s *router) deleteContainers(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
356
-	if err := httputils.ParseForm(r); err != nil {
357
-		return err
358
-	}
359
-
360
-	name := vars["name"]
361
-	config := &daemon.ContainerRmConfig{
362
-		ForceRemove:  httputils.BoolValue(r, "force"),
363
-		RemoveVolume: httputils.BoolValue(r, "v"),
364
-		RemoveLink:   httputils.BoolValue(r, "link"),
365
-	}
366
-
367
-	if err := s.daemon.ContainerRm(name, config); err != nil {
368
-		// Force a 404 for the empty string
369
-		if strings.Contains(strings.ToLower(err.Error()), "prefix can't be empty") {
370
-			return fmt.Errorf("no such id: \"\"")
371
-		}
372
-		return err
373
-	}
374
-
375
-	w.WriteHeader(http.StatusNoContent)
376
-
377
-	return nil
378
-}
379
-
380
-func (s *router) postContainersResize(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
381
-	if err := httputils.ParseForm(r); err != nil {
382
-		return err
383
-	}
384
-
385
-	height, err := strconv.Atoi(r.Form.Get("h"))
386
-	if err != nil {
387
-		return err
388
-	}
389
-	width, err := strconv.Atoi(r.Form.Get("w"))
390
-	if err != nil {
391
-		return err
392
-	}
393
-
394
-	return s.daemon.ContainerResize(vars["name"], height, width)
395
-}
396
-
397
-func (s *router) postContainersAttach(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
398
-	if err := httputils.ParseForm(r); err != nil {
399
-		return err
400
-	}
401
-	containerName := vars["name"]
402
-
403
-	if !s.daemon.Exists(containerName) {
404
-		return derr.ErrorCodeNoSuchContainer.WithArgs(containerName)
405
-	}
406
-
407
-	if s.daemon.IsPaused(containerName) {
408
-		return derr.ErrorCodePausedContainer.WithArgs(containerName)
409
-	}
410
-
411
-	inStream, outStream, err := httputils.HijackConnection(w)
412
-	if err != nil {
413
-		return err
414
-	}
415
-	defer httputils.CloseStreams(inStream, outStream)
416
-
417
-	if _, ok := r.Header["Upgrade"]; ok {
418
-		fmt.Fprintf(outStream, "HTTP/1.1 101 UPGRADED\r\nContent-Type: application/vnd.docker.raw-stream\r\nConnection: Upgrade\r\nUpgrade: tcp\r\n\r\n")
419
-	} else {
420
-		fmt.Fprintf(outStream, "HTTP/1.1 200 OK\r\nContent-Type: application/vnd.docker.raw-stream\r\n\r\n")
421
-	}
422
-
423
-	attachWithLogsConfig := &daemon.ContainerAttachWithLogsConfig{
424
-		InStream:  inStream,
425
-		OutStream: outStream,
426
-		UseStdin:  httputils.BoolValue(r, "stdin"),
427
-		UseStdout: httputils.BoolValue(r, "stdout"),
428
-		UseStderr: httputils.BoolValue(r, "stderr"),
429
-		Logs:      httputils.BoolValue(r, "logs"),
430
-		Stream:    httputils.BoolValue(r, "stream"),
431
-	}
432
-
433
-	if err := s.daemon.ContainerAttachWithLogs(containerName, attachWithLogsConfig); err != nil {
434
-		fmt.Fprintf(outStream, "Error attaching: %s\n", err)
435
-	}
436
-
437
-	return nil
438
-}
439
-
440
-func (s *router) wsContainersAttach(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
441
-	if err := httputils.ParseForm(r); err != nil {
442
-		return err
443
-	}
444
-	containerName := vars["name"]
445
-
446
-	if !s.daemon.Exists(containerName) {
447
-		return derr.ErrorCodeNoSuchContainer.WithArgs(containerName)
448
-	}
449
-
450
-	h := websocket.Handler(func(ws *websocket.Conn) {
451
-		defer ws.Close()
452
-
453
-		wsAttachWithLogsConfig := &daemon.ContainerWsAttachWithLogsConfig{
454
-			InStream:  ws,
455
-			OutStream: ws,
456
-			ErrStream: ws,
457
-			Logs:      httputils.BoolValue(r, "logs"),
458
-			Stream:    httputils.BoolValue(r, "stream"),
459
-		}
460
-
461
-		if err := s.daemon.ContainerWsAttachWithLogs(containerName, wsAttachWithLogsConfig); err != nil {
462
-			logrus.Errorf("Error attaching websocket: %s", err)
463
-		}
464
-	})
465
-	ws := websocket.Server{Handler: h, Handshake: nil}
466
-	ws.ServeHTTP(w, r)
467
-
468
-	return nil
469
-}
470 1
deleted file mode 100644
... ...
@@ -1,112 +0,0 @@
1
-package local
2
-
3
-import (
4
-	"encoding/base64"
5
-	"encoding/json"
6
-	"fmt"
7
-	"io"
8
-	"net/http"
9
-	"os"
10
-	"strings"
11
-
12
-	"github.com/docker/docker/api/server/httputils"
13
-	"github.com/docker/docker/api/types"
14
-	"golang.org/x/net/context"
15
-)
16
-
17
-// postContainersCopy is deprecated in favor of getContainersArchive.
18
-func (s *router) postContainersCopy(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
19
-	if err := httputils.CheckForJSON(r); err != nil {
20
-		return err
21
-	}
22
-
23
-	cfg := types.CopyConfig{}
24
-	if err := json.NewDecoder(r.Body).Decode(&cfg); err != nil {
25
-		return err
26
-	}
27
-
28
-	if cfg.Resource == "" {
29
-		return fmt.Errorf("Path cannot be empty")
30
-	}
31
-
32
-	data, err := s.daemon.ContainerCopy(vars["name"], cfg.Resource)
33
-	if err != nil {
34
-		if strings.Contains(strings.ToLower(err.Error()), "no such id") {
35
-			w.WriteHeader(http.StatusNotFound)
36
-			return nil
37
-		}
38
-		if os.IsNotExist(err) {
39
-			return fmt.Errorf("Could not find the file %s in container %s", cfg.Resource, vars["name"])
40
-		}
41
-		return err
42
-	}
43
-	defer data.Close()
44
-
45
-	w.Header().Set("Content-Type", "application/x-tar")
46
-	if _, err := io.Copy(w, data); err != nil {
47
-		return err
48
-	}
49
-
50
-	return nil
51
-}
52
-
53
-// // Encode the stat to JSON, base64 encode, and place in a header.
54
-func setContainerPathStatHeader(stat *types.ContainerPathStat, header http.Header) error {
55
-	statJSON, err := json.Marshal(stat)
56
-	if err != nil {
57
-		return err
58
-	}
59
-
60
-	header.Set(
61
-		"X-Docker-Container-Path-Stat",
62
-		base64.StdEncoding.EncodeToString(statJSON),
63
-	)
64
-
65
-	return nil
66
-}
67
-
68
-func (s *router) headContainersArchive(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
69
-	v, err := httputils.ArchiveFormValues(r, vars)
70
-	if err != nil {
71
-		return err
72
-	}
73
-
74
-	stat, err := s.daemon.ContainerStatPath(v.Name, v.Path)
75
-	if err != nil {
76
-		return err
77
-	}
78
-
79
-	return setContainerPathStatHeader(stat, w.Header())
80
-}
81
-
82
-func (s *router) getContainersArchive(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
83
-	v, err := httputils.ArchiveFormValues(r, vars)
84
-	if err != nil {
85
-		return err
86
-	}
87
-
88
-	tarArchive, stat, err := s.daemon.ContainerArchivePath(v.Name, v.Path)
89
-	if err != nil {
90
-		return err
91
-	}
92
-	defer tarArchive.Close()
93
-
94
-	if err := setContainerPathStatHeader(stat, w.Header()); err != nil {
95
-		return err
96
-	}
97
-
98
-	w.Header().Set("Content-Type", "application/x-tar")
99
-	_, err = io.Copy(w, tarArchive)
100
-
101
-	return err
102
-}
103
-
104
-func (s *router) putContainersArchive(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
105
-	v, err := httputils.ArchiveFormValues(r, vars)
106
-	if err != nil {
107
-		return err
108
-	}
109
-
110
-	noOverwriteDirNonDir := httputils.BoolValue(r, "noOverwriteDirNonDir")
111
-	return s.daemon.ContainerExtractToDir(v.Name, v.Path, noOverwriteDirNonDir, r.Body)
112
-}
113 1
deleted file mode 100644
... ...
@@ -1,135 +0,0 @@
1
-package local
2
-
3
-import (
4
-	"encoding/json"
5
-	"fmt"
6
-	"io"
7
-	"net/http"
8
-	"strconv"
9
-
10
-	"github.com/Sirupsen/logrus"
11
-	"github.com/docker/docker/api/server/httputils"
12
-	"github.com/docker/docker/api/types"
13
-	"github.com/docker/docker/pkg/stdcopy"
14
-	"github.com/docker/docker/runconfig"
15
-	"golang.org/x/net/context"
16
-)
17
-
18
-func (s *router) getExecByID(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
19
-	eConfig, err := s.daemon.ContainerExecInspect(vars["id"])
20
-	if err != nil {
21
-		return err
22
-	}
23
-
24
-	return httputils.WriteJSON(w, http.StatusOK, eConfig)
25
-}
26
-
27
-func (s *router) postContainerExecCreate(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
28
-	if err := httputils.ParseForm(r); err != nil {
29
-		return err
30
-	}
31
-	if err := httputils.CheckForJSON(r); err != nil {
32
-		return err
33
-	}
34
-	name := vars["name"]
35
-
36
-	execConfig := &runconfig.ExecConfig{}
37
-	if err := json.NewDecoder(r.Body).Decode(execConfig); err != nil {
38
-		return err
39
-	}
40
-	execConfig.Container = name
41
-
42
-	if len(execConfig.Cmd) == 0 {
43
-		return fmt.Errorf("No exec command specified")
44
-	}
45
-
46
-	// Register an instance of Exec in container.
47
-	id, err := s.daemon.ContainerExecCreate(execConfig)
48
-	if err != nil {
49
-		logrus.Errorf("Error setting up exec command in container %s: %s", name, err)
50
-		return err
51
-	}
52
-
53
-	return httputils.WriteJSON(w, http.StatusCreated, &types.ContainerExecCreateResponse{
54
-		ID: id,
55
-	})
56
-}
57
-
58
-// TODO(vishh): Refactor the code to avoid having to specify stream config as part of both create and start.
59
-func (s *router) postContainerExecStart(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
60
-	if err := httputils.ParseForm(r); err != nil {
61
-		return err
62
-	}
63
-
64
-	version := httputils.VersionFromContext(ctx)
65
-	if version.GreaterThan("1.21") {
66
-		if err := httputils.CheckForJSON(r); err != nil {
67
-			return err
68
-		}
69
-	}
70
-
71
-	var (
72
-		execName                  = vars["name"]
73
-		stdin, inStream           io.ReadCloser
74
-		stdout, stderr, outStream io.Writer
75
-	)
76
-
77
-	execStartCheck := &types.ExecStartCheck{}
78
-	if err := json.NewDecoder(r.Body).Decode(execStartCheck); err != nil {
79
-		return err
80
-	}
81
-
82
-	if exists, err := s.daemon.ExecExists(execName); !exists {
83
-		return err
84
-	}
85
-
86
-	if !execStartCheck.Detach {
87
-		var err error
88
-		// Setting up the streaming http interface.
89
-		inStream, outStream, err = httputils.HijackConnection(w)
90
-		if err != nil {
91
-			return err
92
-		}
93
-		defer httputils.CloseStreams(inStream, outStream)
94
-
95
-		if _, ok := r.Header["Upgrade"]; ok {
96
-			fmt.Fprintf(outStream, "HTTP/1.1 101 UPGRADED\r\nContent-Type: application/vnd.docker.raw-stream\r\nConnection: Upgrade\r\nUpgrade: tcp\r\n\r\n")
97
-		} else {
98
-			fmt.Fprintf(outStream, "HTTP/1.1 200 OK\r\nContent-Type: application/vnd.docker.raw-stream\r\n\r\n")
99
-		}
100
-
101
-		stdin = inStream
102
-		stdout = outStream
103
-		if !execStartCheck.Tty {
104
-			stderr = stdcopy.NewStdWriter(outStream, stdcopy.Stderr)
105
-			stdout = stdcopy.NewStdWriter(outStream, stdcopy.Stdout)
106
-		}
107
-	} else {
108
-		outStream = w
109
-	}
110
-
111
-	// Now run the user process in container.
112
-	if err := s.daemon.ContainerExecStart(execName, stdin, stdout, stderr); err != nil {
113
-		if execStartCheck.Detach {
114
-			return err
115
-		}
116
-		logrus.Errorf("Error running exec in container: %v\n", err)
117
-	}
118
-	return nil
119
-}
120
-
121
-func (s *router) postContainerExecResize(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
122
-	if err := httputils.ParseForm(r); err != nil {
123
-		return err
124
-	}
125
-	height, err := strconv.Atoi(r.Form.Get("h"))
126
-	if err != nil {
127
-		return err
128
-	}
129
-	width, err := strconv.Atoi(r.Form.Get("w"))
130
-	if err != nil {
131
-		return err
132
-	}
133
-
134
-	return s.daemon.ContainerExecResize(vars["name"], height, width)
135
-}
136 1
deleted file mode 100644
... ...
@@ -1,33 +0,0 @@
1
-package local
2
-
3
-import (
4
-	"net/http"
5
-
6
-	"github.com/docker/docker/api/server/httputils"
7
-	"golang.org/x/net/context"
8
-)
9
-
10
-// getContainersByName inspects containers configuration and serializes it as json.
11
-func (s *router) getContainersByName(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
12
-	displaySize := httputils.BoolValue(r, "size")
13
-
14
-	var json interface{}
15
-	var err error
16
-
17
-	version := httputils.VersionFromContext(ctx)
18
-
19
-	switch {
20
-	case version.LessThan("1.20"):
21
-		json, err = s.daemon.ContainerInspectPre120(vars["name"])
22
-	case version.Equal("1.20"):
23
-		json, err = s.daemon.ContainerInspect120(vars["name"])
24
-	default:
25
-		json, err = s.daemon.ContainerInspect(vars["name"], displaySize)
26
-	}
27
-
28
-	if err != nil {
29
-		return err
30
-	}
31
-
32
-	return httputils.WriteJSON(w, http.StatusOK, json)
33
-}