This change touches docker logs, attach, and start -a along with get
exit code in the client.
Docker-DCO-1.1-Signed-off-by: Michael Crosby <michael@crosbymichael.com> (github: crosbymichael)
| ... | ... |
@@ -560,10 +560,14 @@ func (cli *DockerCli) forwardAllSignals(cid string) chan os.Signal {
|
| 560 | 560 |
|
| 561 | 561 |
func (cli *DockerCli) CmdStart(args ...string) error {
|
| 562 | 562 |
var ( |
| 563 |
+ cErr chan error |
|
| 564 |
+ tty bool |
|
| 565 |
+ |
|
| 563 | 566 |
cmd = cli.Subcmd("start", "CONTAINER [CONTAINER...]", "Restart a stopped container")
|
| 564 | 567 |
attach = cmd.Bool([]string{"a", "-attach"}, false, "Attach container's stdout/stderr and forward all signals to the process")
|
| 565 | 568 |
openStdin = cmd.Bool([]string{"i", "-interactive"}, false, "Attach container's stdin")
|
| 566 | 569 |
) |
| 570 |
+ |
|
| 567 | 571 |
if err := cmd.Parse(args); err != nil {
|
| 568 | 572 |
return nil |
| 569 | 573 |
} |
| ... | ... |
@@ -572,29 +576,24 @@ func (cli *DockerCli) CmdStart(args ...string) error {
|
| 572 | 572 |
return nil |
| 573 | 573 |
} |
| 574 | 574 |
|
| 575 |
- var ( |
|
| 576 |
- cErr chan error |
|
| 577 |
- tty bool |
|
| 578 |
- ) |
|
| 579 | 575 |
if *attach || *openStdin {
|
| 580 | 576 |
if cmd.NArg() > 1 {
|
| 581 | 577 |
return fmt.Errorf("You cannot start and attach multiple containers at once.")
|
| 582 | 578 |
} |
| 583 | 579 |
|
| 584 |
- body, _, err := readBody(cli.call("GET", "/containers/"+cmd.Arg(0)+"/json", nil, false))
|
|
| 580 |
+ steam, _, err := cli.call("GET", "/containers/"+cmd.Arg(0)+"/json", nil, false)
|
|
| 585 | 581 |
if err != nil {
|
| 586 | 582 |
return err |
| 587 | 583 |
} |
| 588 | 584 |
|
| 589 |
- container := &api.Container{}
|
|
| 590 |
- err = json.Unmarshal(body, container) |
|
| 591 |
- if err != nil {
|
|
| 585 |
+ env := engine.Env{}
|
|
| 586 |
+ if err := env.Decode(steam); err != nil {
|
|
| 592 | 587 |
return err |
| 593 | 588 |
} |
| 589 |
+ config := env.GetSubEnv("Config")
|
|
| 590 |
+ tty = config.GetBool("Tty")
|
|
| 594 | 591 |
|
| 595 |
- tty = container.Config.Tty |
|
| 596 |
- |
|
| 597 |
- if !container.Config.Tty {
|
|
| 592 |
+ if !tty {
|
|
| 598 | 593 |
sigc := cli.forwardAllSignals(cmd.Arg(0)) |
| 599 | 594 |
defer signal.StopCatch(sigc) |
| 600 | 595 |
} |
| ... | ... |
@@ -603,15 +602,17 @@ func (cli *DockerCli) CmdStart(args ...string) error {
|
| 603 | 603 |
|
| 604 | 604 |
v := url.Values{}
|
| 605 | 605 |
v.Set("stream", "1")
|
| 606 |
- if *openStdin && container.Config.OpenStdin {
|
|
| 606 |
+ |
|
| 607 |
+ if *openStdin && config.GetBool("OpenStdin") {
|
|
| 607 | 608 |
v.Set("stdin", "1")
|
| 608 | 609 |
in = cli.in |
| 609 | 610 |
} |
| 611 |
+ |
|
| 610 | 612 |
v.Set("stdout", "1")
|
| 611 | 613 |
v.Set("stderr", "1")
|
| 612 | 614 |
|
| 613 | 615 |
cErr = utils.Go(func() error {
|
| 614 |
- return cli.hijack("POST", "/containers/"+cmd.Arg(0)+"/attach?"+v.Encode(), container.Config.Tty, in, cli.out, cli.err, nil)
|
|
| 616 |
+ return cli.hijack("POST", "/containers/"+cmd.Arg(0)+"/attach?"+v.Encode(), tty, in, cli.out, cli.err, nil)
|
|
| 615 | 617 |
}) |
| 616 | 618 |
} |
| 617 | 619 |
|
| ... | ... |
@@ -774,34 +775,38 @@ func (cli *DockerCli) CmdPort(args ...string) error {
|
| 774 | 774 |
} |
| 775 | 775 |
|
| 776 | 776 |
var ( |
| 777 |
- port = cmd.Arg(1) |
|
| 778 |
- proto = "tcp" |
|
| 779 |
- parts = strings.SplitN(port, "/", 2) |
|
| 780 |
- container api.Container |
|
| 777 |
+ port = cmd.Arg(1) |
|
| 778 |
+ proto = "tcp" |
|
| 779 |
+ parts = strings.SplitN(port, "/", 2) |
|
| 781 | 780 |
) |
| 782 | 781 |
|
| 783 | 782 |
if len(parts) == 2 && len(parts[1]) != 0 {
|
| 784 | 783 |
port = parts[0] |
| 785 | 784 |
proto = parts[1] |
| 786 | 785 |
} |
| 787 |
- body, _, err := readBody(cli.call("GET", "/containers/"+cmd.Arg(0)+"/json", nil, false))
|
|
| 786 |
+ |
|
| 787 |
+ steam, _, err := cli.call("GET", "/containers/"+cmd.Arg(0)+"/json", nil, false)
|
|
| 788 | 788 |
if err != nil {
|
| 789 | 789 |
return err |
| 790 | 790 |
} |
| 791 | 791 |
|
| 792 |
- err = json.Unmarshal(body, &container) |
|
| 793 |
- if err != nil {
|
|
| 792 |
+ env := engine.Env{}
|
|
| 793 |
+ if err := env.Decode(steam); err != nil {
|
|
| 794 |
+ return err |
|
| 795 |
+ } |
|
| 796 |
+ ports := nat.PortMap{}
|
|
| 797 |
+ if err := env.GetSubEnv("NetworkSettings").GetJson("Ports", &ports); err != nil {
|
|
| 794 | 798 |
return err |
| 795 | 799 |
} |
| 796 | 800 |
|
| 797 |
- if frontends, exists := container.NetworkSettings.Ports[nat.Port(port+"/"+proto)]; exists && frontends != nil {
|
|
| 801 |
+ if frontends, exists := ports[nat.Port(port+"/"+proto)]; exists && frontends != nil {
|
|
| 798 | 802 |
for _, frontend := range frontends {
|
| 799 | 803 |
fmt.Fprintf(cli.out, "%s:%s\n", frontend.HostIp, frontend.HostPort) |
| 800 | 804 |
} |
| 801 |
- } else {
|
|
| 802 |
- return fmt.Errorf("Error: No public port '%s' published for %s", cmd.Arg(1), cmd.Arg(0))
|
|
| 805 |
+ return nil |
|
| 803 | 806 |
} |
| 804 |
- return nil |
|
| 807 |
+ |
|
| 808 |
+ return fmt.Errorf("Error: No public port '%s' published for %s", cmd.Arg(1), cmd.Arg(0))
|
|
| 805 | 809 |
} |
| 806 | 810 |
|
| 807 | 811 |
// 'docker rmi IMAGE' removes all images with the name IMAGE |
| ... | ... |
@@ -1619,72 +1624,84 @@ func (cli *DockerCli) CmdDiff(args ...string) error {
|
| 1619 | 1619 |
} |
| 1620 | 1620 |
|
| 1621 | 1621 |
func (cli *DockerCli) CmdLogs(args ...string) error {
|
| 1622 |
- cmd := cli.Subcmd("logs", "CONTAINER", "Fetch the logs of a container")
|
|
| 1623 |
- follow := cmd.Bool([]string{"f", "-follow"}, false, "Follow log output")
|
|
| 1624 |
- times := cmd.Bool([]string{"t", "-timestamps"}, false, "Show timestamps")
|
|
| 1622 |
+ var ( |
|
| 1623 |
+ cmd = cli.Subcmd("logs", "CONTAINER", "Fetch the logs of a container")
|
|
| 1624 |
+ follow = cmd.Bool([]string{"f", "-follow"}, false, "Follow log output")
|
|
| 1625 |
+ times = cmd.Bool([]string{"t", "-timestamps"}, false, "Show timestamps")
|
|
| 1626 |
+ ) |
|
| 1627 |
+ |
|
| 1625 | 1628 |
if err := cmd.Parse(args); err != nil {
|
| 1626 | 1629 |
return nil |
| 1627 | 1630 |
} |
| 1631 |
+ |
|
| 1628 | 1632 |
if cmd.NArg() != 1 {
|
| 1629 | 1633 |
cmd.Usage() |
| 1630 | 1634 |
return nil |
| 1631 | 1635 |
} |
| 1632 | 1636 |
name := cmd.Arg(0) |
| 1633 |
- body, _, err := readBody(cli.call("GET", "/containers/"+name+"/json", nil, false))
|
|
| 1637 |
+ |
|
| 1638 |
+ steam, _, err := cli.call("GET", "/containers/"+name+"/json", nil, false)
|
|
| 1634 | 1639 |
if err != nil {
|
| 1635 | 1640 |
return err |
| 1636 | 1641 |
} |
| 1637 | 1642 |
|
| 1638 |
- container := &api.Container{}
|
|
| 1639 |
- err = json.Unmarshal(body, container) |
|
| 1640 |
- if err != nil {
|
|
| 1643 |
+ env := engine.Env{}
|
|
| 1644 |
+ if err := env.Decode(steam); err != nil {
|
|
| 1641 | 1645 |
return err |
| 1642 | 1646 |
} |
| 1643 | 1647 |
|
| 1644 | 1648 |
v := url.Values{}
|
| 1645 | 1649 |
v.Set("stdout", "1")
|
| 1646 | 1650 |
v.Set("stderr", "1")
|
| 1651 |
+ |
|
| 1647 | 1652 |
if *times {
|
| 1648 | 1653 |
v.Set("timestamps", "1")
|
| 1649 | 1654 |
} |
| 1650 |
- if *follow && container.State.Running {
|
|
| 1655 |
+ |
|
| 1656 |
+ if *follow {
|
|
| 1651 | 1657 |
v.Set("follow", "1")
|
| 1652 | 1658 |
} |
| 1653 | 1659 |
|
| 1654 |
- if err := cli.streamHelper("GET", "/containers/"+name+"/logs?"+v.Encode(), container.Config.Tty, nil, cli.out, cli.err, nil); err != nil {
|
|
| 1655 |
- return err |
|
| 1656 |
- } |
|
| 1657 |
- return nil |
|
| 1660 |
+ return cli.streamHelper("GET", "/containers/"+name+"/logs?"+v.Encode(), env.GetSubEnv("Config").GetBool("Tty"), nil, cli.out, cli.err, nil)
|
|
| 1658 | 1661 |
} |
| 1659 | 1662 |
|
| 1660 | 1663 |
func (cli *DockerCli) CmdAttach(args ...string) error {
|
| 1661 |
- cmd := cli.Subcmd("attach", "[OPTIONS] CONTAINER", "Attach to a running container")
|
|
| 1662 |
- noStdin := cmd.Bool([]string{"#nostdin", "-no-stdin"}, false, "Do not attach stdin")
|
|
| 1663 |
- proxy := cmd.Bool([]string{"#sig-proxy", "-sig-proxy"}, true, "Proxify all received signal to the process (even in non-tty mode)")
|
|
| 1664 |
+ var ( |
|
| 1665 |
+ cmd = cli.Subcmd("attach", "[OPTIONS] CONTAINER", "Attach to a running container")
|
|
| 1666 |
+ noStdin = cmd.Bool([]string{"#nostdin", "-no-stdin"}, false, "Do not attach stdin")
|
|
| 1667 |
+ proxy = cmd.Bool([]string{"#sig-proxy", "-sig-proxy"}, true, "Proxify all received signal to the process (even in non-tty mode)")
|
|
| 1668 |
+ ) |
|
| 1669 |
+ |
|
| 1664 | 1670 |
if err := cmd.Parse(args); err != nil {
|
| 1665 | 1671 |
return nil |
| 1666 | 1672 |
} |
| 1673 |
+ |
|
| 1667 | 1674 |
if cmd.NArg() != 1 {
|
| 1668 | 1675 |
cmd.Usage() |
| 1669 | 1676 |
return nil |
| 1670 | 1677 |
} |
| 1671 | 1678 |
name := cmd.Arg(0) |
| 1672 |
- body, _, err := readBody(cli.call("GET", "/containers/"+name+"/json", nil, false))
|
|
| 1679 |
+ |
|
| 1680 |
+ stream, _, err := cli.call("GET", "/containers/"+name+"/json", nil, false)
|
|
| 1673 | 1681 |
if err != nil {
|
| 1674 | 1682 |
return err |
| 1675 | 1683 |
} |
| 1676 | 1684 |
|
| 1677 |
- container := &api.Container{}
|
|
| 1678 |
- err = json.Unmarshal(body, container) |
|
| 1679 |
- if err != nil {
|
|
| 1685 |
+ env := engine.Env{}
|
|
| 1686 |
+ if err := env.Decode(stream); err != nil {
|
|
| 1680 | 1687 |
return err |
| 1681 | 1688 |
} |
| 1682 | 1689 |
|
| 1683 |
- if !container.State.Running {
|
|
| 1690 |
+ if !env.GetSubEnv("State").GetBool("Running") {
|
|
| 1684 | 1691 |
return fmt.Errorf("You cannot attach to a stopped container, start it first")
|
| 1685 | 1692 |
} |
| 1686 | 1693 |
|
| 1687 |
- if container.Config.Tty && cli.isTerminal {
|
|
| 1694 |
+ var ( |
|
| 1695 |
+ config = env.GetSubEnv("Config")
|
|
| 1696 |
+ tty = config.GetBool("Tty")
|
|
| 1697 |
+ ) |
|
| 1698 |
+ |
|
| 1699 |
+ if tty && cli.isTerminal {
|
|
| 1688 | 1700 |
if err := cli.monitorTtySize(cmd.Arg(0)); err != nil {
|
| 1689 | 1701 |
utils.Debugf("Error monitoring TTY size: %s", err)
|
| 1690 | 1702 |
} |
| ... | ... |
@@ -1694,19 +1711,20 @@ func (cli *DockerCli) CmdAttach(args ...string) error {
|
| 1694 | 1694 |
|
| 1695 | 1695 |
v := url.Values{}
|
| 1696 | 1696 |
v.Set("stream", "1")
|
| 1697 |
- if !*noStdin && container.Config.OpenStdin {
|
|
| 1697 |
+ if !*noStdin && config.GetBool("OpenStdin") {
|
|
| 1698 | 1698 |
v.Set("stdin", "1")
|
| 1699 | 1699 |
in = cli.in |
| 1700 | 1700 |
} |
| 1701 |
+ |
|
| 1701 | 1702 |
v.Set("stdout", "1")
|
| 1702 | 1703 |
v.Set("stderr", "1")
|
| 1703 | 1704 |
|
| 1704 |
- if *proxy && !container.Config.Tty {
|
|
| 1705 |
+ if *proxy && !tty {
|
|
| 1705 | 1706 |
sigc := cli.forwardAllSignals(cmd.Arg(0)) |
| 1706 | 1707 |
defer signal.StopCatch(sigc) |
| 1707 | 1708 |
} |
| 1708 | 1709 |
|
| 1709 |
- if err := cli.hijack("POST", "/containers/"+cmd.Arg(0)+"/attach?"+v.Encode(), container.Config.Tty, in, cli.out, cli.err, nil); err != nil {
|
|
| 1710 |
+ if err := cli.hijack("POST", "/containers/"+cmd.Arg(0)+"/attach?"+v.Encode(), tty, in, cli.out, cli.err, nil); err != nil {
|
|
| 1710 | 1711 |
return err |
| 1711 | 1712 |
} |
| 1712 | 1713 |
|
| ... | ... |
@@ -200,7 +200,7 @@ func waitForExit(cli *DockerCli, containerId string) (int, error) {
|
| 200 | 200 |
// getExitCode perform an inspect on the container. It returns |
| 201 | 201 |
// the running state and the exit code. |
| 202 | 202 |
func getExitCode(cli *DockerCli, containerId string) (bool, int, error) {
|
| 203 |
- body, _, err := readBody(cli.call("GET", "/containers/"+containerId+"/json", nil, false))
|
|
| 203 |
+ steam, _, err := cli.call("GET", "/containers/"+containerId+"/json", nil, false)
|
|
| 204 | 204 |
if err != nil {
|
| 205 | 205 |
// If we can't connect, then the daemon probably died. |
| 206 | 206 |
if err != ErrConnectionRefused {
|
| ... | ... |
@@ -208,11 +208,14 @@ func getExitCode(cli *DockerCli, containerId string) (bool, int, error) {
|
| 208 | 208 |
} |
| 209 | 209 |
return false, -1, nil |
| 210 | 210 |
} |
| 211 |
- c := &api.Container{}
|
|
| 212 |
- if err := json.Unmarshal(body, c); err != nil {
|
|
| 211 |
+ |
|
| 212 |
+ var result engine.Env |
|
| 213 |
+ if err := result.Decode(steam); err != nil {
|
|
| 213 | 214 |
return false, -1, err |
| 214 | 215 |
} |
| 215 |
- return c.State.Running, c.State.ExitCode, nil |
|
| 216 |
+ |
|
| 217 |
+ state := result.GetSubEnv("State")
|
|
| 218 |
+ return state.GetBool("Running"), state.GetInt("ExitCode"), nil
|
|
| 216 | 219 |
} |
| 217 | 220 |
|
| 218 | 221 |
func (cli *DockerCli) monitorTtySize(id string) error {
|
| 219 | 222 |
deleted file mode 100644 |
| ... | ... |
@@ -1,18 +0,0 @@ |
| 1 |
-package api |
|
| 2 |
- |
|
| 3 |
-import ( |
|
| 4 |
- "github.com/dotcloud/docker/nat" |
|
| 5 |
- "github.com/dotcloud/docker/runconfig" |
|
| 6 |
-) |
|
| 7 |
- |
|
| 8 |
-type Container struct {
|
|
| 9 |
- Config runconfig.Config |
|
| 10 |
- HostConfig runconfig.HostConfig |
|
| 11 |
- State struct {
|
|
| 12 |
- Running bool |
|
| 13 |
- ExitCode int |
|
| 14 |
- } |
|
| 15 |
- NetworkSettings struct {
|
|
| 16 |
- Ports nat.PortMap |
|
| 17 |
- } |
|
| 18 |
-} |