diff --git a/libnetwork/client/client.go b/libnetwork/client/client.go index 5c3bda6243..64c6f7da53 100644 --- a/libnetwork/client/client.go +++ b/libnetwork/client/client.go @@ -1,11 +1,9 @@ package client import ( - "errors" "fmt" "io" "io/ioutil" - "os" "reflect" "strings" @@ -51,25 +49,21 @@ func (cli *NetworkCli) getMethod(args ...string) (func(string, ...string) error, // Cmd is borrowed from Docker UI and acts as the entry point for network UI commands. // network UI commands are designed to be invoked from multiple parent chains func (cli *NetworkCli) Cmd(chain string, args ...string) error { - var errStr string if len(args) > 1 { method, exists := cli.getMethod(args[:2]...) if exists { - return method(chain, args[2:]...) + return method(chain+" "+args[0], args[2:]...) } } if len(args) > 0 { method, exists := cli.getMethod(args[0]) if !exists { - errStr = fmt.Sprintf("%s: '%s' is not a %s command. See '%s --help'.\n", chain, args[0], chain, chain) - fmt.Fprintf(cli.err, errStr) - return errors.New(errStr) + return fmt.Errorf("%s: '%s' is not a %s command. See '%s --help'.\n", chain, args[0], chain, chain) } return method(chain, args[1:]...) } - errStr = fmt.Sprintf("'%s' is not a valid command. See '%s --help'.\n", chain, chain) - fmt.Fprintf(cli.err, errStr) - return errors.New(errStr) + flag.Usage() + return nil } // Subcmd is borrowed from Docker UI and performs the same function of configuring the subCmds @@ -92,7 +86,6 @@ func (cli *NetworkCli) Subcmd(chain, name, signature, description string, exitOn fmt.Fprintf(cli.out, "\nUsage: %s %s%s%s\n\n%s\n\n", chain, name, options, signature, description) flags.SetOutput(cli.out) flags.PrintDefaults() - os.Exit(0) } return flags } diff --git a/libnetwork/client/client_test.go b/libnetwork/client/client_test.go index a07ca93f5f..fbb5ba240a 100644 --- a/libnetwork/client/client_test.go +++ b/libnetwork/client/client_test.go @@ -28,16 +28,16 @@ func TestClientDummyCommand(t *testing.T) { } } -func TestClientNoCommand(t *testing.T) { +func TestClientNetworkInvalidCommand(t *testing.T) { var out, errOut bytes.Buffer cFunc := func(method, path string, data interface{}, headers map[string][]string) (io.ReadCloser, int, error) { return nopCloser{bytes.NewBufferString("")}, 200, nil } cli := NewNetworkCli(&out, &errOut, cFunc) - err := cli.Cmd("docker") + err := cli.Cmd("docker", "network", "invalid") if err == nil { - t.Fatalf("Incorrect Command must fail") + t.Fatalf("Passing invalid commands must fail") } } @@ -119,33 +119,7 @@ func TestClientNetworkInfo(t *testing.T) { } } -func TestClientNetworkJoin(t *testing.T) { - var out, errOut bytes.Buffer - cFunc := func(method, path string, data interface{}, headers map[string][]string) (io.ReadCloser, int, error) { - return nopCloser{bytes.NewBufferString("")}, 200, nil - } - cli := NewNetworkCli(&out, &errOut, cFunc) - - err := cli.Cmd("docker", "network", "join", "db1", "dbnet", "db1-ep") - if err != nil { - t.Fatal(err.Error()) - } -} - -func TestClientNetworkLeave(t *testing.T) { - var out, errOut bytes.Buffer - cFunc := func(method, path string, data interface{}, headers map[string][]string) (io.ReadCloser, int, error) { - return nopCloser{bytes.NewBufferString("")}, 200, nil - } - cli := NewNetworkCli(&out, &errOut, cFunc) - - err := cli.Cmd("docker", "network", "leave", "db1", "dbnet") - if err != nil { - t.Fatal(err.Error()) - } -} - -// Docker Flag processing in flag.go uses os.Exit(0) for --help +// Docker Flag processing in flag.go uses os.Exit() frequently, even for --help // TODO : Handle the --help test-case in the IT when CLI is available /* func TestClientNetworkCreateHelp(t *testing.T) { diff --git a/libnetwork/client/network.go b/libnetwork/client/network.go index 6390975f24..52bd9c8d7e 100644 --- a/libnetwork/client/network.go +++ b/libnetwork/client/network.go @@ -8,17 +8,57 @@ import ( flag "github.com/docker/docker/pkg/mflag" ) +const ( + nullNetType = "null" +) + +type command struct { + name string + description string +} + +var ( + networkCommands = []command{ + {"create", "Create a network"}, + {"rm", "Remove a network"}, + {"ls", "List all networks"}, + {"info", "Display information of a network"}, + } +) + +func (cli *NetworkCli) CmdNetwork(chain string, args ...string) error { + cmd := cli.Subcmd(chain, "network", "COMMAND [OPTIONS] [arg...]", networkUsage(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 +} + +func networkUsage(chain string) string { + help := "Commands:\n" + + for _, cmd := range networkCommands { + help += fmt.Sprintf(" %-10.10s%s\n", cmd.name, cmd.description) + } + + help += fmt.Sprintf("\nRun '%s network COMMAND --help' for more information on a command.", chain) + return help +} + // CmdNetworkCreate handles Network Create UI func (cli *NetworkCli) CmdNetworkCreate(chain string, args ...string) error { - cmd := cli.Subcmd(chain, "create", "NETWORK-NAME", chain+" create", false) - flDriver := cmd.String([]string{"d", "-driver"}, "", "Driver to manage the Network") + cmd := cli.Subcmd(chain, "create", "NETWORK-NAME", "Creates a new network with a name specified by the user", false) + flDriver := cmd.String([]string{"d", "-driver"}, "null", "Driver to manage the Network") cmd.Require(flag.Min, 1) err := cmd.ParseFlags(args, true) if err != nil { return err } if *flDriver == "" { - *flDriver = "bridge" + *flDriver = nullNetType } // TODO : Proper Backend handling obj, _, err := readBody(cli.call("POST", "/networks/"+args[0], nil, nil)) @@ -34,7 +74,7 @@ func (cli *NetworkCli) CmdNetworkCreate(chain string, args ...string) error { // CmdNetworkRm handles Network Delete UI func (cli *NetworkCli) CmdNetworkRm(chain string, args ...string) error { - cmd := cli.Subcmd(chain, "rm", "NETWORK-NAME", chain+" rm", false) + cmd := cli.Subcmd(chain, "rm", "NETWORK-NAME", "Deletes a network", false) cmd.Require(flag.Min, 1) err := cmd.ParseFlags(args, true) if err != nil { @@ -54,7 +94,7 @@ func (cli *NetworkCli) CmdNetworkRm(chain string, args ...string) error { // CmdNetworkLs handles Network List UI func (cli *NetworkCli) CmdNetworkLs(chain string, args ...string) error { - cmd := cli.Subcmd(chain, "ls", "", chain+" ls", false) + cmd := cli.Subcmd(chain, "ls", "", "Lists all the networks created by the user", false) err := cmd.ParseFlags(args, true) if err != nil { return err @@ -73,7 +113,7 @@ func (cli *NetworkCli) CmdNetworkLs(chain string, args ...string) error { // CmdNetworkInfo handles Network Info UI func (cli *NetworkCli) CmdNetworkInfo(chain string, args ...string) error { - cmd := cli.Subcmd(chain, "info", "NETWORK-NAME", chain+" info", false) + cmd := cli.Subcmd(chain, "info", "NETWORK-NAME", "Displays detailed information on a network", false) cmd.Require(flag.Min, 1) err := cmd.ParseFlags(args, true) if err != nil {