diff --git a/libnetwork/client/client.go b/libnetwork/client/client.go deleted file mode 100644 index 2916d38041..0000000000 --- a/libnetwork/client/client.go +++ /dev/null @@ -1,115 +0,0 @@ -package client - -import ( - "fmt" - "io" - "io/ioutil" - "net/http" - "reflect" - "strings" - - flag "github.com/docker/docker/libnetwork/client/mflag" -) - -// CallFunc provides environment specific call utility to invoke backend functions from UI -type CallFunc func(string, string, interface{}, map[string][]string) (io.ReadCloser, http.Header, int, error) - -// NetworkCli is the UI object for network subcmds -type NetworkCli struct { - out io.Writer - err io.Writer - call CallFunc -} - -// NewNetworkCli is a convenient function to create a NetworkCli object -func NewNetworkCli(out, err io.Writer, call CallFunc) *NetworkCli { - return &NetworkCli{ - out: out, - err: err, - call: call, - } -} - -// getMethod is Borrowed from Docker UI which uses reflection to identify the UI Handler -func (cli *NetworkCli) getMethod(args ...string) (func(string, ...string) error, bool) { - camelArgs := make([]string, len(args)) - for i, s := range args { - if len(s) == 0 { - return nil, false - } - camelArgs[i] = strings.ToUpper(s[:1]) + strings.ToLower(s[1:]) - } - methodName := "Cmd" + strings.Join(camelArgs, "") - method := reflect.ValueOf(cli).MethodByName(methodName) - if !method.IsValid() { - return nil, false - } - return method.Interface().(func(string, ...string) error), true -} - -// 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 { - if len(args) > 2 { - method, exists := cli.getMethod(args[:3]...) - if exists { - return method(chain+" "+args[0]+" "+args[1], args[3:]...) - } - } - if len(args) > 1 { - method, exists := cli.getMethod(args[:2]...) - if exists { - return method(chain+" "+args[0], args[2:]...) - } - } - if len(args) > 0 { - method, exists := cli.getMethod(args[0]) - if !exists { - return fmt.Errorf("%s: '%s' is not a %s command. See '%s --help'", chain, args[0], chain, chain) - } - return method(chain, args[1:]...) - } - flag.Usage() - return nil -} - -// Subcmd is borrowed from Docker UI and performs the same function of configuring the subCmds -func (cli *NetworkCli) Subcmd(chain, name, signature, description string, exitOnError bool) *flag.FlagSet { - var errorHandling flag.ErrorHandling - if exitOnError { - errorHandling = flag.ExitOnError - } else { - errorHandling = flag.ContinueOnError - } - flags := flag.NewFlagSet(name, errorHandling) - flags.Usage = func() { - flags.ShortUsage() - flags.PrintDefaults() - } - flags.ShortUsage = func() { - options := "" - if signature != "" { - signature = " " + signature - } - if flags.FlagCountUndeprecated() > 0 { - options = " [OPTIONS]" - } - fmt.Fprintf(cli.out, "\nUsage: %s %s%s%s\n\n%s\n\n", chain, name, options, signature, description) - flags.SetOutput(cli.out) - } - return flags -} - -func readBody(stream io.ReadCloser, hdr http.Header, statusCode int, err error) ([]byte, int, error) { - if stream != nil { - defer stream.Close() - } - if err != nil { - return nil, statusCode, err - } - body, err := ioutil.ReadAll(stream) - if err != nil { - return nil, -1, err - } - return body, statusCode, nil -} diff --git a/libnetwork/client/client_service_test.go b/libnetwork/client/client_service_test.go deleted file mode 100644 index 5170200fdf..0000000000 --- a/libnetwork/client/client_service_test.go +++ /dev/null @@ -1,122 +0,0 @@ -package client - -import ( - "bytes" - "testing" - - _ "github.com/docker/docker/libnetwork/testutils" -) - -func TestClientServiceInvalidCommand(t *testing.T) { - var out, errOut bytes.Buffer - cli := NewNetworkCli(&out, &errOut, callbackFunc) - - err := cli.Cmd("docker", "service", "invalid") - if err == nil { - t.Fatal("Passing invalid commands must fail") - } -} - -func TestClientServiceCreate(t *testing.T) { - var out, errOut bytes.Buffer - cli := NewNetworkCli(&out, &errOut, callbackFunc) - - err := cli.Cmd("docker", "service", "publish", mockServiceName+"."+mockNwName) - if err != nil { - t.Fatal(err) - } -} - -func TestClientServiceRm(t *testing.T) { - var out, errOut bytes.Buffer - cli := NewNetworkCli(&out, &errOut, callbackFunc) - - err := cli.Cmd("docker", "service", "unpublish", mockServiceName+"."+mockNwName) - if err != nil { - t.Fatal(err) - } -} - -func TestClientServiceLs(t *testing.T) { - var out, errOut bytes.Buffer - cli := NewNetworkCli(&out, &errOut, callbackFunc) - - err := cli.Cmd("docker", "service", "ls") - if err != nil { - t.Fatal(err) - } -} - -func TestClientServiceInfo(t *testing.T) { - var out, errOut bytes.Buffer - cli := NewNetworkCli(&out, &errOut, callbackFunc) - - err := cli.Cmd("docker", "service", "info", mockServiceName+"."+mockNwName) - if err != nil { - t.Fatal(err) - } -} - -func TestClientServiceInfoById(t *testing.T) { - var out, errOut bytes.Buffer - cli := NewNetworkCli(&out, &errOut, callbackFunc) - - err := cli.Cmd("docker", "service", "info", mockServiceID+"."+mockNwName) - if err != nil { - t.Fatal(err) - } -} - -func TestClientServiceJoin(t *testing.T) { - var out, errOut bytes.Buffer - cli := NewNetworkCli(&out, &errOut, callbackFunc) - - err := cli.Cmd("docker", "service", "attach", mockContainerID, mockServiceName+"."+mockNwName) - if err != nil { - t.Fatal(err) - } -} - -func TestClientServiceLeave(t *testing.T) { - var out, errOut bytes.Buffer - cli := NewNetworkCli(&out, &errOut, callbackFunc) - - err := cli.Cmd("docker", "service", "detach", mockContainerID, mockServiceName+"."+mockNwName) - if err != nil { - t.Fatal(err) - } -} - -// 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 TestClientNetworkServiceCreateHelp(t *testing.T) { - var out, errOut bytes.Buffer - cFunc := func(method, path string, data interface{}, headers map[string][]string) (io.ReadCloser, int, error) { - return nil, 0, nil - } - cli := NewNetworkCli(&out, &errOut, callbackFunc) - - err := cli.Cmd("docker", "network", "create", "--help") - if err != nil { - t.Fatalf(err.Error()) - } -} -*/ - -// Docker flag processing in flag.go uses os.Exit(1) for incorrect parameter case. -// TODO : Handle the missing argument case in the IT when CLI is available -/* -func TestClientNetworkServiceCreateMissingArgument(t *testing.T) { - var out, errOut bytes.Buffer - cFunc := func(method, path string, data interface{}, headers map[string][]string) (io.ReadCloser, int, error) { - return nil, 0, nil - } - cli := NewNetworkCli(&out, &errOut, callbackFunc) - - err := cli.Cmd("docker", "network", "create") - if err != nil { - t.Fatal(err.Error()) - } -} -*/ diff --git a/libnetwork/client/client_test.go b/libnetwork/client/client_test.go deleted file mode 100644 index 0c42cc0fae..0000000000 --- a/libnetwork/client/client_test.go +++ /dev/null @@ -1,228 +0,0 @@ -package client - -import ( - "bytes" - "encoding/json" - "fmt" - "io" - "net/http" - "os" - "strings" - "testing" - - _ "github.com/docker/docker/libnetwork/testutils" -) - -// nopCloser is used to provide a dummy CallFunc for Cmd() -type nopCloser struct { - io.Reader -} - -func (nopCloser) Close() error { return nil } - -func TestMain(m *testing.M) { - setupMockHTTPCallback() - os.Exit(m.Run()) -} - -var callbackFunc func(method, path string, data interface{}, headers map[string][]string) (io.ReadCloser, http.Header, int, error) -var mockNwJSON, mockNwListJSON, mockServiceJSON, mockServiceListJSON, mockSbJSON, mockSbListJSON []byte -var mockNwName = "test" -var mockNwID = "2a3456789" -var mockServiceName = "testSrv" -var mockServiceID = "2a3456789" -var mockContainerID = "2a3456789" -var mockSandboxID = "2b3456789" - -func setupMockHTTPCallback() { - var list []networkResource - nw := networkResource{Name: mockNwName, ID: mockNwID} - mockNwJSON, _ = json.Marshal(nw) - list = append(list, nw) - mockNwListJSON, _ = json.Marshal(list) - - var srvList []serviceResource - ep := serviceResource{Name: mockServiceName, ID: mockServiceID, Network: mockNwName} - mockServiceJSON, _ = json.Marshal(ep) - srvList = append(srvList, ep) - mockServiceListJSON, _ = json.Marshal(srvList) - - var sbxList []SandboxResource - sb := SandboxResource{ID: mockSandboxID, ContainerID: mockContainerID} - mockSbJSON, _ = json.Marshal(sb) - sbxList = append(sbxList, sb) - mockSbListJSON, _ = json.Marshal(sbxList) - - dummyHTTPHdr := http.Header{} - - callbackFunc = func(method, path string, data interface{}, headers map[string][]string) (io.ReadCloser, http.Header, int, error) { - var rsp string - switch method { - case "GET": - if strings.Contains(path, fmt.Sprintf("networks?name=%s", mockNwName)) { - rsp = string(mockNwListJSON) - } else if strings.Contains(path, "networks?name=") { - rsp = "[]" - } else if strings.Contains(path, fmt.Sprintf("networks?partial-id=%s", mockNwID)) { - rsp = string(mockNwListJSON) - } else if strings.Contains(path, "networks?partial-id=") { - rsp = "[]" - } else if strings.HasSuffix(path, "networks") { - rsp = string(mockNwListJSON) - } else if strings.HasSuffix(path, "networks/"+mockNwID) { - rsp = string(mockNwJSON) - } else if strings.Contains(path, fmt.Sprintf("services?name=%s", mockServiceName)) { - rsp = string(mockServiceListJSON) - } else if strings.Contains(path, "services?name=") { - rsp = "[]" - } else if strings.Contains(path, fmt.Sprintf("services?partial-id=%s", mockServiceID)) { - rsp = string(mockServiceListJSON) - } else if strings.Contains(path, "services?partial-id=") { - rsp = "[]" - } else if strings.HasSuffix(path, "services") { - rsp = string(mockServiceListJSON) - } else if strings.HasSuffix(path, "services/"+mockServiceID) { - rsp = string(mockServiceJSON) - } else if strings.Contains(path, "containers") { - return nopCloser{bytes.NewBufferString("")}, dummyHTTPHdr, 400, fmt.Errorf("Bad Request") - } else if strings.Contains(path, fmt.Sprintf("sandboxes?container-id=%s", mockContainerID)) { - rsp = string(mockSbListJSON) - } else if strings.Contains(path, fmt.Sprintf("sandboxes?partial-container-id=%s", mockContainerID)) { - rsp = string(mockSbListJSON) - } - case "POST": - var data []byte - if strings.HasSuffix(path, "networks") { - data, _ = json.Marshal(mockNwID) - } else if strings.HasSuffix(path, "services") { - data, _ = json.Marshal(mockServiceID) - } else if strings.HasSuffix(path, "backend") { - data, _ = json.Marshal(mockSandboxID) - } - rsp = string(data) - case "PUT": - case "DELETE": - rsp = "" - } - return nopCloser{bytes.NewBufferString(rsp)}, dummyHTTPHdr, 200, nil - } -} - -func TestClientDummyCommand(t *testing.T) { - var out, errOut bytes.Buffer - cli := NewNetworkCli(&out, &errOut, callbackFunc) - - err := cli.Cmd("docker", "dummy") - if err == nil { - t.Fatal("Incorrect Command must fail") - } -} - -func TestClientNetworkInvalidCommand(t *testing.T) { - var out, errOut bytes.Buffer - cli := NewNetworkCli(&out, &errOut, callbackFunc) - - err := cli.Cmd("docker", "network", "invalid") - if err == nil { - t.Fatal("Passing invalid commands must fail") - } -} - -func TestClientNetworkCreate(t *testing.T) { - var out, errOut bytes.Buffer - cli := NewNetworkCli(&out, &errOut, callbackFunc) - - err := cli.Cmd("docker", "network", "create", mockNwName) - if err != nil { - t.Fatal(err.Error()) - } -} - -func TestClientNetworkCreateWithDriver(t *testing.T) { - var out, errOut bytes.Buffer - cli := NewNetworkCli(&out, &errOut, callbackFunc) - - err := cli.Cmd("docker", "network", "create", "-f=dummy", mockNwName) - if err == nil { - t.Fatal("Passing incorrect flags to the create command must fail") - } - - err = cli.Cmd("docker", "network", "create", "-d=dummy", mockNwName) - if err != nil { - t.Fatalf(err.Error()) - } -} - -func TestClientNetworkRm(t *testing.T) { - var out, errOut bytes.Buffer - cli := NewNetworkCli(&out, &errOut, callbackFunc) - - err := cli.Cmd("docker", "network", "rm", mockNwName) - if err != nil { - t.Fatal(err.Error()) - } -} - -func TestClientNetworkLs(t *testing.T) { - var out, errOut bytes.Buffer - cli := NewNetworkCli(&out, &errOut, callbackFunc) - - err := cli.Cmd("docker", "network", "ls") - if err != nil { - t.Fatal(err.Error()) - } -} - -func TestClientNetworkInfo(t *testing.T) { - var out, errOut bytes.Buffer - cli := NewNetworkCli(&out, &errOut, callbackFunc) - - err := cli.Cmd("docker", "network", "info", mockNwName) - if err != nil { - t.Fatal(err.Error()) - } -} - -func TestClientNetworkInfoById(t *testing.T) { - var out, errOut bytes.Buffer - cli := NewNetworkCli(&out, &errOut, callbackFunc) - - err := cli.Cmd("docker", "network", "info", mockNwID) - if err != nil { - t.Fatal(err.Error()) - } -} - -// 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 TestClientNetworkServiceCreateHelp(t *testing.T) { - var out, errOut bytes.Buffer - cFunc := func(method, path string, data interface{}, headers map[string][]string) (io.ReadCloser, int, error) { - return nil, 0, nil - } - cli := NewNetworkCli(&out, &errOut, callbackFunc) - - err := cli.Cmd("docker", "network", "create", "--help") - if err != nil { - t.Fatalf(err.Error()) - } -} -*/ - -// Docker flag processing in flag.go uses os.Exit(1) for incorrect parameter case. -// TODO : Handle the missing argument case in the IT when CLI is available -/* -func TestClientNetworkServiceCreateMissingArgument(t *testing.T) { - var out, errOut bytes.Buffer - cFunc := func(method, path string, data interface{}, headers map[string][]string) (io.ReadCloser, int, error) { - return nil, 0, nil - } - cli := NewNetworkCli(&out, &errOut, callbackFunc) - - err := cli.Cmd("docker", "network", "create") - if err != nil { - t.Fatal(err.Error()) - } -} -*/ diff --git a/libnetwork/client/mflag/LICENSE b/libnetwork/client/mflag/LICENSE deleted file mode 100644 index 9b4f4a294e..0000000000 --- a/libnetwork/client/mflag/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -Copyright (c) 2014-2016 The Docker & Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/libnetwork/client/mflag/README.md b/libnetwork/client/mflag/README.md deleted file mode 100644 index da00efa336..0000000000 --- a/libnetwork/client/mflag/README.md +++ /dev/null @@ -1,40 +0,0 @@ -Package mflag (aka multiple-flag) implements command-line flag parsing. -It's an **hacky** fork of the [official golang package](http://golang.org/pkg/flag/) - -It adds: - -* both short and long flag version -`./example -s red` `./example --string blue` - -* multiple names for the same option -``` -$>./example -h -Usage of example: - -s, --string="": a simple string -``` - -___ -It is very flexible on purpose, so you can do things like: -``` -$>./example -h -Usage of example: - -s, -string, --string="": a simple string -``` - -Or: -``` -$>./example -h -Usage of example: - -oldflag, --newflag="": a simple string -``` - -You can also hide some flags from the usage, so if we want only `--newflag`: -``` -$>./example -h -Usage of example: - --newflag="": a simple string -$>./example -oldflag str -str -``` - -See [example.go](example/example.go) for more details. diff --git a/libnetwork/client/mflag/example/example.go b/libnetwork/client/mflag/example/example.go deleted file mode 100644 index 6125878665..0000000000 --- a/libnetwork/client/mflag/example/example.go +++ /dev/null @@ -1,36 +0,0 @@ -package main - -import ( - "fmt" - - flag "github.com/docker/docker/libnetwork/client/mflag" -) - -var ( - i int - str string - b, b2, h bool -) - -func init() { - flag.Bool([]string{"#hp", "#-help"}, false, "display the help") - flag.BoolVar(&b, []string{"b", "#bal", "#bol", "-bal"}, false, "a simple bool") - flag.BoolVar(&b, []string{"g", "#gil"}, false, "a simple bool") - flag.BoolVar(&b2, []string{"#-bool"}, false, "a simple bool") - flag.IntVar(&i, []string{"-integer", "-number"}, -1, "a simple integer") - flag.StringVar(&str, []string{"s", "#hidden", "-string"}, "", "a simple string") //-s -hidden and --string will work, but -hidden won't be in the usage - flag.BoolVar(&h, []string{"h", "#help", "-help"}, false, "display the help") - flag.StringVar(&str, []string{"mode"}, "mode1", "set the mode\nmode1: use the mode1\nmode2: use the mode2\nmode3: use the mode3") - flag.Parse() -} -func main() { - if h { - flag.PrintDefaults() - } else { - fmt.Printf("s/#hidden/-string: %s\n", str) - fmt.Printf("b: %t\n", b) - fmt.Printf("-bool: %t\n", b2) - fmt.Printf("s/#hidden/-string(via lookup): %s\n", flag.Lookup("s").Value.String()) - fmt.Printf("ARGS: %v\n", flag.Args()) - } -} diff --git a/libnetwork/client/mflag/flag.go b/libnetwork/client/mflag/flag.go deleted file mode 100644 index 04b2dd917a..0000000000 --- a/libnetwork/client/mflag/flag.go +++ /dev/null @@ -1,1326 +0,0 @@ -// Copyright 2014-2016 The Docker & Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package mflag implements command-line flag parsing. -// -// Usage: -// -// Define flags using flag.String(), Bool(), Int(), etc. -// -// This declares an integer flag, -f or --flagname, stored in the pointer ip, with type *int. -// import "flag /github.com/docker/libnetwork/client/mflag" -// var ip = flag.Int([]string{"f", "-flagname"}, 1234, "help message for flagname") -// If you like, you can bind the flag to a variable using the Var() functions. -// var flagvar int -// func init() { -// // -flaghidden will work, but will be hidden from the usage -// flag.IntVar(&flagvar, []string{"f", "#flaghidden", "-flagname"}, 1234, "help message for flagname") -// } -// Or you can create custom flags that satisfy the Value interface (with -// pointer receivers) and couple them to flag parsing by -// flag.Var(&flagVal, []string{"name"}, "help message for flagname") -// For such flags, the default value is just the initial value of the variable. -// -// You can also add "deprecated" flags, they are still usable, but are not shown -// in the usage and will display a warning when you try to use them. `#` before -// an option means this option is deprecated, if there is an following option -// without `#` ahead, then that's the replacement, if not, it will just be removed: -// var ip = flag.Int([]string{"#f", "#flagname", "-flagname"}, 1234, "help message for flagname") -// this will display: `Warning: '-f' is deprecated, it will be replaced by '--flagname' soon. See usage.` or -// this will display: `Warning: '-flagname' is deprecated, it will be replaced by '--flagname' soon. See usage.` -// var ip = flag.Int([]string{"f", "#flagname"}, 1234, "help message for flagname") -// will display: `Warning: '-flagname' is deprecated, it will be removed soon. See usage.` -// so you can only use `-f`. -// -// You can also group one letter flags, bif you declare -// var v = flag.Bool([]string{"v", "-verbose"}, false, "help message for verbose") -// var s = flag.Bool([]string{"s", "-slow"}, false, "help message for slow") -// you will be able to use the -vs or -sv -// -// After all flags are defined, call -// flag.Parse() -// to parse the command line into the defined flags. -// -// Flags may then be used directly. If you're using the flags themselves, -// they are all pointers; if you bind to variables, they're values. -// fmt.Println("ip has value ", *ip) -// fmt.Println("flagvar has value ", flagvar) -// -// After parsing, the arguments after the flag are available as the -// slice flag.Args() or individually as flag.Arg(i). -// The arguments are indexed from 0 through flag.NArg()-1. -// -// Command line flag syntax: -// -flag -// -flag=x -// -flag="x" -// -flag='x' -// -flag x // non-boolean flags only -// One or two minus signs may be used; they are equivalent. -// The last form is not permitted for boolean flags because the -// meaning of the command -// cmd -x * -// will change if there is a file called 0, false, etc. You must -// use the -flag=false form to turn off a boolean flag. -// -// Flag parsing stops just before the first non-flag argument -// ("-" is a non-flag argument) or after the terminator "--". -// -// Integer flags accept 1234, 0664, 0x1234 and may be negative. -// Boolean flags may be 1, 0, t, f, true, false, TRUE, FALSE, True, False. -// Duration flags accept any input valid for time.ParseDuration. -// -// The default set of command-line flags is controlled by -// top-level functions. The FlagSet type allows one to define -// independent sets of flags, such as to implement subcommands -// in a command-line interface. The methods of FlagSet are -// analogous to the top-level functions for the command-line -// flag set. - -package mflag - -import ( - "errors" - "fmt" - "io" - "os" - "runtime" - "sort" - "strconv" - "strings" - "text/tabwriter" - "time" -) - -// ErrHelp is the error returned if the flag -help is invoked but no such flag is defined. -var ErrHelp = errors.New("flag: help requested") - -// ErrRetry is the error returned if you need to try letter by letter -var ErrRetry = errors.New("flag: retry") - -// -- bool Value -type boolValue bool - -func newBoolValue(val bool, p *bool) *boolValue { - *p = val - return (*boolValue)(p) -} - -func (b *boolValue) Set(s string) error { - v, err := strconv.ParseBool(s) - *b = boolValue(v) - return err -} - -func (b *boolValue) Get() interface{} { return bool(*b) } - -func (b *boolValue) String() string { return fmt.Sprintf("%v", *b) } - -func (b *boolValue) IsBoolFlag() bool { return true } - -// optional interface to indicate boolean flags that can be -// supplied without "=value" text -type boolFlag interface { - Value - IsBoolFlag() bool -} - -// -- int Value -type intValue int - -func newIntValue(val int, p *int) *intValue { - *p = val - return (*intValue)(p) -} - -func (i *intValue) Set(s string) error { - v, err := strconv.ParseInt(s, 0, 64) - *i = intValue(v) - return err -} - -func (i *intValue) Get() interface{} { return int(*i) } - -func (i *intValue) String() string { return fmt.Sprintf("%v", *i) } - -// -- int64 Value -type int64Value int64 - -func newInt64Value(val int64, p *int64) *int64Value { - *p = val - return (*int64Value)(p) -} - -func (i *int64Value) Set(s string) error { - v, err := strconv.ParseInt(s, 0, 64) - *i = int64Value(v) - return err -} - -func (i *int64Value) Get() interface{} { return int64(*i) } - -func (i *int64Value) String() string { return fmt.Sprintf("%v", *i) } - -// -- uint Value -type uintValue uint - -func newUintValue(val uint, p *uint) *uintValue { - *p = val - return (*uintValue)(p) -} - -func (i *uintValue) Set(s string) error { - v, err := strconv.ParseUint(s, 0, 64) - *i = uintValue(v) - return err -} - -func (i *uintValue) Get() interface{} { return uint(*i) } - -func (i *uintValue) String() string { return fmt.Sprintf("%v", *i) } - -// -- uint64 Value -type uint64Value uint64 - -func newUint64Value(val uint64, p *uint64) *uint64Value { - *p = val - return (*uint64Value)(p) -} - -func (i *uint64Value) Set(s string) error { - v, err := strconv.ParseUint(s, 0, 64) - *i = uint64Value(v) - return err -} - -func (i *uint64Value) Get() interface{} { return uint64(*i) } - -func (i *uint64Value) String() string { return fmt.Sprintf("%v", *i) } - -// -- uint16 Value -type uint16Value uint16 - -func newUint16Value(val uint16, p *uint16) *uint16Value { - *p = val - return (*uint16Value)(p) -} - -func (i *uint16Value) Set(s string) error { - v, err := strconv.ParseUint(s, 0, 16) - *i = uint16Value(v) - return err -} - -func (i *uint16Value) Get() interface{} { return uint16(*i) } - -func (i *uint16Value) String() string { return fmt.Sprintf("%v", *i) } - -// -- string Value -type stringValue string - -func newStringValue(val string, p *string) *stringValue { - *p = val - return (*stringValue)(p) -} - -func (s *stringValue) Set(val string) error { - *s = stringValue(val) - return nil -} - -func (s *stringValue) Get() interface{} { return string(*s) } - -func (s *stringValue) String() string { return string(*s) } - -// -- float64 Value -type float64Value float64 - -func newFloat64Value(val float64, p *float64) *float64Value { - *p = val - return (*float64Value)(p) -} - -func (f *float64Value) Set(s string) error { - v, err := strconv.ParseFloat(s, 64) - *f = float64Value(v) - return err -} - -func (f *float64Value) Get() interface{} { return float64(*f) } - -func (f *float64Value) String() string { return fmt.Sprintf("%v", *f) } - -// -- time.Duration Value -type durationValue time.Duration - -func newDurationValue(val time.Duration, p *time.Duration) *durationValue { - *p = val - return (*durationValue)(p) -} - -func (d *durationValue) Set(s string) error { - v, err := time.ParseDuration(s) - *d = durationValue(v) - return err -} - -func (d *durationValue) Get() interface{} { return time.Duration(*d) } - -func (d *durationValue) String() string { return (*time.Duration)(d).String() } - -// Value is the interface to the dynamic value stored in a flag. -// (The default value is represented as a string.) -// -// If a Value has an IsBoolFlag() bool method returning true, -// the command-line parser makes -name equivalent to -name=true -// rather than using the next command-line argument. -type Value interface { - String() string - Set(string) error -} - -// Getter is an interface that allows the contents of a Value to be retrieved. -// It wraps the Value interface, rather than being part of it, because it -// appeared after Go 1 and its compatibility rules. All Value types provided -// by this package satisfy the Getter interface. -type Getter interface { - Value - Get() interface{} -} - -// ErrorHandling defines how to handle flag parsing errors. -type ErrorHandling int - -// ErrorHandling strategies available when a flag parsing error occurs -const ( - ContinueOnError ErrorHandling = iota - ExitOnError - PanicOnError -) - -// A FlagSet represents a set of defined flags. The zero value of a FlagSet -// has no name and has ContinueOnError error handling. -type FlagSet struct { - // Usage is the function called when an error occurs while parsing flags. - // The field is a function (not a method) that may be changed to point to - // a custom error handler. - Usage func() - ShortUsage func() - - name string - parsed bool - actual map[string]*Flag - formal map[string]*Flag - args []string // arguments after flags - errorHandling ErrorHandling - output io.Writer // nil means stderr; use Out() accessor - nArgRequirements []nArgRequirement -} - -// A Flag represents the state of a flag. -type Flag struct { - Names []string // name as it appears on command line - Usage string // help message - Value Value // value as set - DefValue string // default value (as text); for usage message -} - -type flagSlice []string - -func (p flagSlice) Len() int { return len(p) } -func (p flagSlice) Less(i, j int) bool { - pi, pj := strings.TrimPrefix(p[i], "-"), strings.TrimPrefix(p[j], "-") - lpi, lpj := strings.ToLower(pi), strings.ToLower(pj) - if lpi != lpj { - return lpi < lpj - } - return pi < pj -} -func (p flagSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] } - -// sortFlags returns the flags as a slice in lexicographical sorted order. -func sortFlags(flags map[string]*Flag) []*Flag { - var list flagSlice - - // The sorted list is based on the first name, when flag map might use the other names. - nameMap := make(map[string]string) - - for n, f := range flags { - fName := strings.TrimPrefix(f.Names[0], "#") - nameMap[fName] = n - if len(f.Names) == 1 { - list = append(list, fName) - continue - } - - found := false - for _, name := range list { - if name == fName { - found = true - break - } - } - if !found { - list = append(list, fName) - } - } - sort.Sort(list) - result := make([]*Flag, len(list)) - for i, name := range list { - result[i] = flags[nameMap[name]] - } - return result -} - -// Name returns the name of the FlagSet. -func (fs *FlagSet) Name() string { - return fs.name -} - -// Out returns the destination for usage and error messages. -func (fs *FlagSet) Out() io.Writer { - if fs.output == nil { - return os.Stderr - } - return fs.output -} - -// SetOutput sets the destination for usage and error messages. -// If output is nil, os.Stderr is used. -func (fs *FlagSet) SetOutput(output io.Writer) { - fs.output = output -} - -// VisitAll visits the flags in lexicographical order, calling fn for each. -// It visits all flags, even those not set. -func (fs *FlagSet) VisitAll(fn func(*Flag)) { - for _, flag := range sortFlags(fs.formal) { - fn(flag) - } -} - -// VisitAll visits the command-line flags in lexicographical order, calling -// fn for each. It visits all flags, even those not set. -func VisitAll(fn func(*Flag)) { - CommandLine.VisitAll(fn) -} - -// Visit visits the flags in lexicographical order, calling fn for each. -// It visits only those flags that have been set. -func (fs *FlagSet) Visit(fn func(*Flag)) { - for _, flag := range sortFlags(fs.actual) { - fn(flag) - } -} - -// Visit visits the command-line flags in lexicographical order, calling fn -// for each. It visits only those flags that have been set. -func Visit(fn func(*Flag)) { - CommandLine.Visit(fn) -} - -// Lookup returns the Flag structure of the named flag, returning nil if none exists. -func (fs *FlagSet) Lookup(name string) *Flag { - return fs.formal[name] -} - -// IsSet indicates whether the specified flag is set in the given FlagSet -func (fs *FlagSet) IsSet(name string) bool { - return fs.actual[name] != nil -} - -// Lookup returns the Flag structure of the named command-line flag, -// returning nil if none exists. -func Lookup(name string) *Flag { - return CommandLine.formal[name] -} - -// IsSet indicates whether the specified flag was specified at all on the cmd line. -func IsSet(name string) bool { - return CommandLine.IsSet(name) -} - -type nArgRequirementType int - -// Indicator used to pass to BadArgs function -const ( - Exact nArgRequirementType = iota - Max - Min -) - -type nArgRequirement struct { - Type nArgRequirementType - N int -} - -// Require adds a requirement about the number of arguments for the FlagSet. -// The first parameter can be Exact, Max, or Min to respectively specify the exact, -// the maximum, or the minimal number of arguments required. -// The actual check is done in FlagSet.CheckArgs(). -func (fs *FlagSet) Require(nArgRequirementType nArgRequirementType, nArg int) { - fs.nArgRequirements = append(fs.nArgRequirements, nArgRequirement{nArgRequirementType, nArg}) -} - -// CheckArgs uses the requirements set by FlagSet.Require() to validate -// the number of arguments. If the requirements are not met, -// an error message string is returned. -func (fs *FlagSet) CheckArgs() (message string) { - for _, req := range fs.nArgRequirements { - var arguments string - if req.N == 1 { - arguments = "1 argument" - } else { - arguments = fmt.Sprintf("%d arguments", req.N) - } - - str := func(kind string) string { - return fmt.Sprintf("%q requires %s%s", fs.name, kind, arguments) - } - - switch req.Type { - case Exact: - if fs.NArg() != req.N { - return str("") - } - case Max: - if fs.NArg() > req.N { - return str("a maximum of ") - } - case Min: - if fs.NArg() < req.N { - return str("a minimum of ") - } - } - } - return "" -} - -// Set sets the value of the named flag. -func (fs *FlagSet) Set(name, value string) error { - flag, ok := fs.formal[name] - if !ok { - return fmt.Errorf("no such flag -%v", name) - } - if err := flag.Value.Set(value); err != nil { - return err - } - if fs.actual == nil { - fs.actual = make(map[string]*Flag) - } - fs.actual[name] = flag - return nil -} - -// Set sets the value of the named command-line flag. -func Set(name, value string) error { - return CommandLine.Set(name, value) -} - -// isZeroValue guesses whether the string represents the zero -// value for a flag. It is not accurate but in practice works OK. -func isZeroValue(value string) bool { - switch value { - case "false": - return true - case "": - return true - case "0": - return true - } - return false -} - -// PrintDefaults prints, to standard error unless configured -// otherwise, the default values of all defined flags in the set. -func (fs *FlagSet) PrintDefaults() { - writer := tabwriter.NewWriter(fs.Out(), 20, 1, 3, ' ', 0) - home, _ := os.UserHomeDir() - - // Don't substitute when HOME is / - if runtime.GOOS != "windows" && home == "/" { - home = "" - } - - // Add a blank line between cmd description and list of options - if fs.FlagCount() > 0 { - fmt.Fprintln(writer, "") - } - - fs.VisitAll(func(flag *Flag) { - names := []string{} - for _, name := range flag.Names { - if name[0] != '#' { - names = append(names, name) - } - } - if len(names) > 0 && len(flag.Usage) > 0 { - val := flag.DefValue - - if home != "" && strings.HasPrefix(val, home) { - val = getShortcutString() + val[len(home):] - } - - if isZeroValue(val) { - format := " -%s" - fmt.Fprintf(writer, format, strings.Join(names, ", -")) - } else { - format := " -%s=%s" - fmt.Fprintf(writer, format, strings.Join(names, ", -"), val) - } - for _, line := range strings.Split(flag.Usage, "\n") { - fmt.Fprintln(writer, "\t", line) - } - } - }) - writer.Flush() -} - -func getShortcutString() string { - if runtime.GOOS == "windows" { - return "%USERPROFILE%" - } - return "~" -} - -// PrintDefaults prints to standard error the default values of all defined command-line flags. -func PrintDefaults() { - CommandLine.PrintDefaults() -} - -// defaultUsage is the default function to print a usage message. -func defaultUsage(fs *FlagSet) { - if fs.name == "" { - fmt.Fprintf(fs.Out(), "Usage:\n") - } else { - fmt.Fprintf(fs.Out(), "Usage of %s:\n", fs.name) - } - fs.PrintDefaults() -} - -// NOTE: Usage is not just defaultUsage(CommandLine) -// because it serves (via godoc flag Usage) as the example -// for how to write your own usage function. - -// Usage prints to standard error a usage message documenting all defined command-line flags. -// The function is a variable that may be changed to point to a custom function. -var Usage = func() { - fmt.Fprintf(CommandLine.Out(), "Usage of %s:\n", os.Args[0]) - PrintDefaults() -} - -// ShortUsage prints to standard error a usage message documenting the standard command layout -// The function is a variable that may be changed to point to a custom function. -var ShortUsage = func() { - fmt.Fprintf(CommandLine.output, "Usage of %s:\n", os.Args[0]) -} - -// FlagCount returns the number of flags that have been defined. -func (fs *FlagSet) FlagCount() int { return len(sortFlags(fs.formal)) } - -// FlagCountUndeprecated returns the number of undeprecated flags that have been defined. -func (fs *FlagSet) FlagCountUndeprecated() int { - count := 0 - for _, flag := range sortFlags(fs.formal) { - for _, name := range flag.Names { - if name[0] != '#' { - count++ - break - } - } - } - return count -} - -// NFlag returns the number of flags that have been set. -func (fs *FlagSet) NFlag() int { return len(fs.actual) } - -// NFlag returns the number of command-line flags that have been set. -func NFlag() int { return len(CommandLine.actual) } - -// Arg returns the i'th argument. Arg(0) is the first remaining argument -// after flags have been processed. -func (fs *FlagSet) Arg(i int) string { - if i < 0 || i >= len(fs.args) { - return "" - } - return fs.args[i] -} - -// Arg returns the i'th command-line argument. Arg(0) is the first remaining argument -// after flags have been processed. -func Arg(i int) string { - return CommandLine.Arg(i) -} - -// NArg is the number of arguments remaining after flags have been processed. -func (fs *FlagSet) NArg() int { return len(fs.args) } - -// NArg is the number of arguments remaining after flags have been processed. -func NArg() int { return len(CommandLine.args) } - -// Args returns the non-flag arguments. -func (fs *FlagSet) Args() []string { return fs.args } - -// Args returns the non-flag command-line arguments. -func Args() []string { return CommandLine.args } - -// BoolVar defines a bool flag with specified name, default value, and usage string. -// The argument p points to a bool variable in which to store the value of the flag. -func (fs *FlagSet) BoolVar(p *bool, names []string, value bool, usage string) { - fs.Var(newBoolValue(value, p), names, usage) -} - -// BoolVar defines a bool flag with specified name, default value, and usage string. -// The argument p points to a bool variable in which to store the value of the flag. -func BoolVar(p *bool, names []string, value bool, usage string) { - CommandLine.Var(newBoolValue(value, p), names, usage) -} - -// Bool defines a bool flag with specified name, default value, and usage string. -// The return value is the address of a bool variable that stores the value of the flag. -func (fs *FlagSet) Bool(names []string, value bool, usage string) *bool { - p := new(bool) - fs.BoolVar(p, names, value, usage) - return p -} - -// Bool defines a bool flag with specified name, default value, and usage string. -// The return value is the address of a bool variable that stores the value of the flag. -func Bool(names []string, value bool, usage string) *bool { - return CommandLine.Bool(names, value, usage) -} - -// IntVar defines an int flag with specified name, default value, and usage string. -// The argument p points to an int variable in which to store the value of the flag. -func (fs *FlagSet) IntVar(p *int, names []string, value int, usage string) { - fs.Var(newIntValue(value, p), names, usage) -} - -// IntVar defines an int flag with specified name, default value, and usage string. -// The argument p points to an int variable in which to store the value of the flag. -func IntVar(p *int, names []string, value int, usage string) { - CommandLine.Var(newIntValue(value, p), names, usage) -} - -// Int defines an int flag with specified name, default value, and usage string. -// The return value is the address of an int variable that stores the value of the flag. -func (fs *FlagSet) Int(names []string, value int, usage string) *int { - p := new(int) - fs.IntVar(p, names, value, usage) - return p -} - -// Int defines an int flag with specified name, default value, and usage string. -// The return value is the address of an int variable that stores the value of the flag. -func Int(names []string, value int, usage string) *int { - return CommandLine.Int(names, value, usage) -} - -// Int64Var defines an int64 flag with specified name, default value, and usage string. -// The argument p points to an int64 variable in which to store the value of the flag. -func (fs *FlagSet) Int64Var(p *int64, names []string, value int64, usage string) { - fs.Var(newInt64Value(value, p), names, usage) -} - -// Int64Var defines an int64 flag with specified name, default value, and usage string. -// The argument p points to an int64 variable in which to store the value of the flag. -func Int64Var(p *int64, names []string, value int64, usage string) { - CommandLine.Var(newInt64Value(value, p), names, usage) -} - -// Int64 defines an int64 flag with specified name, default value, and usage string. -// The return value is the address of an int64 variable that stores the value of the flag. -func (fs *FlagSet) Int64(names []string, value int64, usage string) *int64 { - p := new(int64) - fs.Int64Var(p, names, value, usage) - return p -} - -// Int64 defines an int64 flag with specified name, default value, and usage string. -// The return value is the address of an int64 variable that stores the value of the flag. -func Int64(names []string, value int64, usage string) *int64 { - return CommandLine.Int64(names, value, usage) -} - -// UintVar defines a uint flag with specified name, default value, and usage string. -// The argument p points to a uint variable in which to store the value of the flag. -func (fs *FlagSet) UintVar(p *uint, names []string, value uint, usage string) { - fs.Var(newUintValue(value, p), names, usage) -} - -// UintVar defines a uint flag with specified name, default value, and usage string. -// The argument p points to a uint variable in which to store the value of the flag. -func UintVar(p *uint, names []string, value uint, usage string) { - CommandLine.Var(newUintValue(value, p), names, usage) -} - -// Uint defines a uint flag with specified name, default value, and usage string. -// The return value is the address of a uint variable that stores the value of the flag. -func (fs *FlagSet) Uint(names []string, value uint, usage string) *uint { - p := new(uint) - fs.UintVar(p, names, value, usage) - return p -} - -// Uint defines a uint flag with specified name, default value, and usage string. -// The return value is the address of a uint variable that stores the value of the flag. -func Uint(names []string, value uint, usage string) *uint { - return CommandLine.Uint(names, value, usage) -} - -// Uint64Var defines a uint64 flag with specified name, default value, and usage string. -// The argument p points to a uint64 variable in which to store the value of the flag. -func (fs *FlagSet) Uint64Var(p *uint64, names []string, value uint64, usage string) { - fs.Var(newUint64Value(value, p), names, usage) -} - -// Uint64Var defines a uint64 flag with specified name, default value, and usage string. -// The argument p points to a uint64 variable in which to store the value of the flag. -func Uint64Var(p *uint64, names []string, value uint64, usage string) { - CommandLine.Var(newUint64Value(value, p), names, usage) -} - -// Uint64 defines a uint64 flag with specified name, default value, and usage string. -// The return value is the address of a uint64 variable that stores the value of the flag. -func (fs *FlagSet) Uint64(names []string, value uint64, usage string) *uint64 { - p := new(uint64) - fs.Uint64Var(p, names, value, usage) - return p -} - -// Uint64 defines a uint64 flag with specified name, default value, and usage string. -// The return value is the address of a uint64 variable that stores the value of the flag. -func Uint64(names []string, value uint64, usage string) *uint64 { - return CommandLine.Uint64(names, value, usage) -} - -// Uint16Var defines a uint16 flag with specified name, default value, and usage string. -// The argument p points to a uint16 variable in which to store the value of the flag. -func (fs *FlagSet) Uint16Var(p *uint16, names []string, value uint16, usage string) { - fs.Var(newUint16Value(value, p), names, usage) -} - -// Uint16Var defines a uint16 flag with specified name, default value, and usage string. -// The argument p points to a uint16 variable in which to store the value of the flag. -func Uint16Var(p *uint16, names []string, value uint16, usage string) { - CommandLine.Var(newUint16Value(value, p), names, usage) -} - -// Uint16 defines a uint16 flag with specified name, default value, and usage string. -// The return value is the address of a uint16 variable that stores the value of the flag. -func (fs *FlagSet) Uint16(names []string, value uint16, usage string) *uint16 { - p := new(uint16) - fs.Uint16Var(p, names, value, usage) - return p -} - -// Uint16 defines a uint16 flag with specified name, default value, and usage string. -// The return value is the address of a uint16 variable that stores the value of the flag. -func Uint16(names []string, value uint16, usage string) *uint16 { - return CommandLine.Uint16(names, value, usage) -} - -// StringVar defines a string flag with specified name, default value, and usage string. -// The argument p points to a string variable in which to store the value of the flag. -func (fs *FlagSet) StringVar(p *string, names []string, value string, usage string) { - fs.Var(newStringValue(value, p), names, usage) -} - -// StringVar defines a string flag with specified name, default value, and usage string. -// The argument p points to a string variable in which to store the value of the flag. -func StringVar(p *string, names []string, value string, usage string) { - CommandLine.Var(newStringValue(value, p), names, usage) -} - -// String defines a string flag with specified name, default value, and usage string. -// The return value is the address of a string variable that stores the value of the flag. -func (fs *FlagSet) String(names []string, value string, usage string) *string { - p := new(string) - fs.StringVar(p, names, value, usage) - return p -} - -// String defines a string flag with specified name, default value, and usage string. -// The return value is the address of a string variable that stores the value of the flag. -func String(names []string, value string, usage string) *string { - return CommandLine.String(names, value, usage) -} - -// Float64Var defines a float64 flag with specified name, default value, and usage string. -// The argument p points to a float64 variable in which to store the value of the flag. -func (fs *FlagSet) Float64Var(p *float64, names []string, value float64, usage string) { - fs.Var(newFloat64Value(value, p), names, usage) -} - -// Float64Var defines a float64 flag with specified name, default value, and usage string. -// The argument p points to a float64 variable in which to store the value of the flag. -func Float64Var(p *float64, names []string, value float64, usage string) { - CommandLine.Var(newFloat64Value(value, p), names, usage) -} - -// Float64 defines a float64 flag with specified name, default value, and usage string. -// The return value is the address of a float64 variable that stores the value of the flag. -func (fs *FlagSet) Float64(names []string, value float64, usage string) *float64 { - p := new(float64) - fs.Float64Var(p, names, value, usage) - return p -} - -// Float64 defines a float64 flag with specified name, default value, and usage string. -// The return value is the address of a float64 variable that stores the value of the flag. -func Float64(names []string, value float64, usage string) *float64 { - return CommandLine.Float64(names, value, usage) -} - -// DurationVar defines a time.Duration flag with specified name, default value, and usage string. -// The argument p points to a time.Duration variable in which to store the value of the flag. -func (fs *FlagSet) DurationVar(p *time.Duration, names []string, value time.Duration, usage string) { - fs.Var(newDurationValue(value, p), names, usage) -} - -// DurationVar defines a time.Duration flag with specified name, default value, and usage string. -// The argument p points to a time.Duration variable in which to store the value of the flag. -func DurationVar(p *time.Duration, names []string, value time.Duration, usage string) { - CommandLine.Var(newDurationValue(value, p), names, usage) -} - -// Duration defines a time.Duration flag with specified name, default value, and usage string. -// The return value is the address of a time.Duration variable that stores the value of the flag. -func (fs *FlagSet) Duration(names []string, value time.Duration, usage string) *time.Duration { - p := new(time.Duration) - fs.DurationVar(p, names, value, usage) - return p -} - -// Duration defines a time.Duration flag with specified name, default value, and usage string. -// The return value is the address of a time.Duration variable that stores the value of the flag. -func Duration(names []string, value time.Duration, usage string) *time.Duration { - return CommandLine.Duration(names, value, usage) -} - -// Var defines a flag with the specified name and usage string. The type and -// value of the flag are represented by the first argument, of type Value, which -// typically holds a user-defined implementation of Value. For instance, the -// caller could create a flag that turns a comma-separated string into a slice -// of strings by giving the slice the methods of Value; in particular, Set would -// decompose the comma-separated string into the slice. -func (fs *FlagSet) Var(value Value, names []string, usage string) { - // Remember the default value as a string; it won't change. - flag := &Flag{names, usage, value, value.String()} - for _, name := range names { - name = strings.TrimPrefix(name, "#") - _, alreadythere := fs.formal[name] - if alreadythere { - var msg string - if fs.name == "" { - msg = fmt.Sprintf("flag redefined: %s", name) - } else { - msg = fmt.Sprintf("%s flag redefined: %s", fs.name, name) - } - fmt.Fprintln(fs.Out(), msg) - panic(msg) // Happens only if flags are declared with identical names - } - if fs.formal == nil { - fs.formal = make(map[string]*Flag) - } - fs.formal[name] = flag - } -} - -// Var defines a flag with the specified name and usage string. The type and -// value of the flag are represented by the first argument, of type Value, which -// typically holds a user-defined implementation of Value. For instance, the -// caller could create a flag that turns a comma-separated string into a slice -// of strings by giving the slice the methods of Value; in particular, Set would -// decompose the comma-separated string into the slice. -func Var(value Value, names []string, usage string) { - CommandLine.Var(value, names, usage) -} - -// failf prints to standard error a formatted error and usage message and -// returns the error. -func (fs *FlagSet) failf(format string, a ...interface{}) error { - err := fmt.Errorf(format, a...) - fmt.Fprintln(fs.Out(), err) - if os.Args[0] == fs.name { - fmt.Fprintf(fs.Out(), "See '%s --help'.\n", os.Args[0]) - } else { - fmt.Fprintf(fs.Out(), "See '%s %s --help'.\n", os.Args[0], fs.name) - } - return err -} - -// usage calls the Usage method for the flag set, or the usage function if -// the flag set is CommandLine. -func (fs *FlagSet) usage() { - if fs == CommandLine { - Usage() - } else if fs.Usage == nil { - defaultUsage(fs) - } else { - fs.Usage() - } -} - -func trimQuotes(str string) string { - if len(str) == 0 { - return str - } - type quote struct { - start, end byte - } - - // All valid quote types. - quotes := []quote{ - // Double quotes - { - start: '"', - end: '"', - }, - - // Single quotes - { - start: '\'', - end: '\'', - }, - } - - for _, quote := range quotes { - // Only strip if outermost match. - if str[0] == quote.start && str[len(str)-1] == quote.end { - str = str[1 : len(str)-1] - break - } - } - - return str -} - -// parseOne parses one flag. It reports whether a flag was seen. -func (fs *FlagSet) parseOne() (bool, string, error) { - if len(fs.args) == 0 { - return false, "", nil - } - s := fs.args[0] - if len(s) == 0 || s[0] != '-' || len(s) == 1 { - return false, "", nil - } - if s[1] == '-' && len(s) == 2 { // "--" terminates the flags - fs.args = fs.args[1:] - return false, "", nil - } - name := s[1:] - if len(name) == 0 || name[0] == '=' { - return false, "", fs.failf("bad flag syntax: %s", s) - } - - // it's a flag. does it have an argument? - fs.args = fs.args[1:] - hasValue := false - value := "" - if i := strings.Index(name, "="); i != -1 { - value = trimQuotes(name[i+1:]) - hasValue = true - name = name[:i] - } - - m := fs.formal - flag, alreadythere := m[name] // BUG - if !alreadythere { - if name == "-help" || name == "help" || name == "h" { // special case for nice help message. - fs.usage() - return false, "", ErrHelp - } - if len(name) > 0 && name[0] == '-' { - return false, "", fs.failf("flag provided but not defined: -%s", name) - } - return false, name, ErrRetry - } - if fv, ok := flag.Value.(boolFlag); ok && fv.IsBoolFlag() { // special case: doesn't need an arg - if hasValue { - if err := fv.Set(value); err != nil { - return false, "", fs.failf("invalid boolean value %q for -%s: %v", value, name, err) - } - } else { - fv.Set("true") - } - } else { - // It must have a value, which might be the next argument. - if !hasValue && len(fs.args) > 0 { - // value is the next arg - hasValue = true - value, fs.args = fs.args[0], fs.args[1:] - } - if !hasValue { - return false, "", fs.failf("flag needs an argument: -%s", name) - } - if err := flag.Value.Set(value); err != nil { - return false, "", fs.failf("invalid value %q for flag -%s: %v", value, name, err) - } - } - if fs.actual == nil { - fs.actual = make(map[string]*Flag) - } - fs.actual[name] = flag - for i, n := range flag.Names { - if n == fmt.Sprintf("#%s", name) { - replacement := "" - for j := i; j < len(flag.Names); j++ { - if flag.Names[j][0] != '#' { - replacement = flag.Names[j] - break - } - } - if replacement != "" { - fmt.Fprintf(fs.Out(), "Warning: '-%s' is deprecated, it will be replaced by '-%s' soon. See usage.\n", name, replacement) - } else { - fmt.Fprintf(fs.Out(), "Warning: '-%s' is deprecated, it will be removed soon. See usage.\n", name) - } - } - } - return true, "", nil -} - -// Parse parses flag definitions from the argument list, which should not -// include the command name. Must be called after all flags in the FlagSet -// are defined and before flags are accessed by the program. -// The return value will be ErrHelp if -help was set but not defined. -func (fs *FlagSet) Parse(arguments []string) error { - fs.parsed = true - fs.args = arguments - for { - seen, name, err := fs.parseOne() - if seen { - continue - } - if err == nil { - break - } - if err == ErrRetry { - if len(name) > 1 { - err = nil - for _, letter := range strings.Split(name, "") { - fs.args = append([]string{"-" + letter}, fs.args...) - seen2, _, err2 := fs.parseOne() - if seen2 { - continue - } - if err2 != nil { - err = fs.failf("flag provided but not defined: -%s", name) - break - } - } - if err == nil { - continue - } - } else { - err = fs.failf("flag provided but not defined: -%s", name) - } - } - switch fs.errorHandling { - case ContinueOnError: - return err - case ExitOnError: - os.Exit(125) - case PanicOnError: - panic(err) - } - } - return nil -} - -// ParseFlags is a utility function that adds a help flag if withHelp is true, -// calls fs.Parse(args) and prints a relevant error message if there are -// incorrect number of arguments. It returns error only if error handling is -// set to ContinueOnError and parsing fails. If error handling is set to -// ExitOnError, it's safe to ignore the return value. -func (fs *FlagSet) ParseFlags(args []string, withHelp bool) error { - var help *bool - if withHelp { - help = fs.Bool([]string{"#help", "-help"}, false, "Print usage") - } - if err := fs.Parse(args); err != nil { - return err - } - if help != nil && *help { - fs.SetOutput(os.Stdout) - fs.Usage() - os.Exit(0) - } - if str := fs.CheckArgs(); str != "" { - fs.SetOutput(os.Stderr) - fs.ReportError(str, withHelp) - fs.ShortUsage() - os.Exit(1) - } - return nil -} - -// ReportError is a utility method that prints a user-friendly message -// containing the error that occurred during parsing and a suggestion to get help -func (fs *FlagSet) ReportError(str string, withHelp bool) { - if withHelp { - if os.Args[0] == fs.Name() { - str += ".\nSee '" + os.Args[0] + " --help'" - } else { - str += ".\nSee '" + os.Args[0] + " " + fs.Name() + " --help'" - } - } - fmt.Fprintf(fs.Out(), "%s: %s.\n", os.Args[0], str) -} - -// Parsed reports whether fs.Parse has been called. -func (fs *FlagSet) Parsed() bool { - return fs.parsed -} - -// Parse parses the command-line flags from os.Args[1:]. Must be called -// after all flags are defined and before flags are accessed by the program. -func Parse() { - // Ignore errors; CommandLine is set for ExitOnError. - CommandLine.Parse(os.Args[1:]) -} - -// Parsed returns true if the command-line flags have been parsed. -func Parsed() bool { - return CommandLine.Parsed() -} - -// CommandLine is the default set of command-line flags, parsed from os.Args. -// The top-level functions such as BoolVar, Arg, and on are wrappers for the -// methods of CommandLine. -var CommandLine = NewFlagSet(os.Args[0], ExitOnError) - -// NewFlagSet returns a new, empty flag set with the specified name and -// error handling property. -func NewFlagSet(name string, errorHandling ErrorHandling) *FlagSet { - f := &FlagSet{ - name: name, - errorHandling: errorHandling, - } - return f -} - -// Init sets the name and error handling property for a flag set. -// By default, the zero FlagSet uses an empty name and the -// ContinueOnError error handling policy. -func (fs *FlagSet) Init(name string, errorHandling ErrorHandling) { - fs.name = name - fs.errorHandling = errorHandling -} - -type mergeVal struct { - Value - key string - fset *FlagSet -} - -func (v mergeVal) Set(s string) error { - return v.fset.Set(v.key, s) -} - -func (v mergeVal) IsBoolFlag() bool { - if b, ok := v.Value.(boolFlag); ok { - return b.IsBoolFlag() - } - return false -} - -// Name returns the name of a mergeVal. -// If the original value had a name, return the original name, -// otherwise, return the key assigned to this mergeVal. -func (v mergeVal) Name() string { - type namedValue interface { - Name() string - } - if nVal, ok := v.Value.(namedValue); ok { - return nVal.Name() - } - return v.key -} - -// Merge is an helper function that merges n FlagSets into a single dest FlagSet -// In case of name collision between the flagsets it will apply -// the destination FlagSet's errorHandling behavior. -func Merge(dest *FlagSet, flagsets ...*FlagSet) error { - for _, fset := range flagsets { - if fset.formal == nil { - continue - } - for k, f := range fset.formal { - if _, ok := dest.formal[k]; ok { - var err error - if fset.name == "" { - err = fmt.Errorf("flag redefined: %s", k) - } else { - err = fmt.Errorf("%s flag redefined: %s", fset.name, k) - } - fmt.Fprintln(fset.Out(), err.Error()) - // Happens only if flags are declared with identical names - switch dest.errorHandling { - case ContinueOnError: - return err - case ExitOnError: - os.Exit(2) - case PanicOnError: - panic(err) - } - } - newF := *f - newF.Value = mergeVal{f.Value, k, fset} - if dest.formal == nil { - dest.formal = make(map[string]*Flag) - } - dest.formal[k] = &newF - } - } - return nil -} - -// IsEmpty reports if the FlagSet is actually empty. -func (fs *FlagSet) IsEmpty() bool { - return len(fs.actual) == 0 -} - -// ListOpts holds a list of values and a validation function. -type ListOpts struct { - values *[]string - validator func(val string) (string, error) -} - -// NewListOpts creates a new ListOpts with the specified validator. -func NewListOpts(validator func(val string) (string, error)) ListOpts { - var values []string - return ListOpts{ - values: &values, - validator: validator, - } -} - -func (opts *ListOpts) String() string { - if len(*opts.values) == 0 { - return "" - } - return fmt.Sprintf("%v", *opts.values) -} - -// Set validates if needed the input value and adds it to the -// internal slice. -func (opts *ListOpts) Set(value string) error { - if opts.validator != nil { - v, err := opts.validator(value) - if err != nil { - return err - } - value = v - } - *opts.values = append(*opts.values, value) - return nil -} - -// GetAll returns the values of slice. -func (opts *ListOpts) GetAll() []string { - return *opts.values -} diff --git a/libnetwork/client/mflag/flag_test.go b/libnetwork/client/mflag/flag_test.go deleted file mode 100644 index 1a9f67b684..0000000000 --- a/libnetwork/client/mflag/flag_test.go +++ /dev/null @@ -1,527 +0,0 @@ -// Copyright 2014-2016 The Docker & Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package mflag - -import ( - "bytes" - "fmt" - "os" - "sort" - "strings" - "testing" - "time" - - _ "github.com/docker/docker/libnetwork/testutils" -) - -// ResetForTesting clears all flag state and sets the usage function as directed. -// After calling ResetForTesting, parse errors in flag handling will not -// exit the program. -func ResetForTesting(usage func()) { - CommandLine = NewFlagSet(os.Args[0], ContinueOnError) - Usage = usage -} -func boolString(s string) string { - if s == "0" { - return "false" - } - return "true" -} - -func TestEverything(t *testing.T) { - ResetForTesting(nil) - Bool([]string{"test_bool"}, false, "bool value") - Int([]string{"test_int"}, 0, "int value") - Int64([]string{"test_int64"}, 0, "int64 value") - Uint([]string{"test_uint"}, 0, "uint value") - Uint64([]string{"test_uint64"}, 0, "uint64 value") - String([]string{"test_string"}, "0", "string value") - Float64([]string{"test_float64"}, 0, "float64 value") - Duration([]string{"test_duration"}, 0, "time.Duration value") - - m := make(map[string]*Flag) - desired := "0" - visitor := func(f *Flag) { - for _, name := range f.Names { - if len(name) > 5 && name[0:5] == "test_" { - m[name] = f - ok := false - switch { - case f.Value.String() == desired: - ok = true - case name == "test_bool" && f.Value.String() == boolString(desired): - ok = true - case name == "test_duration" && f.Value.String() == desired+"s": - ok = true - } - if !ok { - t.Error("Visit: bad value", f.Value.String(), "for", name) - } - } - } - } - VisitAll(visitor) - if len(m) != 8 { - t.Error("VisitAll misses some flags") - for k, v := range m { - t.Log(k, *v) - } - } - m = make(map[string]*Flag) - Visit(visitor) - if len(m) != 0 { - t.Error("Visit sees unset flags") - for k, v := range m { - t.Log(k, *v) - } - } - // Now set all flags - Set("test_bool", "true") - Set("test_int", "1") - Set("test_int64", "1") - Set("test_uint", "1") - Set("test_uint64", "1") - Set("test_string", "1") - Set("test_float64", "1") - Set("test_duration", "1s") - desired = "1" - Visit(visitor) - if len(m) != 8 { - t.Error("Visit fails after set") - for k, v := range m { - t.Log(k, *v) - } - } - // Now test they're visited in sort order. - var flagNames []string - Visit(func(f *Flag) { - flagNames = append(flagNames, f.Names...) - }) - if !sort.StringsAreSorted(flagNames) { - t.Errorf("flag names not sorted: %v", flagNames) - } -} - -func TestGet(t *testing.T) { - ResetForTesting(nil) - Bool([]string{"test_bool"}, true, "bool value") - Int([]string{"test_int"}, 1, "int value") - Int64([]string{"test_int64"}, 2, "int64 value") - Uint([]string{"test_uint"}, 3, "uint value") - Uint64([]string{"test_uint64"}, 4, "uint64 value") - String([]string{"test_string"}, "5", "string value") - Float64([]string{"test_float64"}, 6, "float64 value") - Duration([]string{"test_duration"}, 7, "time.Duration value") - - visitor := func(f *Flag) { - for _, name := range f.Names { - if len(name) > 5 && name[0:5] == "test_" { - g, ok := f.Value.(Getter) - if !ok { - t.Errorf("Visit: value does not satisfy Getter: %T", f.Value) - return - } - switch name { - case "test_bool": - ok = g.Get() == true - case "test_int": - ok = g.Get() == int(1) - case "test_int64": - ok = g.Get() == int64(2) - case "test_uint": - ok = g.Get() == uint(3) - case "test_uint64": - ok = g.Get() == uint64(4) - case "test_string": - ok = g.Get() == "5" - case "test_float64": - ok = g.Get() == float64(6) - case "test_duration": - ok = g.Get() == time.Duration(7) - } - if !ok { - t.Errorf("Visit: bad value %T(%v) for %s", g.Get(), g.Get(), name) - } - } - } - } - VisitAll(visitor) -} - -func testParse(f *FlagSet, t *testing.T) { - if f.Parsed() { - t.Error("f.Parse() = true before Parse") - } - boolFlag := f.Bool([]string{"bool"}, false, "bool value") - bool2Flag := f.Bool([]string{"bool2"}, false, "bool2 value") - f.Bool([]string{"bool3"}, false, "bool3 value") - bool4Flag := f.Bool([]string{"bool4"}, false, "bool4 value") - intFlag := f.Int([]string{"-int"}, 0, "int value") - int64Flag := f.Int64([]string{"-int64"}, 0, "int64 value") - uintFlag := f.Uint([]string{"uint"}, 0, "uint value") - uint64Flag := f.Uint64([]string{"-uint64"}, 0, "uint64 value") - stringFlag := f.String([]string{"string"}, "0", "string value") - f.String([]string{"string2"}, "0", "string2 value") - singleQuoteFlag := f.String([]string{"squote"}, "", "single quoted value") - doubleQuoteFlag := f.String([]string{"dquote"}, "", "double quoted value") - mixedQuoteFlag := f.String([]string{"mquote"}, "", "mixed quoted value") - mixed2QuoteFlag := f.String([]string{"mquote2"}, "", "mixed2 quoted value") - nestedQuoteFlag := f.String([]string{"nquote"}, "", "nested quoted value") - nested2QuoteFlag := f.String([]string{"nquote2"}, "", "nested2 quoted value") - float64Flag := f.Float64([]string{"float64"}, 0, "float64 value") - durationFlag := f.Duration([]string{"duration"}, 5*time.Second, "time.Duration value") - extra := "one-extra-argument" - args := []string{ - "-bool", - "-bool2=true", - "-bool4=false", - "--int", "22", - "--int64", "0x23", - "-uint", "24", - "--uint64", "25", - "-string", "hello", - "-squote='single'", - `-dquote="double"`, - `-mquote='mixed"`, - `-mquote2="mixed2'`, - `-nquote="'single nested'"`, - `-nquote2='"double nested"'`, - "-float64", "2718e28", - "-duration", "2m", - extra, - } - if err := f.Parse(args); err != nil { - t.Fatal(err) - } - if !f.Parsed() { - t.Error("f.Parse() = false after Parse") - } - if *boolFlag != true { - t.Error("bool flag should be true, is ", *boolFlag) - } - if *bool2Flag != true { - t.Error("bool2 flag should be true, is ", *bool2Flag) - } - if !f.IsSet("bool2") { - t.Error("bool2 should be marked as set") - } - if f.IsSet("bool3") { - t.Error("bool3 should not be marked as set") - } - if !f.IsSet("bool4") { - t.Error("bool4 should be marked as set") - } - if *bool4Flag != false { - t.Error("bool4 flag should be false, is ", *bool4Flag) - } - if *intFlag != 22 { - t.Error("int flag should be 22, is ", *intFlag) - } - if *int64Flag != 0x23 { - t.Error("int64 flag should be 0x23, is ", *int64Flag) - } - if *uintFlag != 24 { - t.Error("uint flag should be 24, is ", *uintFlag) - } - if *uint64Flag != 25 { - t.Error("uint64 flag should be 25, is ", *uint64Flag) - } - if *stringFlag != "hello" { - t.Error("string flag should be `hello`, is ", *stringFlag) - } - if !f.IsSet("string") { - t.Error("string flag should be marked as set") - } - if f.IsSet("string2") { - t.Error("string2 flag should not be marked as set") - } - if *singleQuoteFlag != "single" { - t.Error("single quote string flag should be `single`, is ", *singleQuoteFlag) - } - if *doubleQuoteFlag != "double" { - t.Error("double quote string flag should be `double`, is ", *doubleQuoteFlag) - } - if *mixedQuoteFlag != `'mixed"` { - t.Error("mixed quote string flag should be `'mixed\"`, is ", *mixedQuoteFlag) - } - if *mixed2QuoteFlag != `"mixed2'` { - t.Error("mixed2 quote string flag should be `\"mixed2'`, is ", *mixed2QuoteFlag) - } - if *nestedQuoteFlag != "'single nested'" { - t.Error("nested quote string flag should be `'single nested'`, is ", *nestedQuoteFlag) - } - if *nested2QuoteFlag != `"double nested"` { - t.Error("double quote string flag should be `\"double nested\"`, is ", *nested2QuoteFlag) - } - if *float64Flag != 2718e28 { - t.Error("float64 flag should be 2718e28, is ", *float64Flag) - } - if *durationFlag != 2*time.Minute { - t.Error("duration flag should be 2m, is ", *durationFlag) - } - if len(f.Args()) != 1 { - t.Error("expected one argument, got", len(f.Args())) - } else if f.Args()[0] != extra { - t.Errorf("expected argument %q got %q", extra, f.Args()[0]) - } -} - -func testPanic(f *FlagSet, t *testing.T) { - f.Int([]string{"-int"}, 0, "int value") - if f.Parsed() { - t.Error("f.Parse() = true before Parse") - } - args := []string{ - "-int", "21", - } - f.Parse(args) -} - -func TestParsePanic(t *testing.T) { - ResetForTesting(func() {}) - testPanic(CommandLine, t) -} - -func TestParse(t *testing.T) { - ResetForTesting(func() { t.Error("bad parse") }) - testParse(CommandLine, t) -} - -func TestFlagSetParse(t *testing.T) { - testParse(NewFlagSet("test", ContinueOnError), t) -} - -// Declare a user-defined flag type. -type flagVar []string - -func (f *flagVar) String() string { - return fmt.Sprint([]string(*f)) -} - -func (f *flagVar) Set(value string) error { - *f = append(*f, value) - return nil -} - -func TestUserDefined(t *testing.T) { - var flags FlagSet - flags.Init("test", ContinueOnError) - var v flagVar - flags.Var(&v, []string{"v"}, "usage") - if err := flags.Parse([]string{"-v", "1", "-v", "2", "-v=3"}); err != nil { - t.Error(err) - } - if len(v) != 3 { - t.Fatal("expected 3 args; got ", len(v)) - } - expect := "[1 2 3]" - if v.String() != expect { - t.Errorf("expected value %q got %q", expect, v.String()) - } -} - -// Declare a user-defined boolean flag type. -type boolFlagVar struct { - count int -} - -func (b *boolFlagVar) String() string { - return fmt.Sprintf("%d", b.count) -} - -func (b *boolFlagVar) Set(value string) error { - if value == "true" { - b.count++ - } - return nil -} - -func (b *boolFlagVar) IsBoolFlag() bool { - return b.count < 4 -} - -func TestUserDefinedBool(t *testing.T) { - var flags FlagSet - flags.Init("test", ContinueOnError) - var b boolFlagVar - var err error - flags.Var(&b, []string{"b"}, "usage") - if err = flags.Parse([]string{"-b", "-b", "-b", "-b=true", "-b=false", "-b", "barg", "-b"}); err != nil { - if b.count < 4 { - t.Error(err) - } - } - - if b.count != 4 { - t.Errorf("want: %d; got: %d", 4, b.count) - } - - if err == nil { - t.Error("expected error; got none") - } -} - -func TestSetOutput(t *testing.T) { - var flags FlagSet - var buf bytes.Buffer - flags.SetOutput(&buf) - flags.Init("test", ContinueOnError) - flags.Parse([]string{"-unknown"}) - if out := buf.String(); !strings.Contains(out, "-unknown") { - t.Logf("expected output mentioning unknown; got %q", out) - } -} - -// This tests that one can reset the flags. This still works but not well, and is -// superseded by FlagSet. -func TestChangingArgs(t *testing.T) { - ResetForTesting(func() { t.Fatal("bad parse") }) - oldArgs := os.Args - defer func() { os.Args = oldArgs }() - os.Args = []string{"cmd", "-before", "subcmd", "-after", "args"} - before := Bool([]string{"before"}, false, "") - if err := CommandLine.Parse(os.Args[1:]); err != nil { - t.Fatal(err) - } - cmd := Arg(0) - os.Args = Args() - after := Bool([]string{"after"}, false, "") - Parse() - args := Args() - - if !*before || cmd != "subcmd" || !*after || len(args) != 1 || args[0] != "args" { - t.Fatalf("expected true subcmd true [args] got %v %v %v %v", *before, cmd, *after, args) - } -} - -// Test that -help invokes the usage message and returns ErrHelp. -func TestHelp(t *testing.T) { - var helpCalled = false - fs := NewFlagSet("help test", ContinueOnError) - fs.Usage = func() { helpCalled = true } - var flag bool - fs.BoolVar(&flag, []string{"flag"}, false, "regular flag") - // Regular flag invocation should work - err := fs.Parse([]string{"-flag=true"}) - if err != nil { - t.Fatal("expected no error; got ", err) - } - if !flag { - t.Error("flag was not set by -flag") - } - if helpCalled { - t.Error("help called for regular flag") - helpCalled = false // reset for next test - } - // Help flag should work as expected. - err = fs.Parse([]string{"-help"}) - if err == nil { - t.Fatal("error expected") - } - if err != ErrHelp { - t.Fatal("expected ErrHelp; got ", err) - } - if !helpCalled { - t.Fatal("help was not called") - } - // If we define a help flag, that should override. - var help bool - fs.BoolVar(&help, []string{"help"}, false, "help flag") - helpCalled = false - err = fs.Parse([]string{"-help"}) - if err != nil { - t.Fatal("expected no error for defined -help; got ", err) - } - if helpCalled { - t.Fatal("help was called; should not have been for defined help flag") - } -} - -// Test the flag count functions. -func TestFlagCounts(t *testing.T) { - fs := NewFlagSet("help test", ContinueOnError) - var flag bool - fs.BoolVar(&flag, []string{"flag1"}, false, "regular flag") - fs.BoolVar(&flag, []string{"#deprecated1"}, false, "regular flag") - fs.BoolVar(&flag, []string{"f", "flag2"}, false, "regular flag") - fs.BoolVar(&flag, []string{"#d", "#deprecated2"}, false, "regular flag") - fs.BoolVar(&flag, []string{"flag3"}, false, "regular flag") - fs.BoolVar(&flag, []string{"g", "#flag4", "-flag4"}, false, "regular flag") - - if fs.FlagCount() != 6 { - t.Fatal("FlagCount wrong. ", fs.FlagCount()) - } - if fs.FlagCountUndeprecated() != 4 { - t.Fatal("FlagCountUndeprecated wrong. ", fs.FlagCountUndeprecated()) - } - if fs.NFlag() != 0 { - t.Fatal("NFlag wrong. ", fs.NFlag()) - } - err := fs.Parse([]string{"-fd", "-g", "-flag4"}) - if err != nil { - t.Fatal("expected no error for defined -help; got ", err) - } - if fs.NFlag() != 4 { - t.Fatal("NFlag wrong. ", fs.NFlag()) - } -} - -// Show up bug in sortFlags -func TestSortFlags(t *testing.T) { - fs := NewFlagSet("help TestSortFlags", ContinueOnError) - - var err error - - var b bool - fs.BoolVar(&b, []string{"b", "-banana"}, false, "usage") - - err = fs.Parse([]string{"--banana=true"}) - if err != nil { - t.Fatal("expected no error; got ", err) - } - - count := 0 - - fs.VisitAll(func(flag *Flag) { - count++ - if flag == nil { - t.Fatal("VisitAll should not return a nil flag") - } - }) - flagcount := fs.FlagCount() - if flagcount != count { - t.Fatalf("FlagCount (%d) != number (%d) of elements visited", flagcount, count) - } - // Make sure its idempotent - if flagcount != fs.FlagCount() { - t.Fatalf("FlagCount (%d) != fs.FlagCount() (%d) of elements visited", flagcount, fs.FlagCount()) - } - - count = 0 - fs.Visit(func(flag *Flag) { - count++ - if flag == nil { - t.Fatal("Visit should not return a nil flag") - } - }) - nflag := fs.NFlag() - if nflag != count { - t.Fatalf("NFlag (%d) != number (%d) of elements visited", nflag, count) - } - if nflag != fs.NFlag() { - t.Fatalf("NFlag (%d) != fs.NFlag() (%d) of elements visited", nflag, fs.NFlag()) - } -} - -func TestMergeFlags(t *testing.T) { - base := NewFlagSet("base", ContinueOnError) - base.String([]string{"f"}, "", "") - - fs := NewFlagSet("test", ContinueOnError) - Merge(fs, base) - if len(fs.formal) != 1 { - t.Fatalf("FlagCount (%d) != number (1) of elements merged", len(fs.formal)) - } -} diff --git a/libnetwork/client/network.go b/libnetwork/client/network.go deleted file mode 100644 index bc050f7e2d..0000000000 --- a/libnetwork/client/network.go +++ /dev/null @@ -1,267 +0,0 @@ -package client - -import ( - "bytes" - "encoding/json" - "fmt" - "net/http" - "strings" - "text/tabwriter" - - flag "github.com/docker/docker/libnetwork/client/mflag" - "github.com/docker/docker/libnetwork/netlabel" - "github.com/docker/docker/pkg/stringid" -) - -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"}, - } -) - -// CmdNetwork handles the root Network UI -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 -} - -// CmdNetworkCreate handles Network Create UI -func (cli *NetworkCli) CmdNetworkCreate(chain string, args ...string) error { - 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"}, "", "Driver to manage the Network") - flID := cmd.String([]string{"-id"}, "", "Network ID string") - flOpts := cmd.String([]string{"o", "-opt"}, "", "Network options") - flInternal := cmd.Bool([]string{"-internal"}, false, "Config the network to be internal") - flIPv6 := cmd.Bool([]string{"-ipv6"}, false, "Enable IPv6 on the network") - flSubnet := cmd.String([]string{"-subnet"}, "", "Subnet option") - flRange := cmd.String([]string{"-ip-range"}, "", "Range option") - - cmd.Require(flag.Exact, 1) - err := cmd.ParseFlags(args, true) - if err != nil { - return err - } - networkOpts := make(map[string]string) - if *flInternal { - networkOpts[netlabel.Internal] = "true" - } - if *flIPv6 { - networkOpts[netlabel.EnableIPv6] = "true" - } - - driverOpts := make(map[string]string) - if *flOpts != "" { - opts := strings.Split(*flOpts, ",") - for _, opt := range opts { - driverOpts[netlabel.Key(opt)] = netlabel.Value(opt) - } - } - - var icList []ipamConf - if *flSubnet != "" { - ic := ipamConf{ - PreferredPool: *flSubnet, - } - - if *flRange != "" { - ic.SubPool = *flRange - } - - icList = append(icList, ic) - } - - // Construct network create request body - nc := networkCreate{Name: cmd.Arg(0), NetworkType: *flDriver, ID: *flID, IPv4Conf: icList, DriverOpts: driverOpts, NetworkOpts: networkOpts} - obj, _, err := readBody(cli.call("POST", "/networks", nc, 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 -} - -// CmdNetworkRm handles Network Delete UI -func (cli *NetworkCli) CmdNetworkRm(chain string, args ...string) error { - cmd := cli.Subcmd(chain, "rm", "NETWORK", "Deletes a network", false) - cmd.Require(flag.Exact, 1) - err := cmd.ParseFlags(args, true) - if err != nil { - return err - } - id, err := lookupNetworkID(cli, cmd.Arg(0)) - if err != nil { - return err - } - _, _, err = readBody(cli.call("DELETE", "/networks/"+id, nil, nil)) - if err != nil { - return err - } - return nil -} - -// CmdNetworkLs handles Network List UI -func (cli *NetworkCli) CmdNetworkLs(chain string, args ...string) error { - cmd := cli.Subcmd(chain, "ls", "", "Lists all the networks created by the user", 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 - } - obj, _, err := readBody(cli.call("GET", "/networks", nil, nil)) - if err != nil { - return err - } - if *last == -1 && *nLatest { - *last = 1 - } - - var networkResources []networkResource - err = json.Unmarshal(obj, &networkResources) - 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 ID\tNAME\tTYPE") - } - - for _, networkResource := range networkResources { - ID := networkResource.ID - netName := networkResource.Name - if !*noTrunc { - ID = stringid.TruncateID(ID) - } - if *quiet { - fmt.Fprintln(wr, ID) - continue - } - netType := networkResource.Type - fmt.Fprintf(wr, "%s\t%s\t%s\t", - ID, - netName, - netType) - fmt.Fprint(wr, "\n") - } - wr.Flush() - return nil -} - -// CmdNetworkInfo handles Network Info UI -func (cli *NetworkCli) CmdNetworkInfo(chain string, args ...string) error { - cmd := cli.Subcmd(chain, "info", "NETWORK", "Displays detailed information on a network", false) - cmd.Require(flag.Exact, 1) - err := cmd.ParseFlags(args, true) - if err != nil { - return err - } - - id, err := lookupNetworkID(cli, cmd.Arg(0)) - if err != nil { - return err - } - - obj, _, err := readBody(cli.call("GET", "/networks/"+id, nil, nil)) - if err != nil { - return err - } - networkResource := &networkResource{} - if err := json.NewDecoder(bytes.NewReader(obj)).Decode(networkResource); err != nil { - return err - } - fmt.Fprintf(cli.out, "Network Id: %s\n", networkResource.ID) - fmt.Fprintf(cli.out, "Name: %s\n", networkResource.Name) - fmt.Fprintf(cli.out, "Type: %s\n", networkResource.Type) - if networkResource.Services != nil { - for _, serviceResource := range networkResource.Services { - fmt.Fprintf(cli.out, " Service Id: %s\n", serviceResource.ID) - fmt.Fprintf(cli.out, "\tName: %s\n", serviceResource.Name) - } - } - - return nil -} - -// Helper function to predict if a string is a name or id or partial-id -// This provides a best-effort mechanism to identify an id with the help of GET Filter APIs -// Being a UI, its most likely that name will be used by the user, which is used to lookup -// the corresponding ID. If ID is not found, this function will assume that the passed string -// is an ID by itself. - -func lookupNetworkID(cli *NetworkCli, nameID string) (string, error) { - obj, statusCode, err := readBody(cli.call("GET", "/networks?name="+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", "/networks?partial-id="+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 Networks matching the partial identifier (%s). Please use full identifier", nameID) - } - return list[0].ID, nil -} - -func networkUsage(chain string) string { - help := "Commands:\n" - - for _, cmd := range networkCommands { - help += fmt.Sprintf(" %-25.25s%s\n", 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 deleted file mode 100644 index a246bc6061..0000000000 --- a/libnetwork/client/service.go +++ /dev/null @@ -1,400 +0,0 @@ -package client - -import ( - "bytes" - "encoding/json" - "errors" - "fmt" - "net/http" - "strings" - "text/tabwriter" - - flag "github.com/docker/docker/libnetwork/client/mflag" - "github.com/docker/docker/libnetwork/netutils" - "github.com/docker/docker/pkg/stringid" -) - -var ( - serviceCommands = []command{ - {"publish", "Publish a service"}, - {"unpublish", "Remove a service"}, - {"attach", "Attach a backend (container) to the service"}, - {"detach", "Detach the backend from the service"}, - {"ls", "Lists all services"}, - {"info", "Display information about a service"}, - } -) - -func lookupServiceID(cli *NetworkCli, nwName, svNameID string) (string, error) { - // Sanity Check - obj, _, err := readBody(cli.call("GET", fmt.Sprintf("/networks?name=%s", nwName), nil, nil)) - if err != nil { - return "", err - } - var nwList []networkResource - if err = json.Unmarshal(obj, &nwList); err != nil { - return "", err - } - if len(nwList) == 0 { - return "", fmt.Errorf("Network %s does not exist", nwName) - } - - if nwName == "" { - obj, _, err := readBody(cli.call("GET", "/networks/"+nwList[0].ID, nil, nil)) - if err != nil { - return "", err - } - networkResource := &networkResource{} - if err := json.NewDecoder(bytes.NewReader(obj)).Decode(networkResource); err != nil { - return "", err - } - nwName = networkResource.Name - } - - // Query service by name - obj, statusCode, err := readBody(cli.call("GET", fmt.Sprintf("/services?name=%s", svNameID), nil, nil)) - if err != nil { - return "", err - } - - if statusCode != http.StatusOK { - return "", fmt.Errorf("name query failed for %s due to: (%d) %s", svNameID, statusCode, string(obj)) - } - - var list []*serviceResource - if err = json.Unmarshal(obj, &list); err != nil { - return "", err - } - for _, sr := range list { - if sr.Network == nwName { - return sr.ID, nil - } - } - - // Query service by Partial-id (this covers full id as well) - obj, statusCode, err = readBody(cli.call("GET", fmt.Sprintf("/services?partial-id=%s", svNameID), nil, nil)) - if err != nil { - return "", err - } - - if statusCode != http.StatusOK { - return "", fmt.Errorf("partial-id match query failed for %s due to: (%d) %s", svNameID, statusCode, string(obj)) - } - - if err = json.Unmarshal(obj, &list); err != nil { - return "", err - } - for _, sr := range list { - if sr.Network == nwName { - return sr.ID, nil - } - } - - return "", fmt.Errorf("Service %s not found on network %s", svNameID, nwName) -} - -func lookupContainerID(cli *NetworkCli, cnNameID string) (string, error) { - // Container is a Docker resource, ask docker about it. - // In case of connection error, we assume we are running in dnet and return whatever was passed to us - obj, _, err := readBody(cli.call("GET", fmt.Sprintf("/containers/%s/json", cnNameID), nil, nil)) - if err != nil { - // We are probably running outside of docker - return cnNameID, nil - } - - var x map[string]interface{} - err = json.Unmarshal(obj, &x) - if err != nil { - return "", err - } - if iid, ok := x["Id"]; ok { - if id, ok := iid.(string); ok { - return id, nil - } - return "", errors.New("Unexpected data type for container ID in json response") - } - return "", errors.New("Cannot find container ID in json response") -} - -func lookupSandboxID(cli *NetworkCli, containerID string) (string, error) { - obj, _, err := readBody(cli.call("GET", fmt.Sprintf("/sandboxes?partial-container-id=%s", containerID), nil, nil)) - if err != nil { - return "", err - } - - var sandboxList []SandboxResource - err = json.Unmarshal(obj, &sandboxList) - if err != nil { - return "", err - } - - if len(sandboxList) == 0 { - return "", fmt.Errorf("cannot find sandbox for container: %s", containerID) - } - - return sandboxList[0].ID, nil -} - -// CmdService handles the 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 -} - -// Parse service name for "SERVICE[.NETWORK]" format -func parseServiceName(name string) (string, string) { - s := strings.Split(name, ".") - var sName, nName string - if len(s) > 1 { - nName = s[len(s)-1] - sName = strings.Join(s[:len(s)-1], ".") - } else { - sName = s[0] - } - return sName, nName -} - -// CmdServicePublish handles service create UI -func (cli *NetworkCli) CmdServicePublish(chain string, args ...string) error { - cmd := cli.Subcmd(chain, "publish", "SERVICE[.NETWORK]", "Publish a new service on a network", false) - flAlias := flag.NewListOpts(netutils.ValidateAlias) - cmd.Var(&flAlias, []string{"-alias"}, "Add alias to self") - cmd.Require(flag.Exact, 1) - err := cmd.ParseFlags(args, true) - if err != nil { - return err - } - - sn, nn := parseServiceName(cmd.Arg(0)) - sc := serviceCreate{Name: sn, Network: nn, MyAliases: flAlias.GetAll()} - obj, _, err := readBody(cli.call("POST", "/services", sc, 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 -} - -// CmdServiceUnpublish handles service delete UI -func (cli *NetworkCli) CmdServiceUnpublish(chain string, args ...string) error { - cmd := cli.Subcmd(chain, "unpublish", "SERVICE[.NETWORK]", "Removes a service", false) - force := cmd.Bool([]string{"f", "-force"}, false, "force unpublish service") - cmd.Require(flag.Exact, 1) - err := cmd.ParseFlags(args, true) - if err != nil { - return err - } - - sn, nn := parseServiceName(cmd.Arg(0)) - serviceID, err := lookupServiceID(cli, nn, sn) - if err != nil { - return err - } - - sd := serviceDelete{Name: sn, Force: *force} - _, _, err = readBody(cli.call("DELETE", "/services/"+serviceID, sd, nil)) - - return err -} - -// CmdServiceLs handles service list UI -func (cli *NetworkCli) CmdServiceLs(chain string, args ...string) error { - cmd := cli.Subcmd(chain, "ls", "SERVICE", "Lists all the services on a network", false) - flNetwork := cmd.String([]string{"net", "-network"}, "", "Only show the services that are published on the specified network") - quiet := cmd.Bool([]string{"q", "-quiet"}, false, "Only display numeric IDs") - noTrunc := cmd.Bool([]string{"#notrunc", "-no-trunc"}, false, "Do not truncate the output") - - err := cmd.ParseFlags(args, true) - if err != nil { - return err - } - - var obj []byte - if *flNetwork == "" { - obj, _, err = readBody(cli.call("GET", "/services", nil, nil)) - } else { - obj, _, err = readBody(cli.call("GET", "/services?network="+*flNetwork, nil, nil)) - } - if err != nil { - return err - } - - var serviceResources []serviceResource - err = json.Unmarshal(obj, &serviceResources) - if err != nil { - fmt.Println(err) - return err - } - - wr := tabwriter.NewWriter(cli.out, 20, 1, 3, ' ', 0) - // unless quiet (-q) is specified, print field titles - if !*quiet { - fmt.Fprintln(wr, "SERVICE ID\tNAME\tNETWORK\tCONTAINER\tSANDBOX") - } - - for _, sr := range serviceResources { - ID := sr.ID - bkID, sbID, err := getBackendID(cli, ID) - if err != nil { - return err - } - if !*noTrunc { - ID = stringid.TruncateID(ID) - bkID = stringid.TruncateID(bkID) - sbID = stringid.TruncateID(sbID) - } - if !*quiet { - fmt.Fprintf(wr, "%s\t%s\t%s\t%s\t%s\n", ID, sr.Name, sr.Network, bkID, sbID) - } else { - fmt.Fprintln(wr, ID) - } - } - wr.Flush() - - return nil -} - -func getBackendID(cli *NetworkCli, servID string) (string, string, error) { - var ( - obj []byte - err error - bk string - sb string - ) - - if obj, _, err = readBody(cli.call("GET", "/services/"+servID+"/backend", nil, nil)); err == nil { - var sr SandboxResource - if err := json.NewDecoder(bytes.NewReader(obj)).Decode(&sr); err == nil { - bk = sr.ContainerID - sb = sr.ID - } else { - // Only print a message, don't make the caller cli fail for this - fmt.Fprintf(cli.out, "Failed to retrieve backend list for service %s (%v)\n", servID, err) - } - } - - return bk, sb, err -} - -// CmdServiceInfo handles service info UI -func (cli *NetworkCli) CmdServiceInfo(chain string, args ...string) error { - cmd := cli.Subcmd(chain, "info", "SERVICE[.NETWORK]", "Displays detailed information about a service", false) - cmd.Require(flag.Min, 1) - - err := cmd.ParseFlags(args, true) - if err != nil { - return err - } - - sn, nn := parseServiceName(cmd.Arg(0)) - serviceID, err := lookupServiceID(cli, nn, sn) - if err != nil { - return err - } - - obj, _, err := readBody(cli.call("GET", "/services/"+serviceID, nil, nil)) - if err != nil { - return err - } - - sr := &serviceResource{} - if err := json.NewDecoder(bytes.NewReader(obj)).Decode(sr); err != nil { - return err - } - - fmt.Fprintf(cli.out, "Service Id: %s\n", sr.ID) - fmt.Fprintf(cli.out, "\tName: %s\n", sr.Name) - fmt.Fprintf(cli.out, "\tNetwork: %s\n", sr.Network) - - return nil -} - -// CmdServiceAttach handles service attach UI -func (cli *NetworkCli) CmdServiceAttach(chain string, args ...string) error { - cmd := cli.Subcmd(chain, "attach", "CONTAINER SERVICE[.NETWORK]", "Sets a container as a service backend", false) - flAlias := flag.NewListOpts(netutils.ValidateAlias) - cmd.Var(&flAlias, []string{"-alias"}, "Add alias for another container") - cmd.Require(flag.Min, 2) - err := cmd.ParseFlags(args, true) - if err != nil { - return err - } - - containerID, err := lookupContainerID(cli, cmd.Arg(0)) - if err != nil { - return err - } - - sandboxID, err := lookupSandboxID(cli, containerID) - if err != nil { - return err - } - - sn, nn := parseServiceName(cmd.Arg(1)) - serviceID, err := lookupServiceID(cli, nn, sn) - if err != nil { - return err - } - - nc := serviceAttach{SandboxID: sandboxID, Aliases: flAlias.GetAll()} - - _, _, err = readBody(cli.call("POST", "/services/"+serviceID+"/backend", nc, nil)) - - return err -} - -// CmdServiceDetach handles service detach UI -func (cli *NetworkCli) CmdServiceDetach(chain string, args ...string) error { - cmd := cli.Subcmd(chain, "detach", "CONTAINER SERVICE", "Removes a container from service backend", false) - cmd.Require(flag.Min, 2) - err := cmd.ParseFlags(args, true) - if err != nil { - return err - } - - sn, nn := parseServiceName(cmd.Arg(1)) - containerID, err := lookupContainerID(cli, cmd.Arg(0)) - if err != nil { - return err - } - - sandboxID, err := lookupSandboxID(cli, containerID) - if err != nil { - return err - } - - serviceID, err := lookupServiceID(cli, nn, sn) - if err != nil { - return err - } - - _, _, err = readBody(cli.call("DELETE", "/services/"+serviceID+"/backend/"+sandboxID, nil, nil)) - if err != nil { - 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/types.go b/libnetwork/client/types.go deleted file mode 100644 index cdfc9d8045..0000000000 --- a/libnetwork/client/types.go +++ /dev/null @@ -1,88 +0,0 @@ -package client - -import "github.com/docker/docker/libnetwork/types" - -/*********** - Resources -************/ - -// networkResource is the body of the "get network" http response message -type networkResource struct { - Name string `json:"name"` - ID string `json:"id"` - Type string `json:"type"` - Services []*serviceResource `json:"services"` -} - -// serviceResource is the body of the "get service" http response message -type serviceResource struct { - Name string `json:"name"` - ID string `json:"id"` - Network string `json:"network"` -} - -// SandboxResource is the body of "get service backend" response message -type SandboxResource struct { - ID string `json:"id"` - Key string `json:"key"` - ContainerID string `json:"container_id"` -} - -/*********** - Body types - ************/ -type ipamConf struct { - PreferredPool string - SubPool string - Gateway string - AuxAddresses map[string]string -} - -// networkCreate is the expected body of the "create network" http request message -type networkCreate struct { - Name string `json:"name"` - ID string `json:"id"` - NetworkType string `json:"network_type"` - IPv4Conf []ipamConf `json:"ipv4_configuration"` - DriverOpts map[string]string `json:"driver_opts"` - NetworkOpts map[string]string `json:"network_opts"` -} - -// serviceCreate represents the body of the "publish service" http request message -type serviceCreate struct { - Name string `json:"name"` - MyAliases []string `json:"my_aliases"` - Network string `json:"network_name"` -} - -// serviceDelete represents the body of the "unpublish service" http request message -type serviceDelete struct { - Name string `json:"name"` - Force bool `json:"force"` -} - -// serviceAttach represents the expected body of the "attach/detach sandbox to/from service" http request messages -type serviceAttach struct { - SandboxID string `json:"sandbox_id"` - Aliases []string `json:"aliases"` -} - -// SandboxCreate is the body of the "post /sandboxes" http request message -type SandboxCreate struct { - ContainerID string `json:"container_id"` - HostName string `json:"host_name"` - DomainName string `json:"domain_name"` - HostsPath string `json:"hosts_path"` - ResolvConfPath string `json:"resolv_conf_path"` - DNS []string `json:"dns"` - ExtraHosts []extraHost `json:"extra_hosts"` - UseDefaultSandbox bool `json:"use_default_sandbox"` - ExposedPorts []types.TransportPort `json:"exposed_ports"` - PortMapping []types.PortBinding `json:"port_mapping"` -} - -// extraHost represents the extra host object -type extraHost struct { - Name string `json:"name"` - Address string `json:"address"` -}