Browse code

Merge pull request #18715 from calavera/remove_is_paused_from_interface

Remove `IsPaused` from backend interface.

Arnaud Porterie authored on 2015/12/29 04:25:11
Showing 4 changed files
... ...
@@ -45,7 +45,6 @@ type stateBackend interface {
45 45
 	ContainerUpdate(name string, hostConfig *container.HostConfig) ([]string, error)
46 46
 	ContainerWait(name string, timeout time.Duration) (int, error)
47 47
 	Exists(id string) bool
48
-	IsPaused(id string) bool
49 48
 }
50 49
 
51 50
 // monitorBackend includes functions to implement to provide containers monitoring functionality.
... ...
@@ -425,29 +425,11 @@ func (s *containerRouter) postContainersAttach(ctx context.Context, w http.Respo
425 425
 	}
426 426
 	containerName := vars["name"]
427 427
 
428
-	if !s.backend.Exists(containerName) {
429
-		return derr.ErrorCodeNoSuchContainer.WithArgs(containerName)
430
-	}
431
-
432
-	if s.backend.IsPaused(containerName) {
433
-		return derr.ErrorCodePausedContainer.WithArgs(containerName)
434
-	}
435
-
436
-	inStream, outStream, err := httputils.HijackConnection(w)
437
-	if err != nil {
438
-		return err
439
-	}
440
-	defer httputils.CloseStreams(inStream, outStream)
441
-
442
-	if _, ok := r.Header["Upgrade"]; ok {
443
-		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")
444
-	} else {
445
-		fmt.Fprintf(outStream, "HTTP/1.1 200 OK\r\nContent-Type: application/vnd.docker.raw-stream\r\n\r\n")
446
-	}
428
+	_, upgrade := r.Header["Upgrade"]
447 429
 
448 430
 	attachWithLogsConfig := &daemon.ContainerAttachWithLogsConfig{
449
-		InStream:  inStream,
450
-		OutStream: outStream,
431
+		Hijacker:  w.(http.Hijacker),
432
+		Upgrade:   upgrade,
451 433
 		UseStdin:  httputils.BoolValue(r, "stdin"),
452 434
 		UseStdout: httputils.BoolValue(r, "stdout"),
453 435
 		UseStderr: httputils.BoolValue(r, "stderr"),
... ...
@@ -455,11 +437,7 @@ func (s *containerRouter) postContainersAttach(ctx context.Context, w http.Respo
455 455
 		Stream:    httputils.BoolValue(r, "stream"),
456 456
 	}
457 457
 
458
-	if err := s.backend.ContainerAttachWithLogs(containerName, attachWithLogsConfig); err != nil {
459
-		fmt.Fprintf(outStream, "Error attaching: %s\n", err)
460
-	}
461
-
462
-	return nil
458
+	return s.backend.ContainerAttachWithLogs(containerName, attachWithLogsConfig)
463 459
 }
464 460
 
