* Exiting experimental network UX
* removed experimental service UX
* integrated with the new network remote API
Signed-off-by: Madhu Venugopal <madhu@docker.com>
| ... | ... |
@@ -1,14 +1,207 @@ |
| 1 |
-// +build experimental |
|
| 2 |
- |
|
| 3 | 1 |
package client |
| 4 | 2 |
|
| 5 | 3 |
import ( |
| 6 |
- nwclient "github.com/docker/libnetwork/client" |
|
| 4 |
+ "bytes" |
|
| 5 |
+ "encoding/json" |
|
| 6 |
+ "fmt" |
|
| 7 |
+ "io" |
|
| 8 |
+ "text/tabwriter" |
|
| 9 |
+ |
|
| 10 |
+ "github.com/docker/docker/api/types" |
|
| 11 |
+ Cli "github.com/docker/docker/cli" |
|
| 12 |
+ flag "github.com/docker/docker/pkg/mflag" |
|
| 13 |
+ "github.com/docker/docker/pkg/stringid" |
|
| 7 | 14 |
) |
| 8 | 15 |
|
| 9 |
-// CmdNetwork is used to create, display and configure network endpoints. |
|
| 16 |
+// CmdNetwork is the parent subcommand for all network commands |
|
| 17 |
+// |
|
| 18 |
+// Usage: docker network <COMMAND> [OPTIONS] |
|
| 10 | 19 |
func (cli *DockerCli) CmdNetwork(args ...string) error {
|
| 11 |
- nCli := nwclient.NewNetworkCli(cli.out, cli.err, nwclient.CallFunc(cli.callWrapper)) |
|
| 12 |
- args = append([]string{"network"}, args...)
|
|
| 13 |
- return nCli.Cmd("docker", args...)
|
|
| 20 |
+ cmd := Cli.Subcmd("network", []string{"COMMAND [OPTIONS]"}, networkUsage(), false)
|
|
| 21 |
+ cmd.Require(flag.Min, 1) |
|
| 22 |
+ err := cmd.ParseFlags(args, true) |
|
| 23 |
+ cmd.Usage() |
|
| 24 |
+ return err |
|
| 25 |
+} |
|
| 26 |
+ |
|
| 27 |
+// CmdNetworkCreate creates a new network with a given name |
|
| 28 |
+// |
|
| 29 |
+// Usage: docker network create [OPTIONS] <NETWORK-NAME> |
|
| 30 |
+func (cli *DockerCli) CmdNetworkCreate(args ...string) error {
|
|
| 31 |
+ cmd := Cli.Subcmd("network create", []string{"NETWORK-NAME"}, "Creates a new network with a name specified by the user", false)
|
|
| 32 |
+ flDriver := cmd.String([]string{"d", "-driver"}, "", "Driver to manage the Network")
|
|
| 33 |
+ cmd.Require(flag.Exact, 1) |
|
| 34 |
+ err := cmd.ParseFlags(args, true) |
|
| 35 |
+ if err != nil {
|
|
| 36 |
+ return err |
|
| 37 |
+ } |
|
| 38 |
+ |
|
| 39 |
+ // Construct network create request body |
|
| 40 |
+ nc := types.NetworkCreate{Name: cmd.Arg(0), Driver: *flDriver, CheckDuplicate: true}
|
|
| 41 |
+ obj, _, err := readBody(cli.call("POST", "/networks/create", nc, nil))
|
|
| 42 |
+ if err != nil {
|
|
| 43 |
+ return err |
|
| 44 |
+ } |
|
| 45 |
+ var resp types.NetworkCreateResponse |
|
| 46 |
+ err = json.Unmarshal(obj, &resp) |
|
| 47 |
+ if err != nil {
|
|
| 48 |
+ return err |
|
| 49 |
+ } |
|
| 50 |
+ fmt.Fprintf(cli.out, "%s\n", resp.ID) |
|
| 51 |
+ return nil |
|
| 52 |
+} |
|
| 53 |
+ |
|
| 54 |
+// CmdNetworkRm deletes a network |
|
| 55 |
+// |
|
| 56 |
+// Usage: docker network rm <NETWORK-NAME | NETWORK-ID> |
|
| 57 |
+func (cli *DockerCli) CmdNetworkRm(args ...string) error {
|
|
| 58 |
+ cmd := Cli.Subcmd("network rm", []string{"NETWORK"}, "Deletes a network", false)
|
|
| 59 |
+ cmd.Require(flag.Exact, 1) |
|
| 60 |
+ err := cmd.ParseFlags(args, true) |
|
| 61 |
+ if err != nil {
|
|
| 62 |
+ return err |
|
| 63 |
+ } |
|
| 64 |
+ _, _, err = readBody(cli.call("DELETE", "/networks/"+cmd.Arg(0), nil, nil))
|
|
| 65 |
+ if err != nil {
|
|
| 66 |
+ return err |
|
| 67 |
+ } |
|
| 68 |
+ return nil |
|
| 69 |
+} |
|
| 70 |
+ |
|
| 71 |
+// CmdNetworkConnect connects a container to a network |
|
| 72 |
+// |
|
| 73 |
+// Usage: docker network connect <NETWORK> <CONTAINER> |
|
| 74 |
+func (cli *DockerCli) CmdNetworkConnect(args ...string) error {
|
|
| 75 |
+ cmd := Cli.Subcmd("network connect", []string{"NETWORK CONTAINER"}, "Connects a container to a network", false)
|
|
| 76 |
+ cmd.Require(flag.Exact, 2) |
|
| 77 |
+ err := cmd.ParseFlags(args, true) |
|
| 78 |
+ if err != nil {
|
|
| 79 |
+ return err |
|
| 80 |
+ } |
|
| 81 |
+ |
|
| 82 |
+ nc := types.NetworkConnect{Container: cmd.Arg(1)}
|
|
| 83 |
+ _, _, err = readBody(cli.call("POST", "/networks/"+cmd.Arg(0)+"/connect", nc, nil))
|
|
| 84 |
+ return err |
|
| 85 |
+} |
|
| 86 |
+ |
|
| 87 |
+// CmdNetworkDisconnect disconnects a container from a network |
|
| 88 |
+// |
|
| 89 |
+// Usage: docker network disconnect <NETWORK> <CONTAINER> |
|
| 90 |
+func (cli *DockerCli) CmdNetworkDisconnect(args ...string) error {
|
|
| 91 |
+ cmd := Cli.Subcmd("network disconnect", []string{"NETWORK CONTAINER"}, "Disconnects container from a network", false)
|
|
| 92 |
+ cmd.Require(flag.Exact, 2) |
|
| 93 |
+ err := cmd.ParseFlags(args, true) |
|
| 94 |
+ if err != nil {
|
|
| 95 |
+ return err |
|
| 96 |
+ } |
|
| 97 |
+ |
|
| 98 |
+ nc := types.NetworkConnect{Container: cmd.Arg(1)}
|
|
| 99 |
+ _, _, err = readBody(cli.call("POST", "/networks/"+cmd.Arg(0)+"/disconnect", nc, nil))
|
|
| 100 |
+ return err |
|
| 101 |
+} |
|
| 102 |
+ |
|
| 103 |
+// CmdNetworkLs lists all the netorks managed by docker daemon |
|
| 104 |
+// |
|
| 105 |
+// Usage: docker network ls [OPTIONS] |
|
| 106 |
+func (cli *DockerCli) CmdNetworkLs(args ...string) error {
|
|
| 107 |
+ cmd := Cli.Subcmd("network ls", []string{""}, "Lists all the networks created by the user", false)
|
|
| 108 |
+ quiet := cmd.Bool([]string{"q", "-quiet"}, false, "Only display numeric IDs")
|
|
| 109 |
+ noTrunc := cmd.Bool([]string{"", "-no-trunc"}, false, "Do not truncate the output")
|
|
| 110 |
+ nLatest := cmd.Bool([]string{"l", "-latest"}, false, "Show the latest network created")
|
|
| 111 |
+ last := cmd.Int([]string{"n"}, -1, "Show n last created networks")
|
|
| 112 |
+ err := cmd.ParseFlags(args, true) |
|
| 113 |
+ if err != nil {
|
|
| 114 |
+ return err |
|
| 115 |
+ } |
|
| 116 |
+ obj, _, err := readBody(cli.call("GET", "/networks", nil, nil))
|
|
| 117 |
+ if err != nil {
|
|
| 118 |
+ return err |
|
| 119 |
+ } |
|
| 120 |
+ if *last == -1 && *nLatest {
|
|
| 121 |
+ *last = 1 |
|
| 122 |
+ } |
|
| 123 |
+ |
|
| 124 |
+ var networkResources []types.NetworkResource |
|
| 125 |
+ err = json.Unmarshal(obj, &networkResources) |
|
| 126 |
+ if err != nil {
|
|
| 127 |
+ return err |
|
| 128 |
+ } |
|
| 129 |
+ |
|
| 130 |
+ wr := tabwriter.NewWriter(cli.out, 20, 1, 3, ' ', 0) |
|
| 131 |
+ |
|
| 132 |
+ // unless quiet (-q) is specified, print field titles |
|
| 133 |
+ if !*quiet {
|
|
| 134 |
+ fmt.Fprintln(wr, "NETWORK ID\tNAME\tDRIVER") |
|
| 135 |
+ } |
|
| 136 |
+ |
|
| 137 |
+ for _, networkResource := range networkResources {
|
|
| 138 |
+ ID := networkResource.ID |
|
| 139 |
+ netName := networkResource.Name |
|
| 140 |
+ if !*noTrunc {
|
|
| 141 |
+ ID = stringid.TruncateID(ID) |
|
| 142 |
+ } |
|
| 143 |
+ if *quiet {
|
|
| 144 |
+ fmt.Fprintln(wr, ID) |
|
| 145 |
+ continue |
|
| 146 |
+ } |
|
| 147 |
+ driver := networkResource.Driver |
|
| 148 |
+ fmt.Fprintf(wr, "%s\t%s\t%s\t", |
|
| 149 |
+ ID, |
|
| 150 |
+ netName, |
|
| 151 |
+ driver) |
|
| 152 |
+ fmt.Fprint(wr, "\n") |
|
| 153 |
+ } |
|
| 154 |
+ wr.Flush() |
|
| 155 |
+ return nil |
|
| 156 |
+} |
|
| 157 |
+ |
|
| 158 |
+// CmdNetworkInspect inspects the network object for more details |
|
| 159 |
+// |
|
| 160 |
+// Usage: docker network inspect <NETWORK> |
|
| 161 |
+// CmdNetworkInspect handles Network inspect UI |
|
| 162 |
+func (cli *DockerCli) CmdNetworkInspect(args ...string) error {
|
|
| 163 |
+ cmd := Cli.Subcmd("network inspect", []string{"NETWORK"}, "Displays detailed information on a network", false)
|
|
| 164 |
+ cmd.Require(flag.Exact, 1) |
|
| 165 |
+ err := cmd.ParseFlags(args, true) |
|
| 166 |
+ if err != nil {
|
|
| 167 |
+ return err |
|
| 168 |
+ } |
|
| 169 |
+ |
|
| 170 |
+ obj, _, err := readBody(cli.call("GET", "/networks/"+cmd.Arg(0), nil, nil))
|
|
| 171 |
+ if err != nil {
|
|
| 172 |
+ return err |
|
| 173 |
+ } |
|
| 174 |
+ networkResource := &types.NetworkResource{}
|
|
| 175 |
+ if err := json.NewDecoder(bytes.NewReader(obj)).Decode(networkResource); err != nil {
|
|
| 176 |
+ return err |
|
| 177 |
+ } |
|
| 178 |
+ |
|
| 179 |
+ indented := new(bytes.Buffer) |
|
| 180 |
+ if err := json.Indent(indented, obj, "", " "); err != nil {
|
|
| 181 |
+ return err |
|
| 182 |
+ } |
|
| 183 |
+ if _, err := io.Copy(cli.out, indented); err != nil {
|
|
| 184 |
+ return err |
|
| 185 |
+ } |
|
| 186 |
+ return nil |
|
| 187 |
+} |
|
| 188 |
+ |
|
| 189 |
+func networkUsage() string {
|
|
| 190 |
+ networkCommands := map[string]string{
|
|
| 191 |
+ "create": "Create a network", |
|
| 192 |
+ "connect": "Connect container to a network", |
|
| 193 |
+ "disconnect": "Disconnect container from a network", |
|
| 194 |
+ "inspect": "Display detailed network information", |
|
| 195 |
+ "ls": "List all networks", |
|
| 196 |
+ "rm": "Remove a network", |
|
| 197 |
+ } |
|
| 198 |
+ |
|
| 199 |
+ help := "Commands:\n" |
|
| 200 |
+ |
|
| 201 |
+ for cmd, description := range networkCommands {
|
|
| 202 |
+ help += fmt.Sprintf(" %-25.25s%s\n", cmd, description)
|
|
| 203 |
+ } |
|
| 204 |
+ |
|
| 205 |
+ help += fmt.Sprintf("\nRun 'docker network COMMAND --help' for more information on a command.")
|
|
| 206 |
+ return help |
|
| 14 | 207 |
} |
| 15 | 208 |
deleted file mode 100644 |
| ... | ... |
@@ -1,17 +0,0 @@ |
| 1 |
-// +build experimental |
|
| 2 |
- |
|
| 3 |
-package client |
|
| 4 |
- |
|
| 5 |
-import ( |
|
| 6 |
- "os" |
|
| 7 |
- |
|
| 8 |
- nwclient "github.com/docker/libnetwork/client" |
|
| 9 |
-) |
|
| 10 |
- |
|
| 11 |
-// CmdService is used to manage network services. |
|
| 12 |
-// service command is user to publish, attach and list a service from a container. |
|
| 13 |
-func (cli *DockerCli) CmdService(args ...string) error {
|
|
| 14 |
- nCli := nwclient.NewNetworkCli(cli.out, cli.err, nwclient.CallFunc(cli.callWrapper)) |
|
| 15 |
- args = append([]string{"service"}, args...)
|
|
| 16 |
- return nCli.Cmd(os.Args[0], args...) |
|
| 17 |
-} |
| 18 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,113 +0,0 @@ |
| 1 |
-// +build experimental |
|
| 2 |
- |
|
| 3 |
-package main |
|
| 4 |
- |
|
| 5 |
-import ( |
|
| 6 |
- "encoding/json" |
|
| 7 |
- "fmt" |
|
| 8 |
- "net/http" |
|
| 9 |
- |
|
| 10 |
- "github.com/go-check/check" |
|
| 11 |
-) |
|
| 12 |
- |
|
| 13 |
-func isServiceAvailable(c *check.C, name string, network string) bool {
|
|
| 14 |
- status, body, err := sockRequest("GET", "/services", nil)
|
|
| 15 |
- c.Assert(status, check.Equals, http.StatusOK) |
|
| 16 |
- c.Assert(err, check.IsNil) |
|
| 17 |
- |
|
| 18 |
- var inspectJSON []struct {
|
|
| 19 |
- Name string |
|
| 20 |
- ID string |
|
| 21 |
- Network string |
|
| 22 |
- } |
|
| 23 |
- if err = json.Unmarshal(body, &inspectJSON); err != nil {
|
|
| 24 |
- c.Fatalf("unable to unmarshal response body: %v", err)
|
|
| 25 |
- } |
|
| 26 |
- for _, s := range inspectJSON {
|
|
| 27 |
- if s.Name == name && s.Network == network {
|
|
| 28 |
- return true |
|
| 29 |
- } |
|
| 30 |
- } |
|
| 31 |
- return false |
|
| 32 |
- |
|
| 33 |
-} |
|
| 34 |
- |
|
| 35 |
-func isServiceNetworkAvailable(c *check.C, name string) bool {
|
|
| 36 |
- status, body, err := sockRequest("GET", "/networks", nil)
|
|
| 37 |
- c.Assert(status, check.Equals, http.StatusOK) |
|
| 38 |
- c.Assert(err, check.IsNil) |
|
| 39 |
- |
|
| 40 |
- var inspectJSON []struct {
|
|
| 41 |
- Name string |
|
| 42 |
- ID string |
|
| 43 |
- Type string |
|
| 44 |
- } |
|
| 45 |
- if err = json.Unmarshal(body, &inspectJSON); err != nil {
|
|
| 46 |
- c.Fatalf("unable to unmarshal response body: %v", err)
|
|
| 47 |
- } |
|
| 48 |
- for _, n := range inspectJSON {
|
|
| 49 |
- if n.Name == name {
|
|
| 50 |
- return true |
|
| 51 |
- } |
|
| 52 |
- } |
|
| 53 |
- return false |
|
| 54 |
- |
|
| 55 |
-} |
|
| 56 |
- |
|
| 57 |
-func (s *DockerSuite) TestServiceApiCreateDelete(c *check.C) {
|
|
| 58 |
- name := "testnetwork" |
|
| 59 |
- config := map[string]interface{}{
|
|
| 60 |
- "name": name, |
|
| 61 |
- "network_type": "bridge", |
|
| 62 |
- } |
|
| 63 |
- |
|
| 64 |
- status, resp, err := sockRequest("POST", "/networks", config)
|
|
| 65 |
- c.Assert(status, check.Equals, http.StatusCreated) |
|
| 66 |
- c.Assert(err, check.IsNil) |
|
| 67 |
- |
|
| 68 |
- if !isServiceNetworkAvailable(c, name) {
|
|
| 69 |
- c.Fatalf("Network %s not found", name)
|
|
| 70 |
- } |
|
| 71 |
- |
|
| 72 |
- var nid string |
|
| 73 |
- err = json.Unmarshal(resp, &nid) |
|
| 74 |
- if err != nil {
|
|
| 75 |
- c.Fatal(err) |
|
| 76 |
- } |
|
| 77 |
- |
|
| 78 |
- sname := "service1" |
|
| 79 |
- sconfig := map[string]interface{}{
|
|
| 80 |
- "name": sname, |
|
| 81 |
- "network_name": name, |
|
| 82 |
- } |
|
| 83 |
- |
|
| 84 |
- status, resp, err = sockRequest("POST", "/services", sconfig)
|
|
| 85 |
- c.Assert(status, check.Equals, http.StatusCreated) |
|
| 86 |
- c.Assert(err, check.IsNil) |
|
| 87 |
- |
|
| 88 |
- if !isServiceAvailable(c, sname, name) {
|
|
| 89 |
- c.Fatalf("Service %s.%s not found", sname, name)
|
|
| 90 |
- } |
|
| 91 |
- |
|
| 92 |
- var id string |
|
| 93 |
- err = json.Unmarshal(resp, &id) |
|
| 94 |
- if err != nil {
|
|
| 95 |
- c.Fatal(err) |
|
| 96 |
- } |
|
| 97 |
- |
|
| 98 |
- status, _, err = sockRequest("DELETE", fmt.Sprintf("/services/%s", id), nil)
|
|
| 99 |
- c.Assert(status, check.Equals, http.StatusOK) |
|
| 100 |
- c.Assert(err, check.IsNil) |
|
| 101 |
- |
|
| 102 |
- if isServiceAvailable(c, sname, name) {
|
|
| 103 |
- c.Fatalf("Service %s.%s not deleted", sname, name)
|
|
| 104 |
- } |
|
| 105 |
- |
|
| 106 |
- status, _, err = sockRequest("DELETE", fmt.Sprintf("/networks/%s", nid), nil)
|
|
| 107 |
- c.Assert(status, check.Equals, http.StatusOK) |
|
| 108 |
- c.Assert(err, check.IsNil) |
|
| 109 |
- |
|
| 110 |
- if isNetworkAvailable(c, name) {
|
|
| 111 |
- c.Fatalf("Network %s not deleted", name)
|
|
| 112 |
- } |
|
| 113 |
-} |
| ... | ... |
@@ -1,10 +1,11 @@ |
| 1 |
-// +build experimental |
|
| 2 |
- |
|
| 3 | 1 |
package main |
| 4 | 2 |
|
| 5 | 3 |
import ( |
| 4 |
+ "encoding/json" |
|
| 5 |
+ "net" |
|
| 6 | 6 |
"strings" |
| 7 | 7 |
|
| 8 |
+ "github.com/docker/docker/api/types" |
|
| 8 | 9 |
"github.com/go-check/check" |
| 9 | 10 |
) |
| 10 | 11 |
|
| ... | ... |
@@ -31,6 +32,14 @@ func isNwPresent(c *check.C, name string) bool {
|
| 31 | 31 |
return false |
| 32 | 32 |
} |
| 33 | 33 |
|
| 34 |
+func getNwResource(c *check.C, name string) *types.NetworkResource {
|
|
| 35 |
+ out, _ := dockerCmd(c, "network", "inspect", name) |
|
| 36 |
+ nr := types.NetworkResource{}
|
|
| 37 |
+ err := json.Unmarshal([]byte(out), &nr) |
|
| 38 |
+ c.Assert(err, check.IsNil) |
|
| 39 |
+ return &nr |
|
| 40 |
+} |
|
| 41 |
+ |
|
| 34 | 42 |
func (s *DockerSuite) TestDockerNetworkLsDefault(c *check.C) {
|
| 35 | 43 |
defaults := []string{"bridge", "host", "none"}
|
| 36 | 44 |
for _, nn := range defaults {
|
| ... | ... |
@@ -45,3 +54,45 @@ func (s *DockerSuite) TestDockerNetworkCreateDelete(c *check.C) {
|
| 45 | 45 |
dockerCmd(c, "network", "rm", "test") |
| 46 | 46 |
assertNwNotAvailable(c, "test") |
| 47 | 47 |
} |
| 48 |
+ |
|
| 49 |
+func (s *DockerSuite) TestDockerNetworkConnectDisconnect(c *check.C) {
|
|
| 50 |
+ dockerCmd(c, "network", "create", "test") |
|
| 51 |
+ assertNwIsAvailable(c, "test") |
|
| 52 |
+ nr := getNwResource(c, "test") |
|
| 53 |
+ |
|
| 54 |
+ c.Assert(nr.Name, check.Equals, "test") |
|
| 55 |
+ c.Assert(len(nr.Containers), check.Equals, 0) |
|
| 56 |
+ |
|
| 57 |
+ // run a container |
|
| 58 |
+ out, _ := dockerCmd(c, "run", "-d", "--name", "test", "busybox", "top") |
|
| 59 |
+ c.Assert(waitRun("test"), check.IsNil)
|
|
| 60 |
+ containerID := strings.TrimSpace(out) |
|
| 61 |
+ |
|
| 62 |
+ // connect the container to the test network |
|
| 63 |
+ dockerCmd(c, "network", "connect", "test", containerID) |
|
| 64 |
+ |
|
| 65 |
+ // inspect the network to make sure container is connected |
|
| 66 |
+ nr = getNetworkResource(c, nr.ID) |
|
| 67 |
+ c.Assert(len(nr.Containers), check.Equals, 1) |
|
| 68 |
+ c.Assert(nr.Containers[containerID], check.NotNil) |
|
| 69 |
+ |
|
| 70 |
+ // check if container IP matches network inspect |
|
| 71 |
+ ip, _, err := net.ParseCIDR(nr.Containers[containerID].IPv4Address) |
|
| 72 |
+ c.Assert(err, check.IsNil) |
|
| 73 |
+ containerIP := findContainerIP(c, "test") |
|
| 74 |
+ c.Assert(ip.String(), check.Equals, containerIP) |
|
| 75 |
+ |
|
| 76 |
+ // disconnect container from the network |
|
| 77 |
+ dockerCmd(c, "network", "disconnect", "test", containerID) |
|
| 78 |
+ nr = getNwResource(c, "test") |
|
| 79 |
+ c.Assert(nr.Name, check.Equals, "test") |
|
| 80 |
+ c.Assert(len(nr.Containers), check.Equals, 0) |
|
| 81 |
+ |
|
| 82 |
+ // check if network connect fails for inactive containers |
|
| 83 |
+ dockerCmd(c, "stop", containerID) |
|
| 84 |
+ _, _, err = dockerCmdWithError("network", "connect", "test", containerID)
|
|
| 85 |
+ c.Assert(err, check.NotNil) |
|
| 86 |
+ |
|
| 87 |
+ dockerCmd(c, "network", "rm", "test") |
|
| 88 |
+ assertNwNotAvailable(c, "test") |
|
| 89 |
+} |
| ... | ... |
@@ -18,7 +18,9 @@ import ( |
| 18 | 18 |
"sync" |
| 19 | 19 |
"time" |
| 20 | 20 |
|
| 21 |
+ "github.com/docker/docker/pkg/integration/checker" |
|
| 21 | 22 |
"github.com/docker/docker/pkg/nat" |
| 23 |
+ "github.com/docker/docker/runconfig" |
|
| 22 | 24 |
"github.com/docker/libnetwork/resolvconf" |
| 23 | 25 |
"github.com/go-check/check" |
| 24 | 26 |
) |
| ... | ... |
@@ -3408,6 +3410,7 @@ func (s *DockerSuite) TestContainersInUserDefinedNetwork(c *check.C) {
|
| 3408 | 3408 |
testRequires(c, DaemonIsLinux) |
| 3409 | 3409 |
dockerCmd(c, "network", "create", "-d", "bridge", "testnetwork") |
| 3410 | 3410 |
dockerCmd(c, "run", "-d", "--net=testnetwork", "--name=first", "busybox", "top") |
| 3411 |
+ c.Assert(waitRun("first"), check.IsNil)
|
|
| 3411 | 3412 |
dockerCmd(c, "run", "-t", "--net=testnetwork", "--name=second", "busybox", "ping", "-c", "1", "first") |
| 3412 | 3413 |
dockerCmd(c, "stop", "first") |
| 3413 | 3414 |
dockerCmd(c, "stop", "second") |
| ... | ... |
@@ -3421,7 +3424,9 @@ func (s *DockerSuite) TestContainersInMultipleNetworks(c *check.C) {
|
| 3421 | 3421 |
dockerCmd(c, "network", "create", "-d", "bridge", "testnetwork2") |
| 3422 | 3422 |
// Run and connect containers to testnetwork1 |
| 3423 | 3423 |
dockerCmd(c, "run", "-d", "--net=testnetwork1", "--name=first", "busybox", "top") |
| 3424 |
+ c.Assert(waitRun("first"), check.IsNil)
|
|
| 3424 | 3425 |
dockerCmd(c, "run", "-d", "--net=testnetwork1", "--name=second", "busybox", "top") |
| 3426 |
+ c.Assert(waitRun("second"), check.IsNil)
|
|
| 3425 | 3427 |
// Check connectivity between containers in testnetwork2 |
| 3426 | 3428 |
dockerCmd(c, "exec", "first", "ping", "-c", "1", "second.testnetwork1") |
| 3427 | 3429 |
// Connect containers to testnetwork2 |
| ... | ... |
@@ -3440,9 +3445,11 @@ func (s *DockerSuite) TestContainersNetworkIsolation(c *check.C) {
|
| 3440 | 3440 |
// Create 2 networks using bridge driver |
| 3441 | 3441 |
dockerCmd(c, "network", "create", "-d", "bridge", "testnetwork1") |
| 3442 | 3442 |
dockerCmd(c, "network", "create", "-d", "bridge", "testnetwork2") |
| 3443 |
- // Run 1 containers in testnetwork1 and another in testnetwork2 |
|
| 3443 |
+ // Run 1 container in testnetwork1 and another in testnetwork2 |
|
| 3444 | 3444 |
dockerCmd(c, "run", "-d", "--net=testnetwork1", "--name=first", "busybox", "top") |
| 3445 |
+ c.Assert(waitRun("first"), check.IsNil)
|
|
| 3445 | 3446 |
dockerCmd(c, "run", "-d", "--net=testnetwork2", "--name=second", "busybox", "top") |
| 3447 |
+ c.Assert(waitRun("second"), check.IsNil)
|
|
| 3446 | 3448 |
|
| 3447 | 3449 |
// Check Isolation between containers : ping must fail |
| 3448 | 3450 |
_, _, err := dockerCmdWithError("exec", "first", "ping", "-c", "1", "second")
|
| ... | ... |
@@ -3471,7 +3478,9 @@ func (s *DockerSuite) TestNetworkRmWithActiveContainers(c *check.C) {
|
| 3471 | 3471 |
dockerCmd(c, "network", "create", "-d", "bridge", "testnetwork1") |
| 3472 | 3472 |
// Run and connect containers to testnetwork1 |
| 3473 | 3473 |
dockerCmd(c, "run", "-d", "--net=testnetwork1", "--name=first", "busybox", "top") |
| 3474 |
+ c.Assert(waitRun("first"), check.IsNil)
|
|
| 3474 | 3475 |
dockerCmd(c, "run", "-d", "--net=testnetwork1", "--name=second", "busybox", "top") |
| 3476 |
+ c.Assert(waitRun("second"), check.IsNil)
|
|
| 3475 | 3477 |
// Network delete with active containers must fail |
| 3476 | 3478 |
_, _, err := dockerCmdWithError("network", "rm", "testnetwork1")
|
| 3477 | 3479 |
c.Assert(err, check.NotNil) |
| ... | ... |
@@ -3492,7 +3501,9 @@ func (s *DockerSuite) TestContainerRestartInMultipleNetworks(c *check.C) {
|
| 3492 | 3492 |
dockerCmd(c, "network", "create", "-d", "bridge", "testnetwork2") |
| 3493 | 3493 |
// Run and connect containers to testnetwork1 |
| 3494 | 3494 |
dockerCmd(c, "run", "-d", "--net=testnetwork1", "--name=first", "busybox", "top") |
| 3495 |
+ c.Assert(waitRun("first"), check.IsNil)
|
|
| 3495 | 3496 |
dockerCmd(c, "run", "-d", "--net=testnetwork1", "--name=second", "busybox", "top") |
| 3497 |
+ c.Assert(waitRun("second"), check.IsNil)
|
|
| 3496 | 3498 |
// Check connectivity between containers in testnetwork2 |
| 3497 | 3499 |
dockerCmd(c, "exec", "first", "ping", "-c", "1", "second.testnetwork1") |
| 3498 | 3500 |
// Connect containers to testnetwork2 |
| ... | ... |
@@ -3523,6 +3534,7 @@ func (s *DockerSuite) TestContainerWithConflictingHostNetworks(c *check.C) {
|
| 3523 | 3523 |
testRequires(c, DaemonIsLinux) |
| 3524 | 3524 |
// Run a container with --net=host |
| 3525 | 3525 |
dockerCmd(c, "run", "-d", "--net=host", "--name=first", "busybox", "top") |
| 3526 |
+ c.Assert(waitRun("first"), check.IsNil)
|
|
| 3526 | 3527 |
|
| 3527 | 3528 |
// Create a network using bridge driver |
| 3528 | 3529 |
dockerCmd(c, "network", "create", "-d", "bridge", "testnetwork1") |
| ... | ... |
@@ -3537,14 +3549,43 @@ func (s *DockerSuite) TestContainerWithConflictingHostNetworks(c *check.C) {
|
| 3537 | 3537 |
func (s *DockerSuite) TestContainerWithConflictingSharedNetwork(c *check.C) {
|
| 3538 | 3538 |
testRequires(c, DaemonIsLinux) |
| 3539 | 3539 |
dockerCmd(c, "run", "-d", "--name=first", "busybox", "top") |
| 3540 |
+ c.Assert(waitRun("first"), check.IsNil)
|
|
| 3540 | 3541 |
// Run second container in first container's network namespace |
| 3541 | 3542 |
dockerCmd(c, "run", "-d", "--net=container:first", "--name=second", "busybox", "top") |
| 3543 |
+ c.Assert(waitRun("second"), check.IsNil)
|
|
| 3542 | 3544 |
|
| 3543 | 3545 |
// Create a network using bridge driver |
| 3544 | 3546 |
dockerCmd(c, "network", "create", "-d", "bridge", "testnetwork1") |
| 3545 | 3547 |
|
| 3546 | 3548 |
// Connecting to the user defined network must fail |
| 3547 |
- _, _, err := dockerCmdWithError("network", "connect", "testnetwork1", "second")
|
|
| 3549 |
+ out, _, err := dockerCmdWithError("network", "connect", "testnetwork1", "second")
|
|
| 3550 |
+ c.Assert(err, check.NotNil) |
|
| 3551 |
+ c.Assert(out, checker.Contains, runconfig.ErrConflictSharedNetwork.Error()) |
|
| 3552 |
+ |
|
| 3553 |
+ dockerCmd(c, "stop", "first") |
|
| 3554 |
+ dockerCmd(c, "stop", "second") |
|
| 3555 |
+ dockerCmd(c, "network", "rm", "testnetwork1") |
|
| 3556 |
+} |
|
| 3557 |
+ |
|
| 3558 |
+func (s *DockerSuite) TestContainerWithConflictingNoneNetwork(c *check.C) {
|
|
| 3559 |
+ testRequires(c, DaemonIsLinux) |
|
| 3560 |
+ dockerCmd(c, "run", "-d", "--net=none", "--name=first", "busybox", "top") |
|
| 3561 |
+ c.Assert(waitRun("first"), check.IsNil)
|
|
| 3562 |
+ |
|
| 3563 |
+ // Create a network using bridge driver |
|
| 3564 |
+ dockerCmd(c, "network", "create", "-d", "bridge", "testnetwork1") |
|
| 3565 |
+ |
|
| 3566 |
+ // Connecting to the user defined network must fail |
|
| 3567 |
+ out, _, err := dockerCmdWithError("network", "connect", "testnetwork1", "first")
|
|
| 3568 |
+ c.Assert(err, check.NotNil) |
|
| 3569 |
+ c.Assert(out, checker.Contains, runconfig.ErrConflictNoNetwork.Error()) |
|
| 3570 |
+ |
|
| 3571 |
+ // create a container connected to testnetwork1 |
|
| 3572 |
+ dockerCmd(c, "run", "-d", "--net=testnetwork1", "--name=second", "busybox", "top") |
|
| 3573 |
+ c.Assert(waitRun("second"), check.IsNil)
|
|
| 3574 |
+ |
|
| 3575 |
+ // Connect second container to none network. it must fail as well |
|
| 3576 |
+ _, _, err = dockerCmdWithError("network", "connect", "none", "second")
|
|
| 3548 | 3577 |
c.Assert(err, check.NotNil) |
| 3549 | 3578 |
|
| 3550 | 3579 |
dockerCmd(c, "stop", "first") |
| 3551 | 3580 |
deleted file mode 100644 |
| ... | ... |
@@ -1,69 +0,0 @@ |
| 1 |
-// +build experimental |
|
| 2 |
- |
|
| 3 |
-package main |
|
| 4 |
- |
|
| 5 |
-import ( |
|
| 6 |
- "fmt" |
|
| 7 |
- "strings" |
|
| 8 |
- |
|
| 9 |
- "github.com/go-check/check" |
|
| 10 |
-) |
|
| 11 |
- |
|
| 12 |
-func assertSrvIsAvailable(c *check.C, sname, name string) {
|
|
| 13 |
- if !isSrvPresent(c, sname, name) {
|
|
| 14 |
- c.Fatalf("Service %s on network %s not found in service ls o/p", sname, name)
|
|
| 15 |
- } |
|
| 16 |
-} |
|
| 17 |
- |
|
| 18 |
-func assertSrvNotAvailable(c *check.C, sname, name string) {
|
|
| 19 |
- if isSrvPresent(c, sname, name) {
|
|
| 20 |
- c.Fatalf("Found service %s on network %s in service ls o/p", sname, name)
|
|
| 21 |
- } |
|
| 22 |
-} |
|
| 23 |
- |
|
| 24 |
-func isSrvPresent(c *check.C, sname, name string) bool {
|
|
| 25 |
- out, _, _ := dockerCmdWithStdoutStderr(c, "service", "ls") |
|
| 26 |
- lines := strings.Split(out, "\n") |
|
| 27 |
- for i := 1; i < len(lines)-1; i++ {
|
|
| 28 |
- if strings.Contains(lines[i], sname) && strings.Contains(lines[i], name) {
|
|
| 29 |
- return true |
|
| 30 |
- } |
|
| 31 |
- } |
|
| 32 |
- return false |
|
| 33 |
-} |
|
| 34 |
- |
|
| 35 |
-func isCntPresent(c *check.C, cname, sname, name string) bool {
|
|
| 36 |
- out, _, _ := dockerCmdWithStdoutStderr(c, "service", "ls", "--no-trunc") |
|
| 37 |
- lines := strings.Split(out, "\n") |
|
| 38 |
- for i := 1; i < len(lines)-1; i++ {
|
|
| 39 |
- fmt.Println(lines) |
|
| 40 |
- if strings.Contains(lines[i], name) && strings.Contains(lines[i], sname) && strings.Contains(lines[i], cname) {
|
|
| 41 |
- return true |
|
| 42 |
- } |
|
| 43 |
- } |
|
| 44 |
- return false |
|
| 45 |
-} |
|
| 46 |
- |
|
| 47 |
-func (s *DockerSuite) TestDockerServiceCreateDelete(c *check.C) {
|
|
| 48 |
- dockerCmdWithStdoutStderr(c, "network", "create", "test") |
|
| 49 |
- assertNwIsAvailable(c, "test") |
|
| 50 |
- |
|
| 51 |
- dockerCmdWithStdoutStderr(c, "service", "publish", "s1.test") |
|
| 52 |
- assertSrvIsAvailable(c, "s1", "test") |
|
| 53 |
- |
|
| 54 |
- dockerCmdWithStdoutStderr(c, "service", "unpublish", "s1.test") |
|
| 55 |
- assertSrvNotAvailable(c, "s1", "test") |
|
| 56 |
- |
|
| 57 |
- dockerCmdWithStdoutStderr(c, "network", "rm", "test") |
|
| 58 |
- assertNwNotAvailable(c, "test") |
|
| 59 |
-} |
|
| 60 |
- |
|
| 61 |
-func (s *DockerSuite) TestDockerPublishServiceFlag(c *check.C) {
|
|
| 62 |
- // Run saying the container is the backend for the specified service on the specified network |
|
| 63 |
- out, _ := dockerCmd(c, "run", "-d", "--expose=23", "--publish-service", "telnet.production", "busybox", "top") |
|
| 64 |
- cid := strings.TrimSpace(out) |
|
| 65 |
- |
|
| 66 |
- // Verify container is attached in service ps o/p |
|
| 67 |
- assertSrvIsAvailable(c, "telnet", "production") |
|
| 68 |
- dockerCmd(c, "rm", "-f", cid) |
|
| 69 |
-} |
| 70 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,115 +0,0 @@ |
| 1 |
-package client |
|
| 2 |
- |
|
| 3 |
-import ( |
|
| 4 |
- "fmt" |
|
| 5 |
- "io" |
|
| 6 |
- "io/ioutil" |
|
| 7 |
- "net/http" |
|
| 8 |
- "reflect" |
|
| 9 |
- "strings" |
|
| 10 |
- |
|
| 11 |
- flag "github.com/docker/docker/pkg/mflag" |
|
| 12 |
-) |
|
| 13 |
- |
|
| 14 |
-// CallFunc provides environment specific call utility to invoke backend functions from UI |
|
| 15 |
-type CallFunc func(string, string, interface{}, map[string][]string) (io.ReadCloser, http.Header, int, error)
|
|
| 16 |
- |
|
| 17 |
-// NetworkCli is the UI object for network subcmds |
|
| 18 |
-type NetworkCli struct {
|
|
| 19 |
- out io.Writer |
|
| 20 |
- err io.Writer |
|
| 21 |
- call CallFunc |
|
| 22 |
-} |
|
| 23 |
- |
|
| 24 |
-// NewNetworkCli is a convenient function to create a NetworkCli object |
|
| 25 |
-func NewNetworkCli(out, err io.Writer, call CallFunc) *NetworkCli {
|
|
| 26 |
- return &NetworkCli{
|
|
| 27 |
- out: out, |
|
| 28 |
- err: err, |
|
| 29 |
- call: call, |
|
| 30 |
- } |
|
| 31 |
-} |
|
| 32 |
- |
|
| 33 |
-// getMethod is Borrowed from Docker UI which uses reflection to identify the UI Handler |
|
| 34 |
-func (cli *NetworkCli) getMethod(args ...string) (func(string, ...string) error, bool) {
|
|
| 35 |
- camelArgs := make([]string, len(args)) |
|
| 36 |
- for i, s := range args {
|
|
| 37 |
- if len(s) == 0 {
|
|
| 38 |
- return nil, false |
|
| 39 |
- } |
|
| 40 |
- camelArgs[i] = strings.ToUpper(s[:1]) + strings.ToLower(s[1:]) |
|
| 41 |
- } |
|
| 42 |
- methodName := "Cmd" + strings.Join(camelArgs, "") |
|
| 43 |
- method := reflect.ValueOf(cli).MethodByName(methodName) |
|
| 44 |
- if !method.IsValid() {
|
|
| 45 |
- return nil, false |
|
| 46 |
- } |
|
| 47 |
- return method.Interface().(func(string, ...string) error), true |
|
| 48 |
-} |
|
| 49 |
- |
|
| 50 |
-// Cmd is borrowed from Docker UI and acts as the entry point for network UI commands. |
|
| 51 |
-// network UI commands are designed to be invoked from multiple parent chains |
|
| 52 |
-func (cli *NetworkCli) Cmd(chain string, args ...string) error {
|
|
| 53 |
- if len(args) > 2 {
|
|
| 54 |
- method, exists := cli.getMethod(args[:3]...) |
|
| 55 |
- if exists {
|
|
| 56 |
- return method(chain+" "+args[0]+" "+args[1], args[3:]...) |
|
| 57 |
- } |
|
| 58 |
- } |
|
| 59 |
- if len(args) > 1 {
|
|
| 60 |
- method, exists := cli.getMethod(args[:2]...) |
|
| 61 |
- if exists {
|
|
| 62 |
- return method(chain+" "+args[0], args[2:]...) |
|
| 63 |
- } |
|
| 64 |
- } |
|
| 65 |
- if len(args) > 0 {
|
|
| 66 |
- method, exists := cli.getMethod(args[0]) |
|
| 67 |
- if !exists {
|
|
| 68 |
- return fmt.Errorf("%s: '%s' is not a %s command. See '%s --help'.\n", chain, args[0], chain, chain)
|
|
| 69 |
- } |
|
| 70 |
- return method(chain, args[1:]...) |
|
| 71 |
- } |
|
| 72 |
- flag.Usage() |
|
| 73 |
- return nil |
|
| 74 |
-} |
|
| 75 |
- |
|
| 76 |
-// Subcmd is borrowed from Docker UI and performs the same function of configuring the subCmds |
|
| 77 |
-func (cli *NetworkCli) Subcmd(chain, name, signature, description string, exitOnError bool) *flag.FlagSet {
|
|
| 78 |
- var errorHandling flag.ErrorHandling |
|
| 79 |
- if exitOnError {
|
|
| 80 |
- errorHandling = flag.ExitOnError |
|
| 81 |
- } else {
|
|
| 82 |
- errorHandling = flag.ContinueOnError |
|
| 83 |
- } |
|
| 84 |
- flags := flag.NewFlagSet(name, errorHandling) |
|
| 85 |
- flags.Usage = func() {
|
|
| 86 |
- flags.ShortUsage() |
|
| 87 |
- flags.PrintDefaults() |
|
| 88 |
- } |
|
| 89 |
- flags.ShortUsage = func() {
|
|
| 90 |
- options := "" |
|
| 91 |
- if signature != "" {
|
|
| 92 |
- signature = " " + signature |
|
| 93 |
- } |
|
| 94 |
- if flags.FlagCountUndeprecated() > 0 {
|
|
| 95 |
- options = " [OPTIONS]" |
|
| 96 |
- } |
|
| 97 |
- fmt.Fprintf(cli.out, "\nUsage: %s %s%s%s\n\n%s\n\n", chain, name, options, signature, description) |
|
| 98 |
- flags.SetOutput(cli.out) |
|
| 99 |
- } |
|
| 100 |
- return flags |
|
| 101 |
-} |
|
| 102 |
- |
|
| 103 |
-func readBody(stream io.ReadCloser, hdr http.Header, statusCode int, err error) ([]byte, int, error) {
|
|
| 104 |
- if stream != nil {
|
|
| 105 |
- defer stream.Close() |
|
| 106 |
- } |
|
| 107 |
- if err != nil {
|
|
| 108 |
- return nil, statusCode, err |
|
| 109 |
- } |
|
| 110 |
- body, err := ioutil.ReadAll(stream) |
|
| 111 |
- if err != nil {
|
|
| 112 |
- return nil, -1, err |
|
| 113 |
- } |
|
| 114 |
- return body, statusCode, nil |
|
| 115 |
-} |
| 116 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,231 +0,0 @@ |
| 1 |
-package client |
|
| 2 |
- |
|
| 3 |
-import ( |
|
| 4 |
- "bytes" |
|
| 5 |
- "encoding/json" |
|
| 6 |
- "fmt" |
|
| 7 |
- "net/http" |
|
| 8 |
- "text/tabwriter" |
|
| 9 |
- |
|
| 10 |
- flag "github.com/docker/docker/pkg/mflag" |
|
| 11 |
- "github.com/docker/docker/pkg/stringid" |
|
| 12 |
-) |
|
| 13 |
- |
|
| 14 |
-type command struct {
|
|
| 15 |
- name string |
|
| 16 |
- description string |
|
| 17 |
-} |
|
| 18 |
- |
|
| 19 |
-var ( |
|
| 20 |
- networkCommands = []command{
|
|
| 21 |
- {"create", "Create a network"},
|
|
| 22 |
- {"rm", "Remove a network"},
|
|
| 23 |
- {"ls", "List all networks"},
|
|
| 24 |
- {"info", "Display information of a network"},
|
|
| 25 |
- } |
|
| 26 |
-) |
|
| 27 |
- |
|
| 28 |
-// CmdNetwork handles the root Network UI |
|
| 29 |
-func (cli *NetworkCli) CmdNetwork(chain string, args ...string) error {
|
|
| 30 |
- cmd := cli.Subcmd(chain, "network", "COMMAND [OPTIONS] [arg...]", networkUsage(chain), false) |
|
| 31 |
- cmd.Require(flag.Min, 1) |
|
| 32 |
- err := cmd.ParseFlags(args, true) |
|
| 33 |
- if err == nil {
|
|
| 34 |
- cmd.Usage() |
|
| 35 |
- return fmt.Errorf("invalid command : %v", args)
|
|
| 36 |
- } |
|
| 37 |
- return err |
|
| 38 |
-} |
|
| 39 |
- |
|
| 40 |
-// CmdNetworkCreate handles Network Create UI |
|
| 41 |
-func (cli *NetworkCli) CmdNetworkCreate(chain string, args ...string) error {
|
|
| 42 |
- cmd := cli.Subcmd(chain, "create", "NETWORK-NAME", "Creates a new network with a name specified by the user", false) |
|
| 43 |
- flDriver := cmd.String([]string{"d", "-driver"}, "", "Driver to manage the Network")
|
|
| 44 |
- cmd.Require(flag.Exact, 1) |
|
| 45 |
- err := cmd.ParseFlags(args, true) |
|
| 46 |
- if err != nil {
|
|
| 47 |
- return err |
|
| 48 |
- } |
|
| 49 |
- |
|
| 50 |
- // Construct network create request body |
|
| 51 |
- ops := make(map[string]interface{})
|
|
| 52 |
- nc := networkCreate{Name: cmd.Arg(0), NetworkType: *flDriver, Options: ops}
|
|
| 53 |
- obj, _, err := readBody(cli.call("POST", "/networks", nc, nil))
|
|
| 54 |
- if err != nil {
|
|
| 55 |
- return err |
|
| 56 |
- } |
|
| 57 |
- var replyID string |
|
| 58 |
- err = json.Unmarshal(obj, &replyID) |
|
| 59 |
- if err != nil {
|
|
| 60 |
- return err |
|
| 61 |
- } |
|
| 62 |
- fmt.Fprintf(cli.out, "%s\n", replyID) |
|
| 63 |
- return nil |
|
| 64 |
-} |
|
| 65 |
- |
|
| 66 |
-// CmdNetworkRm handles Network Delete UI |
|
| 67 |
-func (cli *NetworkCli) CmdNetworkRm(chain string, args ...string) error {
|
|
| 68 |
- cmd := cli.Subcmd(chain, "rm", "NETWORK", "Deletes a network", false) |
|
| 69 |
- cmd.Require(flag.Exact, 1) |
|
| 70 |
- err := cmd.ParseFlags(args, true) |
|
| 71 |
- if err != nil {
|
|
| 72 |
- return err |
|
| 73 |
- } |
|
| 74 |
- id, err := lookupNetworkID(cli, cmd.Arg(0)) |
|
| 75 |
- if err != nil {
|
|
| 76 |
- return err |
|
| 77 |
- } |
|
| 78 |
- _, _, err = readBody(cli.call("DELETE", "/networks/"+id, nil, nil))
|
|
| 79 |
- if err != nil {
|
|
| 80 |
- return err |
|
| 81 |
- } |
|
| 82 |
- return nil |
|
| 83 |
-} |
|
| 84 |
- |
|
| 85 |
-// CmdNetworkLs handles Network List UI |
|
| 86 |
-func (cli *NetworkCli) CmdNetworkLs(chain string, args ...string) error {
|
|
| 87 |
- cmd := cli.Subcmd(chain, "ls", "", "Lists all the networks created by the user", false) |
|
| 88 |
- quiet := cmd.Bool([]string{"q", "-quiet"}, false, "Only display numeric IDs")
|
|
| 89 |
- noTrunc := cmd.Bool([]string{"#notrunc", "-no-trunc"}, false, "Do not truncate the output")
|
|
| 90 |
- nLatest := cmd.Bool([]string{"l", "-latest"}, false, "Show the latest network created")
|
|
| 91 |
- last := cmd.Int([]string{"n"}, -1, "Show n last created networks")
|
|
| 92 |
- err := cmd.ParseFlags(args, true) |
|
| 93 |
- if err != nil {
|
|
| 94 |
- return err |
|
| 95 |
- } |
|
| 96 |
- obj, _, err := readBody(cli.call("GET", "/networks", nil, nil))
|
|
| 97 |
- if err != nil {
|
|
| 98 |
- return err |
|
| 99 |
- } |
|
| 100 |
- if *last == -1 && *nLatest {
|
|
| 101 |
- *last = 1 |
|
| 102 |
- } |
|
| 103 |
- |
|
| 104 |
- var networkResources []networkResource |
|
| 105 |
- err = json.Unmarshal(obj, &networkResources) |
|
| 106 |
- if err != nil {
|
|
| 107 |
- return err |
|
| 108 |
- } |
|
| 109 |
- |
|
| 110 |
- wr := tabwriter.NewWriter(cli.out, 20, 1, 3, ' ', 0) |
|
| 111 |
- |
|
| 112 |
- // unless quiet (-q) is specified, print field titles |
|
| 113 |
- if !*quiet {
|
|
| 114 |
- fmt.Fprintln(wr, "NETWORK ID\tNAME\tTYPE") |
|
| 115 |
- } |
|
| 116 |
- |
|
| 117 |
- for _, networkResource := range networkResources {
|
|
| 118 |
- ID := networkResource.ID |
|
| 119 |
- netName := networkResource.Name |
|
| 120 |
- if !*noTrunc {
|
|
| 121 |
- ID = stringid.TruncateID(ID) |
|
| 122 |
- } |
|
| 123 |
- if *quiet {
|
|
| 124 |
- fmt.Fprintln(wr, ID) |
|
| 125 |
- continue |
|
| 126 |
- } |
|
| 127 |
- netType := networkResource.Type |
|
| 128 |
- fmt.Fprintf(wr, "%s\t%s\t%s\t", |
|
| 129 |
- ID, |
|
| 130 |
- netName, |
|
| 131 |
- netType) |
|
| 132 |
- fmt.Fprint(wr, "\n") |
|
| 133 |
- } |
|
| 134 |
- wr.Flush() |
|
| 135 |
- return nil |
|
| 136 |
-} |
|
| 137 |
- |
|
| 138 |
-// CmdNetworkInfo handles Network Info UI |
|
| 139 |
-func (cli *NetworkCli) CmdNetworkInfo(chain string, args ...string) error {
|
|
| 140 |
- cmd := cli.Subcmd(chain, "info", "NETWORK", "Displays detailed information on a network", false) |
|
| 141 |
- cmd.Require(flag.Exact, 1) |
|
| 142 |
- err := cmd.ParseFlags(args, true) |
|
| 143 |
- if err != nil {
|
|
| 144 |
- return err |
|
| 145 |
- } |
|
| 146 |
- |
|
| 147 |
- id, err := lookupNetworkID(cli, cmd.Arg(0)) |
|
| 148 |
- if err != nil {
|
|
| 149 |
- return err |
|
| 150 |
- } |
|
| 151 |
- |
|
| 152 |
- obj, _, err := readBody(cli.call("GET", "/networks/"+id, nil, nil))
|
|
| 153 |
- if err != nil {
|
|
| 154 |
- return err |
|
| 155 |
- } |
|
| 156 |
- networkResource := &networkResource{}
|
|
| 157 |
- if err := json.NewDecoder(bytes.NewReader(obj)).Decode(networkResource); err != nil {
|
|
| 158 |
- return err |
|
| 159 |
- } |
|
| 160 |
- fmt.Fprintf(cli.out, "Network Id: %s\n", networkResource.ID) |
|
| 161 |
- fmt.Fprintf(cli.out, "Name: %s\n", networkResource.Name) |
|
| 162 |
- fmt.Fprintf(cli.out, "Type: %s\n", networkResource.Type) |
|
| 163 |
- if networkResource.Services != nil {
|
|
| 164 |
- for _, serviceResource := range networkResource.Services {
|
|
| 165 |
- fmt.Fprintf(cli.out, " Service Id: %s\n", serviceResource.ID) |
|
| 166 |
- fmt.Fprintf(cli.out, "\tName: %s\n", serviceResource.Name) |
|
| 167 |
- } |
|
| 168 |
- } |
|
| 169 |
- |
|
| 170 |
- return nil |
|
| 171 |
-} |
|
| 172 |
- |
|
| 173 |
-// Helper function to predict if a string is a name or id or partial-id |
|
| 174 |
-// This provides a best-effort mechanism to identify a id with the help of GET Filter APIs |
|
| 175 |
-// Being a UI, its most likely that name will be used by the user, which is used to lookup |
|
| 176 |
-// the corresponding ID. If ID is not found, this function will assume that the passed string |
|
| 177 |
-// is an ID by itself. |
|
| 178 |
- |
|
| 179 |
-func lookupNetworkID(cli *NetworkCli, nameID string) (string, error) {
|
|
| 180 |
- obj, statusCode, err := readBody(cli.call("GET", "/networks?name="+nameID, nil, nil))
|
|
| 181 |
- if err != nil {
|
|
| 182 |
- return "", err |
|
| 183 |
- } |
|
| 184 |
- |
|
| 185 |
- if statusCode != http.StatusOK {
|
|
| 186 |
- return "", fmt.Errorf("name query failed for %s due to : statuscode(%d) %v", nameID, statusCode, string(obj))
|
|
| 187 |
- } |
|
| 188 |
- |
|
| 189 |
- var list []*networkResource |
|
| 190 |
- err = json.Unmarshal(obj, &list) |
|
| 191 |
- if err != nil {
|
|
| 192 |
- return "", err |
|
| 193 |
- } |
|
| 194 |
- if len(list) > 0 {
|
|
| 195 |
- // name query filter will always return a single-element collection |
|
| 196 |
- return list[0].ID, nil |
|
| 197 |
- } |
|
| 198 |
- |
|
| 199 |
- // Check for Partial-id |
|
| 200 |
- obj, statusCode, err = readBody(cli.call("GET", "/networks?partial-id="+nameID, nil, nil))
|
|
| 201 |
- if err != nil {
|
|
| 202 |
- return "", err |
|
| 203 |
- } |
|
| 204 |
- |
|
| 205 |
- if statusCode != http.StatusOK {
|
|
| 206 |
- return "", fmt.Errorf("partial-id match query failed for %s due to : statuscode(%d) %v", nameID, statusCode, string(obj))
|
|
| 207 |
- } |
|
| 208 |
- |
|
| 209 |
- err = json.Unmarshal(obj, &list) |
|
| 210 |
- if err != nil {
|
|
| 211 |
- return "", err |
|
| 212 |
- } |
|
| 213 |
- if len(list) == 0 {
|
|
| 214 |
- return "", fmt.Errorf("resource not found %s", nameID)
|
|
| 215 |
- } |
|
| 216 |
- if len(list) > 1 {
|
|
| 217 |
- return "", fmt.Errorf("multiple Networks matching the partial identifier (%s). Please use full identifier", nameID)
|
|
| 218 |
- } |
|
| 219 |
- return list[0].ID, nil |
|
| 220 |
-} |
|
| 221 |
- |
|
| 222 |
-func networkUsage(chain string) string {
|
|
| 223 |
- help := "Commands:\n" |
|
| 224 |
- |
|
| 225 |
- for _, cmd := range networkCommands {
|
|
| 226 |
- help += fmt.Sprintf(" %-25.25s%s\n", cmd.name, cmd.description)
|
|
| 227 |
- } |
|
| 228 |
- |
|
| 229 |
- help += fmt.Sprintf("\nRun '%s network COMMAND --help' for more information on a command.", chain)
|
|
| 230 |
- return help |
|
| 231 |
-} |
| 232 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,392 +0,0 @@ |
| 1 |
-package client |
|
| 2 |
- |
|
| 3 |
-import ( |
|
| 4 |
- "bytes" |
|
| 5 |
- "encoding/json" |
|
| 6 |
- "fmt" |
|
| 7 |
- "net/http" |
|
| 8 |
- "strings" |
|
| 9 |
- "text/tabwriter" |
|
| 10 |
- |
|
| 11 |
- flag "github.com/docker/docker/pkg/mflag" |
|
| 12 |
- "github.com/docker/docker/pkg/stringid" |
|
| 13 |
-) |
|
| 14 |
- |
|
| 15 |
-var ( |
|
| 16 |
- serviceCommands = []command{
|
|
| 17 |
- {"publish", "Publish a service"},
|
|
| 18 |
- {"unpublish", "Remove a service"},
|
|
| 19 |
- {"attach", "Attach a backend (container) to the service"},
|
|
| 20 |
- {"detach", "Detach the backend from the service"},
|
|
| 21 |
- {"ls", "Lists all services"},
|
|
| 22 |
- {"info", "Display information about a service"},
|
|
| 23 |
- } |
|
| 24 |
-) |
|
| 25 |
- |
|
| 26 |
-func lookupServiceID(cli *NetworkCli, nwName, svNameID string) (string, error) {
|
|
| 27 |
- // Sanity Check |
|
| 28 |
- obj, _, err := readBody(cli.call("GET", fmt.Sprintf("/networks?name=%s", nwName), nil, nil))
|
|
| 29 |
- if err != nil {
|
|
| 30 |
- return "", err |
|
| 31 |
- } |
|
| 32 |
- var nwList []networkResource |
|
| 33 |
- if err = json.Unmarshal(obj, &nwList); err != nil {
|
|
| 34 |
- return "", err |
|
| 35 |
- } |
|
| 36 |
- if len(nwList) == 0 {
|
|
| 37 |
- return "", fmt.Errorf("Network %s does not exist", nwName)
|
|
| 38 |
- } |
|
| 39 |
- |
|
| 40 |
- if nwName == "" {
|
|
| 41 |
- obj, _, err := readBody(cli.call("GET", "/networks/"+nwList[0].ID, nil, nil))
|
|
| 42 |
- if err != nil {
|
|
| 43 |
- return "", err |
|
| 44 |
- } |
|
| 45 |
- networkResource := &networkResource{}
|
|
| 46 |
- if err := json.NewDecoder(bytes.NewReader(obj)).Decode(networkResource); err != nil {
|
|
| 47 |
- return "", err |
|
| 48 |
- } |
|
| 49 |
- nwName = networkResource.Name |
|
| 50 |
- } |
|
| 51 |
- |
|
| 52 |
- // Query service by name |
|
| 53 |
- obj, statusCode, err := readBody(cli.call("GET", fmt.Sprintf("/services?name=%s", svNameID), nil, nil))
|
|
| 54 |
- if err != nil {
|
|
| 55 |
- return "", err |
|
| 56 |
- } |
|
| 57 |
- |
|
| 58 |
- if statusCode != http.StatusOK {
|
|
| 59 |
- return "", fmt.Errorf("name query failed for %s due to: (%d) %s", svNameID, statusCode, string(obj))
|
|
| 60 |
- } |
|
| 61 |
- |
|
| 62 |
- var list []*serviceResource |
|
| 63 |
- if err = json.Unmarshal(obj, &list); err != nil {
|
|
| 64 |
- return "", err |
|
| 65 |
- } |
|
| 66 |
- for _, sr := range list {
|
|
| 67 |
- if sr.Network == nwName {
|
|
| 68 |
- return sr.ID, nil |
|
| 69 |
- } |
|
| 70 |
- } |
|
| 71 |
- |
|
| 72 |
- // Query service by Partial-id (this covers full id as well) |
|
| 73 |
- obj, statusCode, err = readBody(cli.call("GET", fmt.Sprintf("/services?partial-id=%s", svNameID), nil, nil))
|
|
| 74 |
- if err != nil {
|
|
| 75 |
- return "", err |
|
| 76 |
- } |
|
| 77 |
- |
|
| 78 |
- if statusCode != http.StatusOK {
|
|
| 79 |
- return "", fmt.Errorf("partial-id match query failed for %s due to: (%d) %s", svNameID, statusCode, string(obj))
|
|
| 80 |
- } |
|
| 81 |
- |
|
| 82 |
- if err = json.Unmarshal(obj, &list); err != nil {
|
|
| 83 |
- return "", err |
|
| 84 |
- } |
|
| 85 |
- for _, sr := range list {
|
|
| 86 |
- if sr.Network == nwName {
|
|
| 87 |
- return sr.ID, nil |
|
| 88 |
- } |
|
| 89 |
- } |
|
| 90 |
- |
|
| 91 |
- return "", fmt.Errorf("Service %s not found on network %s", svNameID, nwName)
|
|
| 92 |
-} |
|
| 93 |
- |
|
| 94 |
-func lookupContainerID(cli *NetworkCli, cnNameID string) (string, error) {
|
|
| 95 |
- // Container is a Docker resource, ask docker about it. |
|
| 96 |
- // In case of connecton error, we assume we are running in dnet and return whatever was passed to us |
|
| 97 |
- obj, _, err := readBody(cli.call("GET", fmt.Sprintf("/containers/%s/json", cnNameID), nil, nil))
|
|
| 98 |
- if err != nil {
|
|
| 99 |
- // We are probably running outside of docker |
|
| 100 |
- return cnNameID, nil |
|
| 101 |
- } |
|
| 102 |
- |
|
| 103 |
- var x map[string]interface{}
|
|
| 104 |
- err = json.Unmarshal(obj, &x) |
|
| 105 |
- if err != nil {
|
|
| 106 |
- return "", err |
|
| 107 |
- } |
|
| 108 |
- if iid, ok := x["Id"]; ok {
|
|
| 109 |
- if id, ok := iid.(string); ok {
|
|
| 110 |
- return id, nil |
|
| 111 |
- } |
|
| 112 |
- return "", fmt.Errorf("Unexpected data type for container ID in json response")
|
|
| 113 |
- } |
|
| 114 |
- return "", fmt.Errorf("Cannot find container ID in json response")
|
|
| 115 |
-} |
|
| 116 |
- |
|
| 117 |
-func lookupSandboxID(cli *NetworkCli, containerID string) (string, error) {
|
|
| 118 |
- obj, _, err := readBody(cli.call("GET", fmt.Sprintf("/sandboxes?partial-container-id=%s", containerID), nil, nil))
|
|
| 119 |
- if err != nil {
|
|
| 120 |
- return "", err |
|
| 121 |
- } |
|
| 122 |
- |
|
| 123 |
- var sandboxList []SandboxResource |
|
| 124 |
- err = json.Unmarshal(obj, &sandboxList) |
|
| 125 |
- if err != nil {
|
|
| 126 |
- return "", err |
|
| 127 |
- } |
|
| 128 |
- |
|
| 129 |
- if len(sandboxList) == 0 {
|
|
| 130 |
- return "", fmt.Errorf("cannot find sandbox for container: %s", containerID)
|
|
| 131 |
- } |
|
| 132 |
- |
|
| 133 |
- return sandboxList[0].ID, nil |
|
| 134 |
-} |
|
| 135 |
- |
|
| 136 |
-// CmdService handles the service UI |
|
| 137 |
-func (cli *NetworkCli) CmdService(chain string, args ...string) error {
|
|
| 138 |
- cmd := cli.Subcmd(chain, "service", "COMMAND [OPTIONS] [arg...]", serviceUsage(chain), false) |
|
| 139 |
- cmd.Require(flag.Min, 1) |
|
| 140 |
- err := cmd.ParseFlags(args, true) |
|
| 141 |
- if err == nil {
|
|
| 142 |
- cmd.Usage() |
|
| 143 |
- return fmt.Errorf("Invalid command : %v", args)
|
|
| 144 |
- } |
|
| 145 |
- return err |
|
| 146 |
-} |
|
| 147 |
- |
|
| 148 |
-// Parse service name for "SERVICE[.NETWORK]" format |
|
| 149 |
-func parseServiceName(name string) (string, string) {
|
|
| 150 |
- s := strings.Split(name, ".") |
|
| 151 |
- var sName, nName string |
|
| 152 |
- if len(s) > 1 {
|
|
| 153 |
- nName = s[len(s)-1] |
|
| 154 |
- sName = strings.Join(s[:len(s)-1], ".") |
|
| 155 |
- } else {
|
|
| 156 |
- sName = s[0] |
|
| 157 |
- } |
|
| 158 |
- return sName, nName |
|
| 159 |
-} |
|
| 160 |
- |
|
| 161 |
-// CmdServicePublish handles service create UI |
|
| 162 |
-func (cli *NetworkCli) CmdServicePublish(chain string, args ...string) error {
|
|
| 163 |
- cmd := cli.Subcmd(chain, "publish", "SERVICE[.NETWORK]", "Publish a new service on a network", false) |
|
| 164 |
- cmd.Require(flag.Exact, 1) |
|
| 165 |
- err := cmd.ParseFlags(args, true) |
|
| 166 |
- if err != nil {
|
|
| 167 |
- return err |
|
| 168 |
- } |
|
| 169 |
- |
|
| 170 |
- sn, nn := parseServiceName(cmd.Arg(0)) |
|
| 171 |
- sc := serviceCreate{Name: sn, Network: nn}
|
|
| 172 |
- obj, _, err := readBody(cli.call("POST", "/services", sc, nil))
|
|
| 173 |
- if err != nil {
|
|
| 174 |
- return err |
|
| 175 |
- } |
|
| 176 |
- |
|
| 177 |
- var replyID string |
|
| 178 |
- err = json.Unmarshal(obj, &replyID) |
|
| 179 |
- if err != nil {
|
|
| 180 |
- return err |
|
| 181 |
- } |
|
| 182 |
- |
|
| 183 |
- fmt.Fprintf(cli.out, "%s\n", replyID) |
|
| 184 |
- return nil |
|
| 185 |
-} |
|
| 186 |
- |
|
| 187 |
-// CmdServiceUnpublish handles service delete UI |
|
| 188 |
-func (cli *NetworkCli) CmdServiceUnpublish(chain string, args ...string) error {
|
|
| 189 |
- cmd := cli.Subcmd(chain, "unpublish", "SERVICE[.NETWORK]", "Removes a service", false) |
|
| 190 |
- cmd.Require(flag.Exact, 1) |
|
| 191 |
- err := cmd.ParseFlags(args, true) |
|
| 192 |
- if err != nil {
|
|
| 193 |
- return err |
|
| 194 |
- } |
|
| 195 |
- |
|
| 196 |
- sn, nn := parseServiceName(cmd.Arg(0)) |
|
| 197 |
- serviceID, err := lookupServiceID(cli, nn, sn) |
|
| 198 |
- if err != nil {
|
|
| 199 |
- return err |
|
| 200 |
- } |
|
| 201 |
- |
|
| 202 |
- _, _, err = readBody(cli.call("DELETE", "/services/"+serviceID, nil, nil))
|
|
| 203 |
- |
|
| 204 |
- return err |
|
| 205 |
-} |
|
| 206 |
- |
|
| 207 |
-// CmdServiceLs handles service list UI |
|
| 208 |
-func (cli *NetworkCli) CmdServiceLs(chain string, args ...string) error {
|
|
| 209 |
- cmd := cli.Subcmd(chain, "ls", "SERVICE", "Lists all the services on a network", false) |
|
| 210 |
- flNetwork := cmd.String([]string{"net", "-network"}, "", "Only show the services that are published on the specified network")
|
|
| 211 |
- quiet := cmd.Bool([]string{"q", "-quiet"}, false, "Only display numeric IDs")
|
|
| 212 |
- noTrunc := cmd.Bool([]string{"#notrunc", "-no-trunc"}, false, "Do not truncate the output")
|
|
| 213 |
- |
|
| 214 |
- err := cmd.ParseFlags(args, true) |
|
| 215 |
- if err != nil {
|
|
| 216 |
- return err |
|
| 217 |
- } |
|
| 218 |
- |
|
| 219 |
- var obj []byte |
|
| 220 |
- if *flNetwork == "" {
|
|
| 221 |
- obj, _, err = readBody(cli.call("GET", "/services", nil, nil))
|
|
| 222 |
- } else {
|
|
| 223 |
- obj, _, err = readBody(cli.call("GET", "/services?network="+*flNetwork, nil, nil))
|
|
| 224 |
- } |
|
| 225 |
- if err != nil {
|
|
| 226 |
- return err |
|
| 227 |
- } |
|
| 228 |
- |
|
| 229 |
- var serviceResources []serviceResource |
|
| 230 |
- err = json.Unmarshal(obj, &serviceResources) |
|
| 231 |
- if err != nil {
|
|
| 232 |
- fmt.Println(err) |
|
| 233 |
- return err |
|
| 234 |
- } |
|
| 235 |
- |
|
| 236 |
- wr := tabwriter.NewWriter(cli.out, 20, 1, 3, ' ', 0) |
|
| 237 |
- // unless quiet (-q) is specified, print field titles |
|
| 238 |
- if !*quiet {
|
|
| 239 |
- fmt.Fprintln(wr, "SERVICE ID\tNAME\tNETWORK\tCONTAINER\tSANDBOX") |
|
| 240 |
- } |
|
| 241 |
- |
|
| 242 |
- for _, sr := range serviceResources {
|
|
| 243 |
- ID := sr.ID |
|
| 244 |
- bkID, sbID, err := getBackendID(cli, ID) |
|
| 245 |
- if err != nil {
|
|
| 246 |
- return err |
|
| 247 |
- } |
|
| 248 |
- if !*noTrunc {
|
|
| 249 |
- ID = stringid.TruncateID(ID) |
|
| 250 |
- bkID = stringid.TruncateID(bkID) |
|
| 251 |
- sbID = stringid.TruncateID(sbID) |
|
| 252 |
- } |
|
| 253 |
- if !*quiet {
|
|
| 254 |
- fmt.Fprintf(wr, "%s\t%s\t%s\t%s\t%s\n", ID, sr.Name, sr.Network, bkID, sbID) |
|
| 255 |
- } else {
|
|
| 256 |
- fmt.Fprintln(wr, ID) |
|
| 257 |
- } |
|
| 258 |
- } |
|
| 259 |
- wr.Flush() |
|
| 260 |
- |
|
| 261 |
- return nil |
|
| 262 |
-} |
|
| 263 |
- |
|
| 264 |
-func getBackendID(cli *NetworkCli, servID string) (string, string, error) {
|
|
| 265 |
- var ( |
|
| 266 |
- obj []byte |
|
| 267 |
- err error |
|
| 268 |
- bk string |
|
| 269 |
- sb string |
|
| 270 |
- ) |
|
| 271 |
- |
|
| 272 |
- if obj, _, err = readBody(cli.call("GET", "/services/"+servID+"/backend", nil, nil)); err == nil {
|
|
| 273 |
- var sr SandboxResource |
|
| 274 |
- if err := json.NewDecoder(bytes.NewReader(obj)).Decode(&sr); err == nil {
|
|
| 275 |
- bk = sr.ContainerID |
|
| 276 |
- sb = sr.ID |
|
| 277 |
- } else {
|
|
| 278 |
- // Only print a message, don't make the caller cli fail for this |
|
| 279 |
- fmt.Fprintf(cli.out, "Failed to retrieve backend list for service %s (%v)\n", servID, err) |
|
| 280 |
- } |
|
| 281 |
- } |
|
| 282 |
- |
|
| 283 |
- return bk, sb, err |
|
| 284 |
-} |
|
| 285 |
- |
|
| 286 |
-// CmdServiceInfo handles service info UI |
|
| 287 |
-func (cli *NetworkCli) CmdServiceInfo(chain string, args ...string) error {
|
|
| 288 |
- cmd := cli.Subcmd(chain, "info", "SERVICE[.NETWORK]", "Displays detailed information about a service", false) |
|
| 289 |
- cmd.Require(flag.Min, 1) |
|
| 290 |
- |
|
| 291 |
- err := cmd.ParseFlags(args, true) |
|
| 292 |
- if err != nil {
|
|
| 293 |
- return err |
|
| 294 |
- } |
|
| 295 |
- |
|
| 296 |
- sn, nn := parseServiceName(cmd.Arg(0)) |
|
| 297 |
- serviceID, err := lookupServiceID(cli, nn, sn) |
|
| 298 |
- if err != nil {
|
|
| 299 |
- return err |
|
| 300 |
- } |
|
| 301 |
- |
|
| 302 |
- obj, _, err := readBody(cli.call("GET", "/services/"+serviceID, nil, nil))
|
|
| 303 |
- if err != nil {
|
|
| 304 |
- return err |
|
| 305 |
- } |
|
| 306 |
- |
|
| 307 |
- sr := &serviceResource{}
|
|
| 308 |
- if err := json.NewDecoder(bytes.NewReader(obj)).Decode(sr); err != nil {
|
|
| 309 |
- return err |
|
| 310 |
- } |
|
| 311 |
- |
|
| 312 |
- fmt.Fprintf(cli.out, "Service Id: %s\n", sr.ID) |
|
| 313 |
- fmt.Fprintf(cli.out, "\tName: %s\n", sr.Name) |
|
| 314 |
- fmt.Fprintf(cli.out, "\tNetwork: %s\n", sr.Network) |
|
| 315 |
- |
|
| 316 |
- return nil |
|
| 317 |
-} |
|
| 318 |
- |
|
| 319 |
-// CmdServiceAttach handles service attach UI |
|
| 320 |
-func (cli *NetworkCli) CmdServiceAttach(chain string, args ...string) error {
|
|
| 321 |
- cmd := cli.Subcmd(chain, "attach", "CONTAINER SERVICE[.NETWORK]", "Sets a container as a service backend", false) |
|
| 322 |
- cmd.Require(flag.Min, 2) |
|
| 323 |
- err := cmd.ParseFlags(args, true) |
|
| 324 |
- if err != nil {
|
|
| 325 |
- return err |
|
| 326 |
- } |
|
| 327 |
- |
|
| 328 |
- containerID, err := lookupContainerID(cli, cmd.Arg(0)) |
|
| 329 |
- if err != nil {
|
|
| 330 |
- return err |
|
| 331 |
- } |
|
| 332 |
- |
|
| 333 |
- sandboxID, err := lookupSandboxID(cli, containerID) |
|
| 334 |
- if err != nil {
|
|
| 335 |
- return err |
|
| 336 |
- } |
|
| 337 |
- |
|
| 338 |
- sn, nn := parseServiceName(cmd.Arg(1)) |
|
| 339 |
- serviceID, err := lookupServiceID(cli, nn, sn) |
|
| 340 |
- if err != nil {
|
|
| 341 |
- return err |
|
| 342 |
- } |
|
| 343 |
- |
|
| 344 |
- nc := serviceAttach{SandboxID: sandboxID}
|
|
| 345 |
- |
|
| 346 |
- _, _, err = readBody(cli.call("POST", "/services/"+serviceID+"/backend", nc, nil))
|
|
| 347 |
- |
|
| 348 |
- return err |
|
| 349 |
-} |
|
| 350 |
- |
|
| 351 |
-// CmdServiceDetach handles service detach UI |
|
| 352 |
-func (cli *NetworkCli) CmdServiceDetach(chain string, args ...string) error {
|
|
| 353 |
- cmd := cli.Subcmd(chain, "detach", "CONTAINER SERVICE", "Removes a container from service backend", false) |
|
| 354 |
- cmd.Require(flag.Min, 2) |
|
| 355 |
- err := cmd.ParseFlags(args, true) |
|
| 356 |
- if err != nil {
|
|
| 357 |
- return err |
|
| 358 |
- } |
|
| 359 |
- |
|
| 360 |
- sn, nn := parseServiceName(cmd.Arg(1)) |
|
| 361 |
- containerID, err := lookupContainerID(cli, cmd.Arg(0)) |
|
| 362 |
- if err != nil {
|
|
| 363 |
- return err |
|
| 364 |
- } |
|
| 365 |
- |
|
| 366 |
- sandboxID, err := lookupSandboxID(cli, containerID) |
|
| 367 |
- if err != nil {
|
|
| 368 |
- return err |
|
| 369 |
- } |
|
| 370 |
- |
|
| 371 |
- serviceID, err := lookupServiceID(cli, nn, sn) |
|
| 372 |
- if err != nil {
|
|
| 373 |
- return err |
|
| 374 |
- } |
|
| 375 |
- |
|
| 376 |
- _, _, err = readBody(cli.call("DELETE", "/services/"+serviceID+"/backend/"+sandboxID, nil, nil))
|
|
| 377 |
- if err != nil {
|
|
| 378 |
- return err |
|
| 379 |
- } |
|
| 380 |
- return nil |
|
| 381 |
-} |
|
| 382 |
- |
|
| 383 |
-func serviceUsage(chain string) string {
|
|
| 384 |
- help := "Commands:\n" |
|
| 385 |
- |
|
| 386 |
- for _, cmd := range serviceCommands {
|
|
| 387 |
- help += fmt.Sprintf(" %-10.10s%s\n", cmd.name, cmd.description)
|
|
| 388 |
- } |
|
| 389 |
- |
|
| 390 |
- help += fmt.Sprintf("\nRun '%s service COMMAND --help' for more information on a command.", chain)
|
|
| 391 |
- return help |
|
| 392 |
-} |
| 393 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,79 +0,0 @@ |
| 1 |
-package client |
|
| 2 |
- |
|
| 3 |
-import "github.com/docker/libnetwork/types" |
|
| 4 |
- |
|
| 5 |
-/*********** |
|
| 6 |
- Resources |
|
| 7 |
-************/ |
|
| 8 |
- |
|
| 9 |
-// networkResource is the body of the "get network" http response message |
|
| 10 |
-type networkResource struct {
|
|
| 11 |
- Name string `json:"name"` |
|
| 12 |
- ID string `json:"id"` |
|
| 13 |
- Type string `json:"type"` |
|
| 14 |
- Services []*serviceResource `json:"services"` |
|
| 15 |
-} |
|
| 16 |
- |
|
| 17 |
-// serviceResource is the body of the "get service" http response message |
|
| 18 |
-type serviceResource struct {
|
|
| 19 |
- Name string `json:"name"` |
|
| 20 |
- ID string `json:"id"` |
|
| 21 |
- Network string `json:"network"` |
|
| 22 |
-} |
|
| 23 |
- |
|
| 24 |
-// SandboxResource is the body of "get service backend" response message |
|
| 25 |
-type SandboxResource struct {
|
|
| 26 |
- ID string `json:"id"` |
|
| 27 |
- Key string `json:"key"` |
|
| 28 |
- ContainerID string `json:"container_id"` |
|
| 29 |
-} |
|
| 30 |
- |
|
| 31 |
-/*********** |
|
| 32 |
- Body types |
|
| 33 |
- ************/ |
|
| 34 |
- |
|
| 35 |
-// networkCreate is the expected body of the "create network" http request message |
|
| 36 |
-type networkCreate struct {
|
|
| 37 |
- Name string `json:"name"` |
|
| 38 |
- NetworkType string `json:"network_type"` |
|
| 39 |
- Options map[string]interface{} `json:"options"`
|
|
| 40 |
-} |
|
| 41 |
- |
|
| 42 |
-// serviceCreate represents the body of the "publish service" http request message |
|
| 43 |
-type serviceCreate struct {
|
|
| 44 |
- Name string `json:"name"` |
|
| 45 |
- Network string `json:"network_name"` |
|
| 46 |
- ExposedPorts []types.TransportPort `json:"exposed_ports"` |
|
| 47 |
- PortMapping []types.PortBinding `json:"port_mapping"` |
|
| 48 |
-} |
|
| 49 |
- |
|
| 50 |
-// serviceAttach represents the expected body of the "attach/detach sandbox to/from service" http request messages |
|
| 51 |
-type serviceAttach struct {
|
|
| 52 |
- SandboxID string `json:"sandbox_id"` |
|
| 53 |
-} |
|
| 54 |
- |
|
| 55 |
-// SandboxCreate is the body of the "post /sandboxes" http request message |
|
| 56 |
-type SandboxCreate struct {
|
|
| 57 |
- ContainerID string `json:"container_id"` |
|
| 58 |
- HostName string `json:"host_name"` |
|
| 59 |
- DomainName string `json:"domain_name"` |
|
| 60 |
- HostsPath string `json:"hosts_path"` |
|
| 61 |
- ResolvConfPath string `json:"resolv_conf_path"` |
|
| 62 |
- DNS []string `json:"dns"` |
|
| 63 |
- ExtraHosts []extraHost `json:"extra_hosts"` |
|
| 64 |
- UseDefaultSandbox bool `json:"use_default_sandbox"` |
|
| 65 |
-} |
|
| 66 |
- |
|
| 67 |
-// extraHost represents the extra host object |
|
| 68 |
-type extraHost struct {
|
|
| 69 |
- Name string `json:"name"` |
|
| 70 |
- Address string `json:"address"` |
|
| 71 |
-} |
|
| 72 |
- |
|
| 73 |
-// sandboxParentUpdate is the object carrying the information about the |
|
| 74 |
-// sanbox parent that needs to be updated |
|
| 75 |
-type sandboxParentUpdate struct {
|
|
| 76 |
- ContainerID string `json:"container_id"` |
|
| 77 |
- Name string `json:"name"` |
|
| 78 |
- Address string `json:"address"` |
|
| 79 |
-} |