Implement docker run with standalone client lib.

Signed-off-by: David Calavera <david.calavera@gmail.com>
This commit is contained in:
David Calavera 2015-12-05 23:18:06 -05:00
parent 962b2d8b9b
commit bcb848c87f
2 changed files with 21 additions and 41 deletions

View File

@ -3,12 +3,12 @@ package client
import ( import (
"fmt" "fmt"
"io" "io"
"net/url"
"os" "os"
"runtime" "runtime"
"strings" "strings"
"github.com/Sirupsen/logrus" "github.com/Sirupsen/logrus"
"github.com/docker/docker/api/types"
Cli "github.com/docker/docker/cli" Cli "github.com/docker/docker/cli"
derr "github.com/docker/docker/errors" derr "github.com/docker/docker/errors"
"github.com/docker/docker/opts" "github.com/docker/docker/opts"
@ -168,70 +168,57 @@ func (cli *DockerCli) CmdRun(args ...string) error {
if *flAutoRemove && (hostConfig.RestartPolicy.IsAlways() || hostConfig.RestartPolicy.IsOnFailure()) { if *flAutoRemove && (hostConfig.RestartPolicy.IsAlways() || hostConfig.RestartPolicy.IsOnFailure()) {
return ErrConflictRestartPolicyAndAutoRemove 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 { if config.AttachStdin || config.AttachStdout || config.AttachStderr {
var ( var (
out, stderr io.Writer out, stderr io.Writer
in io.ReadCloser in io.ReadCloser
v = url.Values{}
) )
v.Set("stream", "1")
if config.AttachStdin { if config.AttachStdin {
v.Set("stdin", "1")
in = cli.in in = cli.in
} }
if config.AttachStdout { if config.AttachStdout {
v.Set("stdout", "1")
out = cli.out out = cli.out
} }
if config.AttachStderr { if config.AttachStderr {
v.Set("stderr", "1")
if config.Tty { if config.Tty {
stderr = cli.out stderr = cli.out
} else { } else {
stderr = cli.err 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) options := types.ContainerAttachOptions{
}) ContainerID: createResponse.ID,
} else { Stream: true,
close(hijacked) Stdin: config.AttachStdin,
} Stdout: config.AttachStdout,
// Acknowledge the hijack before starting Stderr: config.AttachStderr,
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()
} }
case err := <-errCh:
resp, err := cli.client.ContainerAttach(options)
if err != nil { if err != nil {
logrus.Debugf("Error hijack: %s", err)
return err return err
} }
errCh = promise.Go(func() error {
return cli.holdHijackedConnection(config.Tty, in, out, stderr, resp)
})
} }
defer func() { defer func() {
if *flAutoRemove { 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) fmt.Fprintf(cli.err, "Error deleting container: %s\n", err)
} }
} }
}() }()
//start the container //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) cmd.ReportError(err.Error(), false)
return runStartContainerErr(err) return runStartContainerErr(err)
} }
@ -262,7 +249,7 @@ func (cli *DockerCli) CmdRun(args ...string) error {
if *flAutoRemove { if *flAutoRemove {
// Autoremove: wait for the container to finish, retrieve // Autoremove: wait for the container to finish, retrieve
// the exit code and remove the container // 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) return runStartContainerErr(err)
} }
if _, status, err = getExitCode(cli, createResponse.ID); err != nil { if _, status, err = getExitCode(cli, createResponse.ID); err != nil {

View File

@ -95,13 +95,6 @@ func (cli *DockerCli) CmdStart(args ...string) error {
return cli.holdHijackedConnection(c.Config.Tty, in, cli.out, cli.err, resp) 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. // 3. Start the container.
if err := cli.client.ContainerStart(containerID); err != nil { if err := cli.client.ContainerStart(containerID); err != nil {
return err return err