465 461
 func (s *containerRouter) wsContainersAttach(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
... ...
@@ -1,53 +1,84 @@
1 1
 package daemon
2 2
 
3 3
 import (
4
+	"fmt"
4 5
 	"io"
6
+	"net/http"
5 7
 	"time"
6 8
 
7 9
 	"github.com/Sirupsen/logrus"
8 10
 	"github.com/docker/docker/container"
9 11
 	"github.com/docker/docker/daemon/logger"
12
+	derr "github.com/docker/docker/errors"
10 13
 	"github.com/docker/docker/pkg/stdcopy"
11 14
 )
12 15
 
13 16
 // ContainerAttachWithLogsConfig holds the streams to use when connecting to a container to view logs.
14 17
 type ContainerAttachWithLogsConfig struct {
15
-	InStream                       io.ReadCloser
16
-	OutStream                      io.Writer
17
-	UseStdin, UseStdout, UseStderr bool
18
-	Logs, Stream                   bool
18
+	Hijacker  http.Hijacker
19
+	Upgrade   bool
20
+	UseStdin  bool
21
+	UseStdout bool
22
+	UseStderr bool
23
+	Logs      bool
24
+	Stream    bool
19 25
 }
20 26
 
21 27
 // ContainerAttachWithLogs attaches to logs according to the config passed in. See ContainerAttachWithLogsConfig.
22 28
 func (daemon *Daemon) ContainerAttachWithLogs(prefixOrName string, c *ContainerAttachWithLogsConfig) error {
29
+	if c.Hijacker == nil {
30
+		return derr.ErrorCodeNoHijackConnection.WithArgs(prefixOrName)
31
+	}
23 32
 	container, err := daemon.GetContainer(prefixOrName)
24 33
 	if err != nil {
34
+		return derr.ErrorCodeNoSuchContainer.WithArgs(prefixOrName)
35
+	}
36
+	if container.IsPaused() {
37
+		return derr.ErrorCodePausedContainer.WithArgs(prefixOrName)
38
+	}
39
+
40
+	conn, _, err := c.Hijacker.Hijack()
41
+	if err != nil {
25 42
 		return err
26 43
 	}
44
+	defer conn.Close()
45
+	// Flush the options to make sure the client sets the raw mode
46
+	conn.Write([]byte{})
47
+	inStream := conn.(io.ReadCloser)
48
+	outStream := conn.(io.Writer)
49
+
50
+	if c.Upgrade {
51
+		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")
52
+	} else {
53
+		fmt.Fprintf(outStream, "HTTP/1.1 200 OK\r\nContent-Type: application/vnd.docker.raw-stream\r\n\r\n")
54
+	}
27 55
 
28 56
 	var errStream io.Writer
29 57
 
30 58
 	if !container.Config.Tty {
31
-		errStream = stdcopy.NewStdWriter(c.OutStream, stdcopy.Stderr)
32
-		c.OutStream = stdcopy.NewStdWriter(c.OutStream, stdcopy.Stdout)
59
+		errStream = stdcopy.NewStdWriter(outStream, stdcopy.Stderr)
60
+		outStream = stdcopy.NewStdWriter(outStream, stdcopy.Stdout)
33 61
 	} else {
34
-		errStream = c.OutStream
62
+		errStream = outStream
35 63
 	}
36 64
 
37 65
 	var stdin io.ReadCloser
38 66
 	var stdout, stderr io.Writer
39 67
 
40 68
 	if c.UseStdin {
41
-		stdin = c.InStream
69
+		stdin = inStream
42 70
 	}
43 71
 	if c.UseStdout {
44
-		stdout = c.OutStream
72
+		stdout = outStream
45 73
 	}
46 74
 	if c.UseStderr {
47 75
 		stderr = errStream
48 76
 	}
49 77
 
50
-	return daemon.attachWithLogs(container, stdin, stdout, stderr, c.Logs, c.Stream)
78
+	if err := daemon.attachWithLogs(container, stdin, stdout, stderr, c.Logs, c.Stream); err != nil {
79
+		fmt.Fprintf(outStream, "Error attaching: %s\n", err)
80
+	}
81
+	return nil
51 82
 }
52 83
 
53 84
 // ContainerWsAttachWithLogsConfig attach with websockets, since all
... ...
@@ -33,4 +33,13 @@ var (
33 33
 		Description:    "Docker's networking stack is disabled for this platform",
34 34
 		HTTPStatusCode: http.StatusNotFound,
35 35
 	})
36
+
37
+	// ErrorCodeNoHijackConnection is generated when a request tries to attach to a container
38
+	// but the connection to hijack is not provided.
39
+	ErrorCodeNoHijackConnection = errcode.Register(errGroup, errcode.ErrorDescriptor{
40
+		Value:          "HIJACK_CONNECTION_MISSING",
41
+		Message:        "error attaching to container %s, hijack connection missing",
42
+		Description:    "The caller didn't provide a connection to hijack",
43
+		HTTPStatusCode: http.StatusBadRequest,
44
+	})
36 45
 )