From bcb848c87f496fe2b946530521a0d262a489c019 Mon Sep 17 00:00:00 2001 From: David Calavera Date: Sat, 5 Dec 2015 23:18:06 -0500 Subject: [PATCH] Implement docker run with standalone client lib. Signed-off-by: David Calavera --- api/client/run.go | 55 +++++++++++++++++---------------------------- api/client/start.go | 7 ------ 2 files changed, 21 insertions(+), 41 deletions(-) diff --git a/api/client/run.go b/api/client/run.go index 8eb463141a..d93574b29b 100644 --- a/api/client/run.go +++ b/api/client/run.go @@ -3,12 +3,12 @@ package client import ( "fmt" "io" - "net/url" "os" "runtime" "strings" "github.com/Sirupsen/logrus" + "github.com/docker/docker/api/types" Cli "github.com/docker/docker/cli" derr "github.com/docker/docker/errors" "github.com/docker/docker/opts" @@ -168,70 +168,57 @@ func (cli *DockerCli) CmdRun(args ...string) error { if *flAutoRemove && (hostConfig.RestartPolicy.IsAlways() || hostConfig.RestartPolicy.IsOnFailure()) { return ErrConflictRestartPolicyAndAutoRemove } - // We need to instantiate the chan because the select needs it. It can - // be closed but can't be uninitialized. - hijacked := make(chan io.Closer) - // Block the return until the chan gets closed - defer func() { - logrus.Debugf("End of CmdRun(), Waiting for hijack to finish.") - if _, ok := <-hijacked; ok { - fmt.Fprintln(cli.err, "Hijack did not finish (chan still open)") - } - }() + if config.AttachStdin || config.AttachStdout || config.AttachStderr { var ( out, stderr io.Writer in io.ReadCloser - v = url.Values{} ) - v.Set("stream", "1") if config.AttachStdin { - v.Set("stdin", "1") in = cli.in } if config.AttachStdout { - v.Set("stdout", "1") out = cli.out } if config.AttachStderr { - v.Set("stderr", "1") if config.Tty { stderr = cli.out } else { stderr = cli.err } } - errCh = promise.Go(func() error { - return cli.hijack("POST", "/containers/"+createResponse.ID+"/attach?"+v.Encode(), config.Tty, in, out, stderr, hijacked, nil) - }) - } else { - close(hijacked) - } - // Acknowledge the hijack before starting - select { - case closer := <-hijacked: - // Make sure that the hijack gets closed when returning (results - // in closing the hijack chan and freeing server's goroutines) - if closer != nil { - defer closer.Close() + + options := types.ContainerAttachOptions{ + ContainerID: createResponse.ID, + Stream: true, + Stdin: config.AttachStdin, + Stdout: config.AttachStdout, + Stderr: config.AttachStderr, } - case err := <-errCh: + + resp, err := cli.client.ContainerAttach(options) if err != nil { - logrus.Debugf("Error hijack: %s", err) return err } + errCh = promise.Go(func() error { + return cli.holdHijackedConnection(config.Tty, in, out, stderr, resp) + }) } defer func() { if *flAutoRemove { - if _, _, err = readBody(cli.call("DELETE", "/containers/"+createResponse.ID+"?v=1", nil, nil)); err != nil { + options := types.ContainerRemoveOptions{ + ContainerID: createResponse.ID, + RemoveVolumes: true, + } + if err := cli.client.ContainerRemove(options); err != nil { fmt.Fprintf(cli.err, "Error deleting container: %s\n", err) } } }() //start the container - if _, _, err := readBody(cli.call("POST", "/containers/"+createResponse.ID+"/start", nil, nil)); err != nil { + if err := cli.client.ContainerStart(createResponse.ID); err != nil { cmd.ReportError(err.Error(), false) return runStartContainerErr(err) } @@ -262,7 +249,7 @@ func (cli *DockerCli) CmdRun(args ...string) error { if *flAutoRemove { // Autoremove: wait for the container to finish, retrieve // the exit code and remove the container - if _, _, err := readBody(cli.call("POST", "/containers/"+createResponse.ID+"/wait", nil, nil)); err != nil { + if status, err = cli.client.ContainerWait(createResponse.ID); err != nil { return runStartContainerErr(err) } if _, status, err = getExitCode(cli, createResponse.ID); err != nil { diff --git a/api/client/start.go b/api/client/start.go index 3baef202a8..787f87d118 100644 --- a/api/client/start.go +++ b/api/client/start.go @@ -95,13 +95,6 @@ func (cli *DockerCli) CmdStart(args ...string) error { return cli.holdHijackedConnection(c.Config.Tty, in, cli.out, cli.err, resp) }) - select { - case err := <-cErr: - if err != nil { - return err - } - } - // 3. Start the container. if err := cli.client.ContainerStart(containerID); err != nil { return err