Browse Source

Merge pull request #22898 from WeiZhang555/add-detach-event

Add detach event
Alexander Morozov 9 năm trước cách đây
mục cha
commit
c80a2f2937
4 tập tin đã thay đổi với 42 bổ sung12 xóa
  1. 17 5
      container/container.go
  2. 15 6
      daemon/attach.go
  3. 5 1
      daemon/exec.go
  4. 5 0
      integration-cli/docker_cli_run_unix_test.go

+ 17 - 5
container/container.go

@@ -48,6 +48,21 @@ var (
 	errInvalidNetwork  = fmt.Errorf("invalid network settings while building port map info")
 )
 
+// AttachError represents errors of attach
+type AttachError interface {
+	IsDetached() bool
+}
+
+type detachError struct{}
+
+func (e detachError) IsDetached() bool {
+	return true
+}
+
+func (e detachError) Error() string {
+	return "detached from container"
+}
+
 // CommonContainer holds the fields for a container which are
 // applicable across all platforms supported by the daemon.
 type CommonContainer struct {
@@ -393,7 +408,6 @@ func AttachStreams(ctx context.Context, streamConfig *runconfig.StreamConfig, op
 			_, err = copyEscapable(cStdin, stdin, keys)
 		} else {
 			_, err = io.Copy(cStdin, stdin)
-
 		}
 		if err == io.ErrClosedPipe {
 			err = nil
@@ -492,10 +506,8 @@ func copyEscapable(dst io.Writer, src io.ReadCloser, keys []byte) (written int64
 					break
 				}
 				if i == len(keys)-1 {
-					if err := src.Close(); err != nil {
-						return 0, err
-					}
-					return 0, nil
+					src.Close()
+					return 0, detachError{}
 				}
 				nr, er = src.Read(buf)
 			}

+ 15 - 6
daemon/attach.go

@@ -73,9 +73,9 @@ func (daemon *Daemon) ContainerAttachRaw(prefixOrName string, stdin io.ReadClose
 	return daemon.containerAttach(container, stdin, stdout, stderr, false, stream, nil)
 }
 
-func (daemon *Daemon) containerAttach(container *container.Container, stdin io.ReadCloser, stdout, stderr io.Writer, logs, stream bool, keys []byte) error {
+func (daemon *Daemon) containerAttach(c *container.Container, stdin io.ReadCloser, stdout, stderr io.Writer, logs, stream bool, keys []byte) error {
 	if logs {
-		logDriver, err := daemon.getLogger(container)
+		logDriver, err := daemon.getLogger(c)
 		if err != nil {
 			return err
 		}
@@ -105,7 +105,7 @@ func (daemon *Daemon) containerAttach(container *container.Container, stdin io.R
 		}
 	}
 
-	daemon.LogContainerEvent(container, "attach")
+	daemon.LogContainerEvent(c, "attach")
 
 	//stream
 	if stream {
@@ -119,11 +119,20 @@ func (daemon *Daemon) containerAttach(container *container.Container, stdin io.R
 			}()
 			stdinPipe = r
 		}
-		<-container.Attach(stdinPipe, stdout, stderr, keys)
+		err := <-c.Attach(stdinPipe, stdout, stderr, keys)
+		if err != nil {
+			e, ok := err.(container.AttachError)
+			if ok && e.IsDetached() {
+				daemon.LogContainerEvent(c, "detach")
+			} else {
+				logrus.Errorf("attach failed with error: %v", err)
+			}
+		}
+
 		// If we are in stdinonce mode, wait for the process to end
 		// otherwise, simply return
-		if container.Config.StdinOnce && !container.Config.Tty {
-			container.WaitStop(-1 * time.Second)
+		if c.Config.StdinOnce && !c.Config.Tty {
+			c.WaitStop(-1 * time.Second)
 		}
 	}
 	return nil

+ 5 - 1
daemon/exec.go

@@ -222,7 +222,11 @@ func (d *Daemon) ContainerExecStart(ctx context.Context, name string, stdin io.R
 		return fmt.Errorf("context cancelled")
 	case err := <-attachErr:
 		if err != nil {
-			return fmt.Errorf("attach failed with error: %v", err)
+			e, ok := err.(container.AttachError)
+			if !ok || !e.IsDetached() {
+				return fmt.Errorf("attach failed with error: %v", err)
+			}
+			d.LogContainerEvent(c, "detach")
 		}
 	}
 	return nil

+ 5 - 0
integration-cli/docker_cli_run_unix_test.go

@@ -135,6 +135,11 @@ func (s *DockerSuite) TestRunAttachDetach(c *check.C) {
 
 	running := inspectField(c, name, "State.Running")
 	c.Assert(running, checker.Equals, "true", check.Commentf("expected container to still be running"))
+
+	out, _ = dockerCmd(c, "events", "--since=0", "--until", daemonUnixTime(c), "-f", "container="+name)
+	// attach and detach event should be monitored
+	c.Assert(out, checker.Contains, "attach")
+	c.Assert(out, checker.Contains, "detach")
 }
 
 // TestRunDetach checks attaching and detaching with the escape sequence specified via flags.