Browse code

Remove the API container struct and use env

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)

Michael Crosby authored on 2014/06/05 07:11:11
Showing 3 changed files
... ...
@@ -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
-}