From a0cccbbcfab79c49f6583429d6d64a7b06f35d34 Mon Sep 17 00:00:00 2001 From: Madhu Venugopal Date: Mon, 8 Jun 2015 04:17:24 -0700 Subject: [PATCH] Moved services to dnet top-level and removed experimental In prep for the UI/API updates on Docker to integrate the network and endpoints, this PR removes the experimental tag from dnet and moving it to docker UI and API and wrap the top-level "network" and "service" under experimental. Signed-off-by: Madhu Venugopal --- libnetwork/Makefile | 2 +- ...imental_test.go => client_service_test.go} | 18 +- libnetwork/client/network.go | 4 - libnetwork/client/service.go | 316 ++++++++++++++++- libnetwork/client/service_experimental.go | 317 ------------------ libnetwork/cmd/dnet/flags.go | 3 +- 6 files changed, 323 insertions(+), 337 deletions(-) rename libnetwork/client/{client_experimental_test.go => client_service_test.go} (79%) delete mode 100644 libnetwork/client/service_experimental.go diff --git a/libnetwork/Makefile b/libnetwork/Makefile index 9deb2653f7..f5b1169c00 100644 --- a/libnetwork/Makefile +++ b/libnetwork/Makefile @@ -22,7 +22,7 @@ build: ${build_image}.created ${docker} make build-local build-local: - $(shell which godep) go build -tags experimental,libnetwork_discovery ./... + $(shell which godep) go build -tags libnetwork_discovery ./... check: ${build_image}.created ${docker} make check-local diff --git a/libnetwork/client/client_experimental_test.go b/libnetwork/client/client_service_test.go similarity index 79% rename from libnetwork/client/client_experimental_test.go rename to libnetwork/client/client_service_test.go index 9592b3ca77..8ef8a45105 100644 --- a/libnetwork/client/client_experimental_test.go +++ b/libnetwork/client/client_service_test.go @@ -1,5 +1,3 @@ -// +build experimental - package client import ( @@ -13,7 +11,7 @@ func TestClientNetworkServiceInvalidCommand(t *testing.T) { var out, errOut bytes.Buffer cli := NewNetworkCli(&out, &errOut, callbackFunc) - err := cli.Cmd("docker", "network", "service", "invalid") + err := cli.Cmd("docker", "service", "invalid") if err == nil { t.Fatalf("Passing invalid commands must fail") } @@ -23,7 +21,7 @@ func TestClientNetworkServiceCreate(t *testing.T) { var out, errOut bytes.Buffer cli := NewNetworkCli(&out, &errOut, callbackFunc) - err := cli.Cmd("docker", "network", "service", "create", mockServiceName, mockNwName) + err := cli.Cmd("docker", "service", "create", mockServiceName, mockNwName) if err != nil { t.Fatal(err.Error()) } @@ -33,7 +31,7 @@ func TestClientNetworkServiceRm(t *testing.T) { var out, errOut bytes.Buffer cli := NewNetworkCli(&out, &errOut, callbackFunc) - err := cli.Cmd("docker", "network", "service", "rm", mockServiceName, mockNwName) + err := cli.Cmd("docker", "service", "rm", mockServiceName, mockNwName) if err != nil { t.Fatal(err.Error()) } @@ -43,7 +41,7 @@ func TestClientNetworkServiceLs(t *testing.T) { var out, errOut bytes.Buffer cli := NewNetworkCli(&out, &errOut, callbackFunc) - err := cli.Cmd("docker", "network", "service", "ls", mockNwName) + err := cli.Cmd("docker", "service", "ls", mockNwName) if err != nil { t.Fatal(err.Error()) } @@ -53,7 +51,7 @@ func TestClientNetworkServiceInfo(t *testing.T) { var out, errOut bytes.Buffer cli := NewNetworkCli(&out, &errOut, callbackFunc) - err := cli.Cmd("docker", "network", "service", "info", mockServiceName, mockNwName) + err := cli.Cmd("docker", "service", "info", mockServiceName, mockNwName) if err != nil { t.Fatal(err.Error()) } @@ -63,7 +61,7 @@ func TestClientNetworkServiceInfoById(t *testing.T) { var out, errOut bytes.Buffer cli := NewNetworkCli(&out, &errOut, callbackFunc) - err := cli.Cmd("docker", "network", "service", "info", mockServiceID, mockNwID) + err := cli.Cmd("docker", "service", "info", mockServiceID, mockNwID) if err != nil { t.Fatal(err.Error()) } @@ -73,7 +71,7 @@ func TestClientNetworkServiceJoin(t *testing.T) { var out, errOut bytes.Buffer cli := NewNetworkCli(&out, &errOut, callbackFunc) - err := cli.Cmd("docker", "network", "service", "join", mockContainerID, mockServiceName, mockNwName) + err := cli.Cmd("docker", "service", "join", mockContainerID, mockServiceName, mockNwName) if err != nil { t.Fatal(err.Error()) } @@ -83,7 +81,7 @@ func TestClientNetworkServiceLeave(t *testing.T) { var out, errOut bytes.Buffer cli := NewNetworkCli(&out, &errOut, callbackFunc) - err := cli.Cmd("docker", "network", "service", "leave", mockContainerID, mockServiceName, mockNwName) + err := cli.Cmd("docker", "service", "leave", mockContainerID, mockServiceName, mockNwName) if err != nil { t.Fatal(err.Error()) } diff --git a/libnetwork/client/network.go b/libnetwork/client/network.go index c02427b7cb..0b5b3e70cd 100644 --- a/libnetwork/client/network.go +++ b/libnetwork/client/network.go @@ -243,10 +243,6 @@ func networkUsage(chain string) string { help += fmt.Sprintf(" %-25.25s%s\n", cmd.name, cmd.description) } - for _, cmd := range serviceCommands { - help += fmt.Sprintf(" %-25.25s%s\n", "service "+cmd.name, cmd.description) - } - help += fmt.Sprintf("\nRun '%s network COMMAND --help' for more information on a command.", chain) return help } diff --git a/libnetwork/client/service.go b/libnetwork/client/service.go index afdbb7f84b..db07c9c4cd 100644 --- a/libnetwork/client/service.go +++ b/libnetwork/client/service.go @@ -1,7 +1,315 @@ -// +build !experimental - package client -var ( - serviceCommands = []command{} +import ( + "bytes" + "encoding/json" + "fmt" + "net/http" + "text/tabwriter" + + flag "github.com/docker/docker/pkg/mflag" + "github.com/docker/docker/pkg/stringid" ) + +var ( + serviceCommands = []command{ + {"create", "Create a service endpoint"}, + {"rm", "Remove a service endpoint"}, + {"join", "Join a container to a service endpoint"}, + {"leave", "Leave a container from a service endpoint"}, + {"ls", "Lists all service endpoints on a network"}, + {"info", "Display information of a service endpoint"}, + } +) + +func lookupServiceID(cli *NetworkCli, networkID string, nameID string) (string, error) { + obj, statusCode, err := readBody(cli.call("GET", fmt.Sprintf("/networks/%s/endpoints?name=%s", networkID, nameID), nil, nil)) + if err != nil { + return "", err + } + + if statusCode != http.StatusOK { + return "", fmt.Errorf("name query failed for %s due to : statuscode(%d) %v", nameID, statusCode, string(obj)) + } + + var list []*networkResource + err = json.Unmarshal(obj, &list) + if err != nil { + return "", err + } + if len(list) > 0 { + // name query filter will always return a single-element collection + return list[0].ID, nil + } + + // Check for Partial-id + obj, statusCode, err = readBody(cli.call("GET", fmt.Sprintf("/networks/%s/endpoints?partial-id=%s", networkID, nameID), nil, nil)) + if err != nil { + return "", err + } + + if statusCode != http.StatusOK { + return "", fmt.Errorf("partial-id match query failed for %s due to : statuscode(%d) %v", nameID, statusCode, string(obj)) + } + + err = json.Unmarshal(obj, &list) + if err != nil { + return "", err + } + if len(list) == 0 { + return "", fmt.Errorf("resource not found %s", nameID) + } + if len(list) > 1 { + return "", fmt.Errorf("multiple services matching the partial identifier (%s). Please use full identifier", nameID) + } + return list[0].ID, nil +} + +func lookupContainerID(cli *NetworkCli, nameID string) (string, error) { + // TODO : containerID to sandbox-key ? + return nameID, nil +} + +// CmdService handles the network service UI +func (cli *NetworkCli) CmdService(chain string, args ...string) error { + cmd := cli.Subcmd(chain, "service", "COMMAND [OPTIONS] [arg...]", serviceUsage(chain), false) + cmd.Require(flag.Min, 1) + err := cmd.ParseFlags(args, true) + if err == nil { + cmd.Usage() + return fmt.Errorf("Invalid command : %v", args) + } + return err +} + +// CmdServiceCreate handles service create UI +func (cli *NetworkCli) CmdServiceCreate(chain string, args ...string) error { + cmd := cli.Subcmd(chain, "create", "SERVICE NETWORK", "Creates a new service on a network", false) + cmd.Require(flag.Min, 2) + err := cmd.ParseFlags(args, true) + if err != nil { + return err + } + + networkID, err := lookupNetworkID(cli, cmd.Arg(1)) + if err != nil { + return err + } + + ec := endpointCreate{Name: cmd.Arg(0), NetworkID: networkID} + + obj, _, err := readBody(cli.call("POST", "/networks/"+networkID+"/endpoints", ec, nil)) + if err != nil { + return err + } + + var replyID string + err = json.Unmarshal(obj, &replyID) + if err != nil { + return err + } + + fmt.Fprintf(cli.out, "%s\n", replyID) + return nil +} + +// CmdServiceRm handles service delete UI +func (cli *NetworkCli) CmdServiceRm(chain string, args ...string) error { + cmd := cli.Subcmd(chain, "rm", "SERVICE NETWORK", "Deletes a service", false) + cmd.Require(flag.Min, 2) + err := cmd.ParseFlags(args, true) + if err != nil { + return err + } + + networkID, err := lookupNetworkID(cli, cmd.Arg(1)) + if err != nil { + return err + } + + serviceID, err := lookupServiceID(cli, networkID, cmd.Arg(0)) + if err != nil { + return err + } + + _, _, err = readBody(cli.call("DELETE", "/networks/"+networkID+"/endpoints/"+serviceID, nil, nil)) + if err != nil { + return err + } + return nil +} + +// CmdServiceLs handles service list UI +func (cli *NetworkCli) CmdServiceLs(chain string, args ...string) error { + cmd := cli.Subcmd(chain, "ls", "NETWORK", "Lists all the services on a network", false) + quiet := cmd.Bool([]string{"q", "-quiet"}, false, "Only display numeric IDs") + noTrunc := cmd.Bool([]string{"#notrunc", "-no-trunc"}, false, "Do not truncate the output") + nLatest := cmd.Bool([]string{"l", "-latest"}, false, "Show the latest network created") + last := cmd.Int([]string{"n"}, -1, "Show n last created networks") + err := cmd.ParseFlags(args, true) + if err != nil { + return err + } + + cmd.Require(flag.Min, 1) + + networkID, err := lookupNetworkID(cli, cmd.Arg(0)) + if err != nil { + return err + } + + obj, _, err := readBody(cli.call("GET", "/networks/"+networkID+"/endpoints", nil, nil)) + if err != nil { + fmt.Fprintf(cli.err, "%s", err.Error()) + return err + } + if *last == -1 && *nLatest { + *last = 1 + } + + var endpointResources []endpointResource + err = json.Unmarshal(obj, &endpointResources) + if err != nil { + return err + } + + wr := tabwriter.NewWriter(cli.out, 20, 1, 3, ' ', 0) + // unless quiet (-q) is specified, print field titles + if !*quiet { + fmt.Fprintln(wr, "NETWORK SERVICE ID\tNAME\tNETWORK") + } + + for _, networkResource := range endpointResources { + ID := networkResource.ID + netName := networkResource.Name + if !*noTrunc { + ID = stringid.TruncateID(ID) + } + if *quiet { + fmt.Fprintln(wr, ID) + continue + } + network := networkResource.Network + fmt.Fprintf(wr, "%s\t%s\t%s", + ID, + netName, + network) + fmt.Fprint(wr, "\n") + } + wr.Flush() + + return nil +} + +// CmdServiceInfo handles service info UI +func (cli *NetworkCli) CmdServiceInfo(chain string, args ...string) error { + cmd := cli.Subcmd(chain, "info", "SERVICE NETWORK", "Displays detailed information on a service", false) + cmd.Require(flag.Min, 2) + err := cmd.ParseFlags(args, true) + if err != nil { + return err + } + + networkID, err := lookupNetworkID(cli, cmd.Arg(1)) + if err != nil { + return err + } + + serviceID, err := lookupServiceID(cli, networkID, cmd.Arg(0)) + if err != nil { + return err + } + + obj, _, err := readBody(cli.call("GET", "/networks/"+networkID+"/endpoints/"+serviceID, nil, nil)) + if err != nil { + fmt.Fprintf(cli.err, "%s", err.Error()) + return err + } + + endpointResource := &endpointResource{} + if err := json.NewDecoder(bytes.NewReader(obj)).Decode(endpointResource); err != nil { + return err + } + fmt.Fprintf(cli.out, "Service Id: %s\n", endpointResource.ID) + fmt.Fprintf(cli.out, "\tName: %s\n", endpointResource.Name) + fmt.Fprintf(cli.out, "\tNetwork: %s\n", endpointResource.Network) + + return nil +} + +// CmdServiceJoin handles service join UI +func (cli *NetworkCli) CmdServiceJoin(chain string, args ...string) error { + cmd := cli.Subcmd(chain, "join", "CONTAINER SERVICE NETWORK", "Sets a container as a service backend", false) + cmd.Require(flag.Min, 3) + err := cmd.ParseFlags(args, true) + if err != nil { + return err + } + + containerID, err := lookupContainerID(cli, cmd.Arg(0)) + if err != nil { + return err + } + + networkID, err := lookupNetworkID(cli, cmd.Arg(2)) + if err != nil { + return err + } + + serviceID, err := lookupServiceID(cli, networkID, cmd.Arg(1)) + if err != nil { + return err + } + + nc := endpointJoin{ContainerID: containerID} + + _, _, err = readBody(cli.call("POST", "/networks/"+networkID+"/endpoints/"+serviceID+"/containers", nc, nil)) + if err != nil { + fmt.Fprintf(cli.err, "%s", err.Error()) + return err + } + return nil +} + +// CmdServiceLeave handles service leave UI +func (cli *NetworkCli) CmdServiceLeave(chain string, args ...string) error { + cmd := cli.Subcmd(chain, "leave", "CONTAINER SERVICE NETWORK", "Removes a container from service backend", false) + cmd.Require(flag.Min, 3) + err := cmd.ParseFlags(args, true) + if err != nil { + return err + } + + containerID, err := lookupContainerID(cli, cmd.Arg(0)) + if err != nil { + return err + } + + networkID, err := lookupNetworkID(cli, cmd.Arg(2)) + if err != nil { + return err + } + + serviceID, err := lookupServiceID(cli, networkID, cmd.Arg(1)) + if err != nil { + return err + } + + _, _, err = readBody(cli.call("DELETE", "/networks/"+networkID+"/endpoints/"+serviceID+"/containers/"+containerID, nil, nil)) + if err != nil { + fmt.Fprintf(cli.err, "%s", err.Error()) + return err + } + return nil +} + +func serviceUsage(chain string) string { + help := "Commands:\n" + + for _, cmd := range serviceCommands { + help += fmt.Sprintf(" %-10.10s%s\n", cmd.name, cmd.description) + } + + help += fmt.Sprintf("\nRun '%s service COMMAND --help' for more information on a command.", chain) + return help +} diff --git a/libnetwork/client/service_experimental.go b/libnetwork/client/service_experimental.go deleted file mode 100644 index 5965d136f1..0000000000 --- a/libnetwork/client/service_experimental.go +++ /dev/null @@ -1,317 +0,0 @@ -// +build experimental - -package client - -import ( - "bytes" - "encoding/json" - "fmt" - "net/http" - "text/tabwriter" - - flag "github.com/docker/docker/pkg/mflag" - "github.com/docker/docker/pkg/stringid" -) - -var ( - serviceCommands = []command{ - {"create", "Create a service endpoint"}, - {"rm", "Remove a service endpoint"}, - {"join", "Join a container to a service endpoint"}, - {"leave", "Leave a container from a service endpoint"}, - {"ls", "Lists all service endpoints on a network"}, - {"info", "Display information of a service endpoint"}, - } -) - -func lookupServiceID(cli *NetworkCli, networkID string, nameID string) (string, error) { - obj, statusCode, err := readBody(cli.call("GET", fmt.Sprintf("/networks/%s/endpoints?name=%s", networkID, nameID), nil, nil)) - if err != nil { - return "", err - } - - if statusCode != http.StatusOK { - return "", fmt.Errorf("name query failed for %s due to : statuscode(%d) %v", nameID, statusCode, string(obj)) - } - - var list []*networkResource - err = json.Unmarshal(obj, &list) - if err != nil { - return "", err - } - if len(list) > 0 { - // name query filter will always return a single-element collection - return list[0].ID, nil - } - - // Check for Partial-id - obj, statusCode, err = readBody(cli.call("GET", fmt.Sprintf("/networks/%s/endpoints?partial-id=%s", networkID, nameID), nil, nil)) - if err != nil { - return "", err - } - - if statusCode != http.StatusOK { - return "", fmt.Errorf("partial-id match query failed for %s due to : statuscode(%d) %v", nameID, statusCode, string(obj)) - } - - err = json.Unmarshal(obj, &list) - if err != nil { - return "", err - } - if len(list) == 0 { - return "", fmt.Errorf("resource not found %s", nameID) - } - if len(list) > 1 { - return "", fmt.Errorf("multiple services matching the partial identifier (%s). Please use full identifier", nameID) - } - return list[0].ID, nil -} - -func lookupContainerID(cli *NetworkCli, nameID string) (string, error) { - // TODO : containerID to sandbox-key ? - return nameID, nil -} - -// CmdNetworkService handles the network service UI -func (cli *NetworkCli) CmdNetworkService(chain string, args ...string) error { - cmd := cli.Subcmd(chain, "service", "COMMAND [OPTIONS] [arg...]", serviceUsage(chain), false) - cmd.Require(flag.Min, 1) - err := cmd.ParseFlags(args, true) - if err == nil { - cmd.Usage() - return fmt.Errorf("Invalid command : %v", args) - } - return err -} - -// CmdNetworkServiceCreate handles service create UI -func (cli *NetworkCli) CmdNetworkServiceCreate(chain string, args ...string) error { - cmd := cli.Subcmd(chain, "create", "SERVICE NETWORK", "Creates a new service on a network", false) - cmd.Require(flag.Min, 2) - err := cmd.ParseFlags(args, true) - if err != nil { - return err - } - - networkID, err := lookupNetworkID(cli, cmd.Arg(1)) - if err != nil { - return err - } - - ec := endpointCreate{Name: cmd.Arg(0), NetworkID: networkID} - - obj, _, err := readBody(cli.call("POST", "/networks/"+networkID+"/endpoints", ec, nil)) - if err != nil { - return err - } - - var replyID string - err = json.Unmarshal(obj, &replyID) - if err != nil { - return err - } - - fmt.Fprintf(cli.out, "%s\n", replyID) - return nil -} - -// CmdNetworkServiceRm handles service delete UI -func (cli *NetworkCli) CmdNetworkServiceRm(chain string, args ...string) error { - cmd := cli.Subcmd(chain, "rm", "SERVICE NETWORK", "Deletes a service", false) - cmd.Require(flag.Min, 2) - err := cmd.ParseFlags(args, true) - if err != nil { - return err - } - - networkID, err := lookupNetworkID(cli, cmd.Arg(1)) - if err != nil { - return err - } - - serviceID, err := lookupServiceID(cli, networkID, cmd.Arg(0)) - if err != nil { - return err - } - - _, _, err = readBody(cli.call("DELETE", "/networks/"+networkID+"/endpoints/"+serviceID, nil, nil)) - if err != nil { - return err - } - return nil -} - -// CmdNetworkServiceLs handles service list UI -func (cli *NetworkCli) CmdNetworkServiceLs(chain string, args ...string) error { - cmd := cli.Subcmd(chain, "ls", "NETWORK", "Lists all the services on a network", false) - quiet := cmd.Bool([]string{"q", "-quiet"}, false, "Only display numeric IDs") - noTrunc := cmd.Bool([]string{"#notrunc", "-no-trunc"}, false, "Do not truncate the output") - nLatest := cmd.Bool([]string{"l", "-latest"}, false, "Show the latest network created") - last := cmd.Int([]string{"n"}, -1, "Show n last created networks") - err := cmd.ParseFlags(args, true) - if err != nil { - return err - } - - cmd.Require(flag.Min, 1) - - networkID, err := lookupNetworkID(cli, cmd.Arg(0)) - if err != nil { - return err - } - - obj, _, err := readBody(cli.call("GET", "/networks/"+networkID+"/endpoints", nil, nil)) - if err != nil { - fmt.Fprintf(cli.err, "%s", err.Error()) - return err - } - if *last == -1 && *nLatest { - *last = 1 - } - - var endpointResources []endpointResource - err = json.Unmarshal(obj, &endpointResources) - if err != nil { - return err - } - - wr := tabwriter.NewWriter(cli.out, 20, 1, 3, ' ', 0) - // unless quiet (-q) is specified, print field titles - if !*quiet { - fmt.Fprintln(wr, "NETWORK SERVICE ID\tNAME\tNETWORK") - } - - for _, networkResource := range endpointResources { - ID := networkResource.ID - netName := networkResource.Name - if !*noTrunc { - ID = stringid.TruncateID(ID) - } - if *quiet { - fmt.Fprintln(wr, ID) - continue - } - network := networkResource.Network - fmt.Fprintf(wr, "%s\t%s\t%s", - ID, - netName, - network) - fmt.Fprint(wr, "\n") - } - wr.Flush() - - return nil -} - -// CmdNetworkServiceInfo handles service info UI -func (cli *NetworkCli) CmdNetworkServiceInfo(chain string, args ...string) error { - cmd := cli.Subcmd(chain, "info", "SERVICE NETWORK", "Displays detailed information on a service", false) - cmd.Require(flag.Min, 2) - err := cmd.ParseFlags(args, true) - if err != nil { - return err - } - - networkID, err := lookupNetworkID(cli, cmd.Arg(1)) - if err != nil { - return err - } - - serviceID, err := lookupServiceID(cli, networkID, cmd.Arg(0)) - if err != nil { - return err - } - - obj, _, err := readBody(cli.call("GET", "/networks/"+networkID+"/endpoints/"+serviceID, nil, nil)) - if err != nil { - fmt.Fprintf(cli.err, "%s", err.Error()) - return err - } - - endpointResource := &endpointResource{} - if err := json.NewDecoder(bytes.NewReader(obj)).Decode(endpointResource); err != nil { - return err - } - fmt.Fprintf(cli.out, "Service Id: %s\n", endpointResource.ID) - fmt.Fprintf(cli.out, "\tName: %s\n", endpointResource.Name) - fmt.Fprintf(cli.out, "\tNetwork: %s\n", endpointResource.Network) - - return nil -} - -// CmdNetworkServiceJoin handles service join UI -func (cli *NetworkCli) CmdNetworkServiceJoin(chain string, args ...string) error { - cmd := cli.Subcmd(chain, "join", "CONTAINER SERVICE NETWORK", "Sets a container as a service backend", false) - cmd.Require(flag.Min, 3) - err := cmd.ParseFlags(args, true) - if err != nil { - return err - } - - containerID, err := lookupContainerID(cli, cmd.Arg(0)) - if err != nil { - return err - } - - networkID, err := lookupNetworkID(cli, cmd.Arg(2)) - if err != nil { - return err - } - - serviceID, err := lookupServiceID(cli, networkID, cmd.Arg(1)) - if err != nil { - return err - } - - nc := endpointJoin{ContainerID: containerID} - - _, _, err = readBody(cli.call("POST", "/networks/"+networkID+"/endpoints/"+serviceID+"/containers", nc, nil)) - if err != nil { - fmt.Fprintf(cli.err, "%s", err.Error()) - return err - } - return nil -} - -// CmdNetworkServiceLeave handles service leave UI -func (cli *NetworkCli) CmdNetworkServiceLeave(chain string, args ...string) error { - cmd := cli.Subcmd(chain, "leave", "CONTAINER SERVICE NETWORK", "Removes a container from service backend", false) - cmd.Require(flag.Min, 3) - err := cmd.ParseFlags(args, true) - if err != nil { - return err - } - - containerID, err := lookupContainerID(cli, cmd.Arg(0)) - if err != nil { - return err - } - - networkID, err := lookupNetworkID(cli, cmd.Arg(2)) - if err != nil { - return err - } - - serviceID, err := lookupServiceID(cli, networkID, cmd.Arg(1)) - if err != nil { - return err - } - - _, _, err = readBody(cli.call("DELETE", "/networks/"+networkID+"/endpoints/"+serviceID+"/containers/"+containerID, nil, nil)) - if err != nil { - fmt.Fprintf(cli.err, "%s", err.Error()) - return err - } - return nil -} - -func serviceUsage(chain string) string { - help := "Commands:\n" - - for _, cmd := range serviceCommands { - help += fmt.Sprintf(" %-10.10s%s\n", cmd.name, cmd.description) - } - - help += fmt.Sprintf("\nRun '%s service COMMAND --help' for more information on a command.", chain) - return help -} diff --git a/libnetwork/cmd/dnet/flags.go b/libnetwork/cmd/dnet/flags.go index 2e77e1873b..595971bbfe 100644 --- a/libnetwork/cmd/dnet/flags.go +++ b/libnetwork/cmd/dnet/flags.go @@ -23,6 +23,7 @@ var ( dnetCommands = []command{ {"network", "Network management commands"}, + {"service", "Service management commands"}, } ) @@ -45,5 +46,5 @@ func init() { } func printUsage() { - fmt.Println("Usage: dnet network ") + fmt.Println("Usage: dnet COMMAND [arg...]") }