Browse Source

Merge pull request #93 from mavenugo/cli

libnetwork client
Jana Radhakrishnan 10 years ago
parent
commit
144a42267b

+ 15 - 0
libnetwork/Godeps/Godeps.json

@@ -30,6 +30,21 @@
 			"Comment": "v1.4.1-2492-ge690ad9",
 			"Comment": "v1.4.1-2492-ge690ad9",
 			"Rev": "e690ad92925a045344bde8d2d59d7a7f602dded6"
 			"Rev": "e690ad92925a045344bde8d2d59d7a7f602dded6"
 		},
 		},
+		{
+			"ImportPath": "github.com/docker/docker/pkg/mflag",
+			"Comment": "v1.4.1-2492-ge690ad9",
+			"Rev": "e690ad92925a045344bde8d2d59d7a7f602dded6"
+		},
+		{
+			"ImportPath": "github.com/docker/docker/pkg/homedir",
+			"Comment": "v1.4.1-2492-ge690ad9",
+			"Rev": "e690ad92925a045344bde8d2d59d7a7f602dded6"
+		},
+		{
+			"ImportPath": "github.com/docker/libcontainer/user",
+			"Comment": "v1.4.0",
+			"Rev": "53eca435e63db58b06cf796d3a9326db5fd42253"
+		},
 		{
 		{
 			"ImportPath": "github.com/docker/docker/pkg/stringid",
 			"ImportPath": "github.com/docker/docker/pkg/stringid",
 			"Comment": "v1.4.1-2492-ge690ad9",
 			"Comment": "v1.4.1-2492-ge690ad9",

+ 39 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/pkg/homedir/homedir.go

@@ -0,0 +1,39 @@
+package homedir
+
+import (
+	"os"
+	"runtime"
+
+	"github.com/docker/libcontainer/user"
+)
+
+// Key returns the env var name for the user's home dir based on
+// the platform being run on
+func Key() string {
+	if runtime.GOOS == "windows" {
+		return "USERPROFILE"
+	}
+	return "HOME"
+}
+
+// Get returns the home directory of the current user with the help of
+// environment variables depending on the target operating system.
+// Returned path should be used with "path/filepath" to form new paths.
+func Get() string {
+	home := os.Getenv(Key())
+	if home == "" && runtime.GOOS != "windows" {
+		if u, err := user.CurrentUser(); err == nil {
+			return u.Home
+		}
+	}
+	return home
+}
+
+// GetShortcutString returns the string that is shortcut to user's home directory
+// in the native shell of the platform running on.
+func GetShortcutString() string {
+	if runtime.GOOS == "windows" {
+		return "%USERPROFILE%" // be careful while using in format functions
+	}
+	return "~"
+}

+ 24 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/pkg/homedir/homedir_test.go

@@ -0,0 +1,24 @@
+package homedir
+
+import (
+	"path/filepath"
+	"testing"
+)
+
+func TestGet(t *testing.T) {
+	home := Get()
+	if home == "" {
+		t.Fatal("returned home directory is empty")
+	}
+
+	if !filepath.IsAbs(home) {
+		t.Fatalf("returned path is not absolute: %s", home)
+	}
+}
+
+func TestGetShortcutString(t *testing.T) {
+	shortcut := GetShortcutString()
+	if shortcut == "" {
+		t.Fatal("returned shortcut string is empty")
+	}
+}

+ 27 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/pkg/mflag/LICENSE

@@ -0,0 +1,27 @@
+Copyright (c) 2014-2015 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.

+ 40 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/pkg/mflag/README.md

@@ -0,0 +1,40 @@
+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.

+ 36 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/pkg/mflag/example/example.go

@@ -0,0 +1,36 @@
+package main
+
+import (
+	"fmt"
+
+	flag "github.com/docker/docker/pkg/mflag"
+)
+
+var (
+	i        int
+	str      string
+	b, b2, h bool
+)
+
+func init() {
+	flag.Bool([]string{"#hp", "#-halp"}, false, "display the halp")
+	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())
+	}
+}

+ 1131 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/pkg/mflag/flag.go

@@ -0,0 +1,1131 @@
+// Copyright 2014-2015 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 flag 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/docker/pkg/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"
+
+	"github.com/docker/docker/pkg/homedir"
+)
+
+// 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) }
+
+// -- 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 fmt.Sprintf("%s", *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
+
+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()
+
+	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 (f *FlagSet) Name() string {
+	return f.name
+}
+
+// Out returns the destination for usage and error messages.
+func (f *FlagSet) Out() io.Writer {
+	if f.output == nil {
+		return os.Stderr
+	}
+	return f.output
+}
+
+// SetOutput sets the destination for usage and error messages.
+// If output is nil, os.Stderr is used.
+func (f *FlagSet) SetOutput(output io.Writer) {
+	f.output = output
+}
+
+// VisitAll visits the flags in lexicographical order, calling fn for each.
+// It visits all flags, even those not set.
+func (f *FlagSet) VisitAll(fn func(*Flag)) {
+	for _, flag := range sortFlags(f.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 (f *FlagSet) Visit(fn func(*Flag)) {
+	for _, flag := range sortFlags(f.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 (f *FlagSet) Lookup(name string) *Flag {
+	return f.formal[name]
+}
+
+// Indicates whether the specified flag was specified at all on the cmd line
+func (f *FlagSet) IsSet(name string) bool {
+	return f.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]
+}
+
+// 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 (f *FlagSet) Require(nArgRequirementType nArgRequirementType, nArg int) {
+	f.nArgRequirements = append(f.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 (f *FlagSet) CheckArgs() (message string) {
+	for _, req := range f.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", f.name, kind, arguments)
+		}
+
+		switch req.Type {
+		case Exact:
+			if f.NArg() != req.N {
+				return str("")
+			}
+		case Max:
+			if f.NArg() > req.N {
+				return str("a maximum of ")
+			}
+		case Min:
+			if f.NArg() < req.N {
+				return str("a minimum of ")
+			}
+		}
+	}
+	return ""
+}
+
+// Set sets the value of the named flag.
+func (f *FlagSet) Set(name, value string) error {
+	flag, ok := f.formal[name]
+	if !ok {
+		return fmt.Errorf("no such flag -%v", name)
+	}
+	err := flag.Value.Set(value)
+	if err != nil {
+		return err
+	}
+	if f.actual == nil {
+		f.actual = make(map[string]*Flag)
+	}
+	f.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)
+}
+
+// PrintDefaults prints, to standard error unless configured
+// otherwise, the default values of all defined flags in the set.
+func (f *FlagSet) PrintDefaults() {
+	writer := tabwriter.NewWriter(f.Out(), 20, 1, 3, ' ', 0)
+	home := homedir.Get()
+
+	// Don't substitute when HOME is /
+	if runtime.GOOS != "windows" && home == "/" {
+		home = ""
+	}
+	f.VisitAll(func(flag *Flag) {
+		format := "  -%s=%s"
+		names := []string{}
+		for _, name := range flag.Names {
+			if name[0] != '#' {
+				names = append(names, name)
+			}
+		}
+		if len(names) > 0 {
+			val := flag.DefValue
+
+			if home != "" && strings.HasPrefix(val, home) {
+				val = homedir.GetShortcutString() + val[len(home):]
+			}
+
+			fmt.Fprintf(writer, format, strings.Join(names, ", -"), val)
+			for i, line := range strings.Split(flag.Usage, "\n") {
+				if i != 0 {
+					line = "  " + line
+				}
+				fmt.Fprintln(writer, "\t", line)
+			}
+		}
+	})
+	writer.Flush()
+}
+
+// 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(f *FlagSet) {
+	if f.name == "" {
+		fmt.Fprintf(f.Out(), "Usage:\n")
+	} else {
+		fmt.Fprintf(f.Out(), "Usage of %s:\n", f.name)
+	}
+	f.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.output, "Usage of %s:\n", os.Args[0])
+	PrintDefaults()
+}
+
+// FlagCount returns the number of flags that have been defined.
+func (f *FlagSet) FlagCount() int { return len(sortFlags(f.formal)) }
+
+// FlagCountUndeprecated returns the number of undeprecated flags that have been defined.
+func (f *FlagSet) FlagCountUndeprecated() int {
+	count := 0
+	for _, flag := range sortFlags(f.formal) {
+		for _, name := range flag.Names {
+			if name[0] != '#' {
+				count++
+				break
+			}
+		}
+	}
+	return count
+}
+
+// NFlag returns the number of flags that have been set.
+func (f *FlagSet) NFlag() int { return len(f.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 (f *FlagSet) Arg(i int) string {
+	if i < 0 || i >= len(f.args) {
+		return ""
+	}
+	return f.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 (f *FlagSet) NArg() int { return len(f.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 (f *FlagSet) Args() []string { return f.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 (f *FlagSet) BoolVar(p *bool, names []string, value bool, usage string) {
+	f.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 (f *FlagSet) Bool(names []string, value bool, usage string) *bool {
+	p := new(bool)
+	f.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 (f *FlagSet) IntVar(p *int, names []string, value int, usage string) {
+	f.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 (f *FlagSet) Int(names []string, value int, usage string) *int {
+	p := new(int)
+	f.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 (f *FlagSet) Int64Var(p *int64, names []string, value int64, usage string) {
+	f.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 (f *FlagSet) Int64(names []string, value int64, usage string) *int64 {
+	p := new(int64)
+	f.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 (f *FlagSet) UintVar(p *uint, names []string, value uint, usage string) {
+	f.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 (f *FlagSet) Uint(names []string, value uint, usage string) *uint {
+	p := new(uint)
+	f.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 (f *FlagSet) Uint64Var(p *uint64, names []string, value uint64, usage string) {
+	f.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 (f *FlagSet) Uint64(names []string, value uint64, usage string) *uint64 {
+	p := new(uint64)
+	f.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)
+}
+
+// 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 (f *FlagSet) StringVar(p *string, names []string, value string, usage string) {
+	f.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 (f *FlagSet) String(names []string, value string, usage string) *string {
+	p := new(string)
+	f.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 (f *FlagSet) Float64Var(p *float64, names []string, value float64, usage string) {
+	f.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 (f *FlagSet) Float64(names []string, value float64, usage string) *float64 {
+	p := new(float64)
+	f.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 (f *FlagSet) DurationVar(p *time.Duration, names []string, value time.Duration, usage string) {
+	f.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 (f *FlagSet) Duration(names []string, value time.Duration, usage string) *time.Duration {
+	p := new(time.Duration)
+	f.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 (f *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 := f.formal[name]
+		if alreadythere {
+			var msg string
+			if f.name == "" {
+				msg = fmt.Sprintf("flag redefined: %s", name)
+			} else {
+				msg = fmt.Sprintf("%s flag redefined: %s", f.name, name)
+			}
+			fmt.Fprintln(f.Out(), msg)
+			panic(msg) // Happens only if flags are declared with identical names
+		}
+		if f.formal == nil {
+			f.formal = make(map[string]*Flag)
+		}
+		f.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 (f *FlagSet) failf(format string, a ...interface{}) error {
+	err := fmt.Errorf(format, a...)
+	fmt.Fprintln(f.Out(), err)
+	if os.Args[0] == f.name {
+		fmt.Fprintf(f.Out(), "See '%s --help'.\n", os.Args[0])
+	} else {
+		fmt.Fprintf(f.Out(), "See '%s %s --help'.\n", os.Args[0], f.name)
+	}
+	return err
+}
+
+// usage calls the Usage method for the flag set, or the usage function if
+// the flag set is CommandLine.
+func (f *FlagSet) usage() {
+	if f == CommandLine {
+		Usage()
+	} else if f.Usage == nil {
+		defaultUsage(f)
+	} else {
+		f.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 (f *FlagSet) parseOne() (bool, string, error) {
+	if len(f.args) == 0 {
+		return false, "", nil
+	}
+	s := f.args[0]
+	if len(s) == 0 || s[0] != '-' || len(s) == 1 {
+		return false, "", nil
+	}
+	if s[1] == '-' && len(s) == 2 { // "--" terminates the flags
+		f.args = f.args[1:]
+		return false, "", nil
+	}
+	name := s[1:]
+	if len(name) == 0 || name[0] == '=' {
+		return false, "", f.failf("bad flag syntax: %s", s)
+	}
+
+	// it's a flag. does it have an argument?
+	f.args = f.args[1:]
+	hasValue := false
+	value := ""
+	if i := strings.Index(name, "="); i != -1 {
+		value = trimQuotes(name[i+1:])
+		hasValue = true
+		name = name[:i]
+	}
+
+	m := f.formal
+	flag, alreadythere := m[name] // BUG
+	if !alreadythere {
+		if name == "-help" || name == "help" || name == "h" { // special case for nice help message.
+			f.usage()
+			return false, "", ErrHelp
+		}
+		if len(name) > 0 && name[0] == '-' {
+			return false, "", f.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, "", f.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(f.args) > 0 {
+			// value is the next arg
+			hasValue = true
+			value, f.args = f.args[0], f.args[1:]
+		}
+		if !hasValue {
+			return false, "", f.failf("flag needs an argument: -%s", name)
+		}
+		if err := flag.Value.Set(value); err != nil {
+			return false, "", f.failf("invalid value %q for flag -%s: %v", value, name, err)
+		}
+	}
+	if f.actual == nil {
+		f.actual = make(map[string]*Flag)
+	}
+	f.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(f.Out(), "Warning: '-%s' is deprecated, it will be replaced by '-%s' soon. See usage.\n", name, replacement)
+			} else {
+				fmt.Fprintf(f.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 (f *FlagSet) Parse(arguments []string) error {
+	f.parsed = true
+	f.args = arguments
+	for {
+		seen, name, err := f.parseOne()
+		if seen {
+			continue
+		}
+		if err == nil {
+			break
+		}
+		if err == ErrRetry {
+			if len(name) > 1 {
+				err = nil
+				for _, letter := range strings.Split(name, "") {
+					f.args = append([]string{"-" + letter}, f.args...)
+					seen2, _, err2 := f.parseOne()
+					if seen2 {
+						continue
+					}
+					if err2 != nil {
+						err = f.failf("flag provided but not defined: -%s", name)
+						break
+					}
+				}
+				if err == nil {
+					continue
+				}
+			} else {
+				err = f.failf("flag provided but not defined: -%s", name)
+			}
+		}
+		switch f.errorHandling {
+		case ContinueOnError:
+			return err
+		case ExitOnError:
+			os.Exit(2)
+		case PanicOnError:
+			panic(err)
+		}
+	}
+	return nil
+}
+
+// ParseFlags is a utility function that adds a help flag if withHelp is true,
+// calls cmd.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 (cmd *FlagSet) ParseFlags(args []string, withHelp bool) error {
+	var help *bool
+	if withHelp {
+		help = cmd.Bool([]string{"#help", "-help"}, false, "Print usage")
+	}
+	if err := cmd.Parse(args); err != nil {
+		return err
+	}
+	if help != nil && *help {
+		cmd.Usage()
+		// just in case Usage does not exit
+		os.Exit(0)
+	}
+	if str := cmd.CheckArgs(); str != "" {
+		cmd.ReportError(str, withHelp)
+	}
+	return nil
+}
+
+func (cmd *FlagSet) ReportError(str string, withHelp bool) {
+	if withHelp {
+		if os.Args[0] == cmd.Name() {
+			str += ". See '" + os.Args[0] + " --help'"
+		} else {
+			str += ". See '" + os.Args[0] + " " + cmd.Name() + " --help'"
+		}
+	}
+	fmt.Fprintf(cmd.Out(), "docker: %s.\n", str)
+	os.Exit(1)
+}
+
+// Parsed reports whether f.Parse has been called.
+func (f *FlagSet) Parsed() bool {
+	return f.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 (f *FlagSet) Init(name string, errorHandling ErrorHandling) {
+	f.name = name
+	f.errorHandling = errorHandling
+}

+ 516 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/pkg/mflag/flag_test.go

@@ -0,0 +1,516 @@
+// Copyright 2014-2015 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"
+)
+
+// 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.Errorf("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) {
+		for _, name := range f.Names {
+			flagNames = append(flagNames, name)
+		}
+	})
+	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())
+	}
+}

+ 1 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/libcontainer/user/MAINTAINERS

@@ -0,0 +1 @@
+Tianon Gravi <admwiggin@gmail.com> (@tianon)

+ 108 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/libcontainer/user/lookup.go

@@ -0,0 +1,108 @@
+package user
+
+import (
+	"errors"
+	"fmt"
+	"syscall"
+)
+
+var (
+	// The current operating system does not provide the required data for user lookups.
+	ErrUnsupported = errors.New("user lookup: operating system does not provide passwd-formatted data")
+)
+
+func lookupUser(filter func(u User) bool) (User, error) {
+	// Get operating system-specific passwd reader-closer.
+	passwd, err := GetPasswd()
+	if err != nil {
+		return User{}, err
+	}
+	defer passwd.Close()
+
+	// Get the users.
+	users, err := ParsePasswdFilter(passwd, filter)
+	if err != nil {
+		return User{}, err
+	}
+
+	// No user entries found.
+	if len(users) == 0 {
+		return User{}, fmt.Errorf("no matching entries in passwd file")
+	}
+
+	// Assume the first entry is the "correct" one.
+	return users[0], nil
+}
+
+// CurrentUser looks up the current user by their user id in /etc/passwd. If the
+// user cannot be found (or there is no /etc/passwd file on the filesystem),
+// then CurrentUser returns an error.
+func CurrentUser() (User, error) {
+	return LookupUid(syscall.Getuid())
+}
+
+// LookupUser looks up a user by their username in /etc/passwd. If the user
+// cannot be found (or there is no /etc/passwd file on the filesystem), then
+// LookupUser returns an error.
+func LookupUser(username string) (User, error) {
+	return lookupUser(func(u User) bool {
+		return u.Name == username
+	})
+}
+
+// LookupUid looks up a user by their user id in /etc/passwd. If the user cannot
+// be found (or there is no /etc/passwd file on the filesystem), then LookupId
+// returns an error.
+func LookupUid(uid int) (User, error) {
+	return lookupUser(func(u User) bool {
+		return u.Uid == uid
+	})
+}
+
+func lookupGroup(filter func(g Group) bool) (Group, error) {
+	// Get operating system-specific group reader-closer.
+	group, err := GetGroup()
+	if err != nil {
+		return Group{}, err
+	}
+	defer group.Close()
+
+	// Get the users.
+	groups, err := ParseGroupFilter(group, filter)
+	if err != nil {
+		return Group{}, err
+	}
+
+	// No user entries found.
+	if len(groups) == 0 {
+		return Group{}, fmt.Errorf("no matching entries in group file")
+	}
+
+	// Assume the first entry is the "correct" one.
+	return groups[0], nil
+}
+
+// CurrentGroup looks up the current user's group by their primary group id's
+// entry in /etc/passwd. If the group cannot be found (or there is no
+// /etc/group file on the filesystem), then CurrentGroup returns an error.
+func CurrentGroup() (Group, error) {
+	return LookupGid(syscall.Getgid())
+}
+
+// LookupGroup looks up a group by its name in /etc/group. If the group cannot
+// be found (or there is no /etc/group file on the filesystem), then LookupGroup
+// returns an error.
+func LookupGroup(groupname string) (Group, error) {
+	return lookupGroup(func(g Group) bool {
+		return g.Name == groupname
+	})
+}
+
+// LookupGid looks up a group by its group id in /etc/group. If the group cannot
+// be found (or there is no /etc/group file on the filesystem), then LookupGid
+// returns an error.
+func LookupGid(gid int) (Group, error) {
+	return lookupGroup(func(g Group) bool {
+		return g.Gid == gid
+	})
+}

+ 30 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/libcontainer/user/lookup_unix.go

@@ -0,0 +1,30 @@
+// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+
+package user
+
+import (
+	"io"
+	"os"
+)
+
+// Unix-specific path to the passwd and group formatted files.
+const (
+	unixPasswdFile = "/etc/passwd"
+	unixGroupFile  = "/etc/group"
+)
+
+func GetPasswdFile() (string, error) {
+	return unixPasswdFile, nil
+}
+
+func GetPasswd() (io.ReadCloser, error) {
+	return os.Open(unixPasswdFile)
+}
+
+func GetGroupFile() (string, error) {
+	return unixGroupFile, nil
+}
+
+func GetGroup() (io.ReadCloser, error) {
+	return os.Open(unixGroupFile)
+}

+ 21 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/libcontainer/user/lookup_unsupported.go

@@ -0,0 +1,21 @@
+// +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris
+
+package user
+
+import "io"
+
+func GetPasswdFile() (string, error) {
+	return "", ErrUnsupported
+}
+
+func GetPasswd() (io.ReadCloser, error) {
+	return nil, ErrUnsupported
+}
+
+func GetGroupFile() (string, error) {
+	return "", ErrUnsupported
+}
+
+func GetGroup() (io.ReadCloser, error) {
+	return nil, ErrUnsupported
+}

+ 350 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/libcontainer/user/user.go

@@ -0,0 +1,350 @@
+package user
+
+import (
+	"bufio"
+	"fmt"
+	"io"
+	"os"
+	"strconv"
+	"strings"
+)
+
+const (
+	minId = 0
+	maxId = 1<<31 - 1 //for 32-bit systems compatibility
+)
+
+var (
+	ErrRange = fmt.Errorf("Uids and gids must be in range %d-%d", minId, maxId)
+)
+
+type User struct {
+	Name  string
+	Pass  string
+	Uid   int
+	Gid   int
+	Gecos string
+	Home  string
+	Shell string
+}
+
+type Group struct {
+	Name string
+	Pass string
+	Gid  int
+	List []string
+}
+
+func parseLine(line string, v ...interface{}) {
+	if line == "" {
+		return
+	}
+
+	parts := strings.Split(line, ":")
+	for i, p := range parts {
+		if len(v) <= i {
+			// if we have more "parts" than we have places to put them, bail for great "tolerance" of naughty configuration files
+			break
+		}
+
+		switch e := v[i].(type) {
+		case *string:
+			// "root", "adm", "/bin/bash"
+			*e = p
+		case *int:
+			// "0", "4", "1000"
+			// ignore string to int conversion errors, for great "tolerance" of naughty configuration files
+			*e, _ = strconv.Atoi(p)
+		case *[]string:
+			// "", "root", "root,adm,daemon"
+			if p != "" {
+				*e = strings.Split(p, ",")
+			} else {
+				*e = []string{}
+			}
+		default:
+			// panic, because this is a programming/logic error, not a runtime one
+			panic("parseLine expects only pointers!  argument " + strconv.Itoa(i) + " is not a pointer!")
+		}
+	}
+}
+
+func ParsePasswdFile(path string) ([]User, error) {
+	passwd, err := os.Open(path)
+	if err != nil {
+		return nil, err
+	}
+	defer passwd.Close()
+	return ParsePasswd(passwd)
+}
+
+func ParsePasswd(passwd io.Reader) ([]User, error) {
+	return ParsePasswdFilter(passwd, nil)
+}
+
+func ParsePasswdFileFilter(path string, filter func(User) bool) ([]User, error) {
+	passwd, err := os.Open(path)
+	if err != nil {
+		return nil, err
+	}
+	defer passwd.Close()
+	return ParsePasswdFilter(passwd, filter)
+}
+
+func ParsePasswdFilter(r io.Reader, filter func(User) bool) ([]User, error) {
+	if r == nil {
+		return nil, fmt.Errorf("nil source for passwd-formatted data")
+	}
+
+	var (
+		s   = bufio.NewScanner(r)
+		out = []User{}
+	)
+
+	for s.Scan() {
+		if err := s.Err(); err != nil {
+			return nil, err
+		}
+
+		text := strings.TrimSpace(s.Text())
+		if text == "" {
+			continue
+		}
+
+		// see: man 5 passwd
+		//  name:password:UID:GID:GECOS:directory:shell
+		// Name:Pass:Uid:Gid:Gecos:Home:Shell
+		//  root:x:0:0:root:/root:/bin/bash
+		//  adm:x:3:4:adm:/var/adm:/bin/false
+		p := User{}
+		parseLine(
+			text,
+			&p.Name, &p.Pass, &p.Uid, &p.Gid, &p.Gecos, &p.Home, &p.Shell,
+		)
+
+		if filter == nil || filter(p) {
+			out = append(out, p)
+		}
+	}
+
+	return out, nil
+}
+
+func ParseGroupFile(path string) ([]Group, error) {
+	group, err := os.Open(path)
+	if err != nil {
+		return nil, err
+	}
+	defer group.Close()
+	return ParseGroup(group)
+}
+
+func ParseGroup(group io.Reader) ([]Group, error) {
+	return ParseGroupFilter(group, nil)
+}
+
+func ParseGroupFileFilter(path string, filter func(Group) bool) ([]Group, error) {
+	group, err := os.Open(path)
+	if err != nil {
+		return nil, err
+	}
+	defer group.Close()
+	return ParseGroupFilter(group, filter)
+}
+
+func ParseGroupFilter(r io.Reader, filter func(Group) bool) ([]Group, error) {
+	if r == nil {
+		return nil, fmt.Errorf("nil source for group-formatted data")
+	}
+
+	var (
+		s   = bufio.NewScanner(r)
+		out = []Group{}
+	)
+
+	for s.Scan() {
+		if err := s.Err(); err != nil {
+			return nil, err
+		}
+
+		text := s.Text()
+		if text == "" {
+			continue
+		}
+
+		// see: man 5 group
+		//  group_name:password:GID:user_list
+		// Name:Pass:Gid:List
+		//  root:x:0:root
+		//  adm:x:4:root,adm,daemon
+		p := Group{}
+		parseLine(
+			text,
+			&p.Name, &p.Pass, &p.Gid, &p.List,
+		)
+
+		if filter == nil || filter(p) {
+			out = append(out, p)
+		}
+	}
+
+	return out, nil
+}
+
+type ExecUser struct {
+	Uid, Gid int
+	Sgids    []int
+	Home     string
+}
+
+// GetExecUserFile is a wrapper for GetExecUser. It reads data from each of the
+// given file paths and uses that data as the arguments to GetExecUser. If the
+// files cannot be opened for any reason, the error is ignored and a nil
+// io.Reader is passed instead.
+func GetExecUserFile(userSpec string, defaults *ExecUser, passwdPath, groupPath string) (*ExecUser, error) {
+	passwd, err := os.Open(passwdPath)
+	if err != nil {
+		passwd = nil
+	} else {
+		defer passwd.Close()
+	}
+
+	group, err := os.Open(groupPath)
+	if err != nil {
+		group = nil
+	} else {
+		defer group.Close()
+	}
+
+	return GetExecUser(userSpec, defaults, passwd, group)
+}
+
+// GetExecUser parses a user specification string (using the passwd and group
+// readers as sources for /etc/passwd and /etc/group data, respectively). In
+// the case of blank fields or missing data from the sources, the values in
+// defaults is used.
+//
+// GetExecUser will return an error if a user or group literal could not be
+// found in any entry in passwd and group respectively.
+//
+// Examples of valid user specifications are:
+//     * ""
+//     * "user"
+//     * "uid"
+//     * "user:group"
+//     * "uid:gid
+//     * "user:gid"
+//     * "uid:group"
+func GetExecUser(userSpec string, defaults *ExecUser, passwd, group io.Reader) (*ExecUser, error) {
+	var (
+		userArg, groupArg string
+		name              string
+	)
+
+	if defaults == nil {
+		defaults = new(ExecUser)
+	}
+
+	// Copy over defaults.
+	user := &ExecUser{
+		Uid:   defaults.Uid,
+		Gid:   defaults.Gid,
+		Sgids: defaults.Sgids,
+		Home:  defaults.Home,
+	}
+
+	// Sgids slice *cannot* be nil.
+	if user.Sgids == nil {
+		user.Sgids = []int{}
+	}
+
+	// allow for userArg to have either "user" syntax, or optionally "user:group" syntax
+	parseLine(userSpec, &userArg, &groupArg)
+
+	users, err := ParsePasswdFilter(passwd, func(u User) bool {
+		if userArg == "" {
+			return u.Uid == user.Uid
+		}
+		return u.Name == userArg || strconv.Itoa(u.Uid) == userArg
+	})
+	if err != nil && passwd != nil {
+		if userArg == "" {
+			userArg = strconv.Itoa(user.Uid)
+		}
+		return nil, fmt.Errorf("Unable to find user %v: %v", userArg, err)
+	}
+
+	haveUser := users != nil && len(users) > 0
+	if haveUser {
+		// if we found any user entries that matched our filter, let's take the first one as "correct"
+		name = users[0].Name
+		user.Uid = users[0].Uid
+		user.Gid = users[0].Gid
+		user.Home = users[0].Home
+	} else if userArg != "" {
+		// we asked for a user but didn't find them...  let's check to see if we wanted a numeric user
+		user.Uid, err = strconv.Atoi(userArg)
+		if err != nil {
+			// not numeric - we have to bail
+			return nil, fmt.Errorf("Unable to find user %v", userArg)
+		}
+
+		// Must be inside valid uid range.
+		if user.Uid < minId || user.Uid > maxId {
+			return nil, ErrRange
+		}
+
+		// if userArg couldn't be found in /etc/passwd but is numeric, just roll with it - this is legit
+	}
+
+	if groupArg != "" || name != "" {
+		groups, err := ParseGroupFilter(group, func(g Group) bool {
+			// Explicit group format takes precedence.
+			if groupArg != "" {
+				return g.Name == groupArg || strconv.Itoa(g.Gid) == groupArg
+			}
+
+			// Check if user is a member.
+			for _, u := range g.List {
+				if u == name {
+					return true
+				}
+			}
+
+			return false
+		})
+		if err != nil && group != nil {
+			return nil, fmt.Errorf("Unable to find groups for user %v: %v", users[0].Name, err)
+		}
+
+		haveGroup := groups != nil && len(groups) > 0
+		if groupArg != "" {
+			if haveGroup {
+				// if we found any group entries that matched our filter, let's take the first one as "correct"
+				user.Gid = groups[0].Gid
+			} else {
+				// we asked for a group but didn't find id...  let's check to see if we wanted a numeric group
+				user.Gid, err = strconv.Atoi(groupArg)
+				if err != nil {
+					// not numeric - we have to bail
+					return nil, fmt.Errorf("Unable to find group %v", groupArg)
+				}
+
+				// Ensure gid is inside gid range.
+				if user.Gid < minId || user.Gid > maxId {
+					return nil, ErrRange
+				}
+
+				// if groupArg couldn't be found in /etc/group but is numeric, just roll with it - this is legit
+			}
+		} else if haveGroup {
+			// If implicit group format, fill supplementary gids.
+			user.Sgids = make([]int, len(groups))
+			for i, group := range groups {
+				user.Sgids[i] = group.Gid
+			}
+		}
+	}
+
+	return user, nil
+}

+ 352 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/libcontainer/user/user_test.go

@@ -0,0 +1,352 @@
+package user
+
+import (
+	"io"
+	"reflect"
+	"strings"
+	"testing"
+)
+
+func TestUserParseLine(t *testing.T) {
+	var (
+		a, b string
+		c    []string
+		d    int
+	)
+
+	parseLine("", &a, &b)
+	if a != "" || b != "" {
+		t.Fatalf("a and b should be empty ('%v', '%v')", a, b)
+	}
+
+	parseLine("a", &a, &b)
+	if a != "a" || b != "" {
+		t.Fatalf("a should be 'a' and b should be empty ('%v', '%v')", a, b)
+	}
+
+	parseLine("bad boys:corny cows", &a, &b)
+	if a != "bad boys" || b != "corny cows" {
+		t.Fatalf("a should be 'bad boys' and b should be 'corny cows' ('%v', '%v')", a, b)
+	}
+
+	parseLine("", &c)
+	if len(c) != 0 {
+		t.Fatalf("c should be empty (%#v)", c)
+	}
+
+	parseLine("d,e,f:g:h:i,j,k", &c, &a, &b, &c)
+	if a != "g" || b != "h" || len(c) != 3 || c[0] != "i" || c[1] != "j" || c[2] != "k" {
+		t.Fatalf("a should be 'g', b should be 'h', and c should be ['i','j','k'] ('%v', '%v', '%#v')", a, b, c)
+	}
+
+	parseLine("::::::::::", &a, &b, &c)
+	if a != "" || b != "" || len(c) != 0 {
+		t.Fatalf("a, b, and c should all be empty ('%v', '%v', '%#v')", a, b, c)
+	}
+
+	parseLine("not a number", &d)
+	if d != 0 {
+		t.Fatalf("d should be 0 (%v)", d)
+	}
+
+	parseLine("b:12:c", &a, &d, &b)
+	if a != "b" || b != "c" || d != 12 {
+		t.Fatalf("a should be 'b' and b should be 'c', and d should be 12 ('%v', '%v', %v)", a, b, d)
+	}
+}
+
+func TestUserParsePasswd(t *testing.T) {
+	users, err := ParsePasswdFilter(strings.NewReader(`
+root:x:0:0:root:/root:/bin/bash
+adm:x:3:4:adm:/var/adm:/bin/false
+this is just some garbage data
+`), nil)
+	if err != nil {
+		t.Fatalf("Unexpected error: %v", err)
+	}
+	if len(users) != 3 {
+		t.Fatalf("Expected 3 users, got %v", len(users))
+	}
+	if users[0].Uid != 0 || users[0].Name != "root" {
+		t.Fatalf("Expected users[0] to be 0 - root, got %v - %v", users[0].Uid, users[0].Name)
+	}
+	if users[1].Uid != 3 || users[1].Name != "adm" {
+		t.Fatalf("Expected users[1] to be 3 - adm, got %v - %v", users[1].Uid, users[1].Name)
+	}
+}
+
+func TestUserParseGroup(t *testing.T) {
+	groups, err := ParseGroupFilter(strings.NewReader(`
+root:x:0:root
+adm:x:4:root,adm,daemon
+this is just some garbage data
+`), nil)
+	if err != nil {
+		t.Fatalf("Unexpected error: %v", err)
+	}
+	if len(groups) != 3 {
+		t.Fatalf("Expected 3 groups, got %v", len(groups))
+	}
+	if groups[0].Gid != 0 || groups[0].Name != "root" || len(groups[0].List) != 1 {
+		t.Fatalf("Expected groups[0] to be 0 - root - 1 member, got %v - %v - %v", groups[0].Gid, groups[0].Name, len(groups[0].List))
+	}
+	if groups[1].Gid != 4 || groups[1].Name != "adm" || len(groups[1].List) != 3 {
+		t.Fatalf("Expected groups[1] to be 4 - adm - 3 members, got %v - %v - %v", groups[1].Gid, groups[1].Name, len(groups[1].List))
+	}
+}
+
+func TestValidGetExecUser(t *testing.T) {
+	const passwdContent = `
+root:x:0:0:root user:/root:/bin/bash
+adm:x:42:43:adm:/var/adm:/bin/false
+this is just some garbage data
+`
+	const groupContent = `
+root:x:0:root
+adm:x:43:
+grp:x:1234:root,adm
+this is just some garbage data
+`
+	defaultExecUser := ExecUser{
+		Uid:   8888,
+		Gid:   8888,
+		Sgids: []int{8888},
+		Home:  "/8888",
+	}
+
+	tests := []struct {
+		ref      string
+		expected ExecUser
+	}{
+		{
+			ref: "root",
+			expected: ExecUser{
+				Uid:   0,
+				Gid:   0,
+				Sgids: []int{0, 1234},
+				Home:  "/root",
+			},
+		},
+		{
+			ref: "adm",
+			expected: ExecUser{
+				Uid:   42,
+				Gid:   43,
+				Sgids: []int{1234},
+				Home:  "/var/adm",
+			},
+		},
+		{
+			ref: "root:adm",
+			expected: ExecUser{
+				Uid:   0,
+				Gid:   43,
+				Sgids: defaultExecUser.Sgids,
+				Home:  "/root",
+			},
+		},
+		{
+			ref: "adm:1234",
+			expected: ExecUser{
+				Uid:   42,
+				Gid:   1234,
+				Sgids: defaultExecUser.Sgids,
+				Home:  "/var/adm",
+			},
+		},
+		{
+			ref: "42:1234",
+			expected: ExecUser{
+				Uid:   42,
+				Gid:   1234,
+				Sgids: defaultExecUser.Sgids,
+				Home:  "/var/adm",
+			},
+		},
+		{
+			ref: "1337:1234",
+			expected: ExecUser{
+				Uid:   1337,
+				Gid:   1234,
+				Sgids: defaultExecUser.Sgids,
+				Home:  defaultExecUser.Home,
+			},
+		},
+		{
+			ref: "1337",
+			expected: ExecUser{
+				Uid:   1337,
+				Gid:   defaultExecUser.Gid,
+				Sgids: defaultExecUser.Sgids,
+				Home:  defaultExecUser.Home,
+			},
+		},
+		{
+			ref: "",
+			expected: ExecUser{
+				Uid:   defaultExecUser.Uid,
+				Gid:   defaultExecUser.Gid,
+				Sgids: defaultExecUser.Sgids,
+				Home:  defaultExecUser.Home,
+			},
+		},
+	}
+
+	for _, test := range tests {
+		passwd := strings.NewReader(passwdContent)
+		group := strings.NewReader(groupContent)
+
+		execUser, err := GetExecUser(test.ref, &defaultExecUser, passwd, group)
+		if err != nil {
+			t.Logf("got unexpected error when parsing '%s': %s", test.ref, err.Error())
+			t.Fail()
+			continue
+		}
+
+		if !reflect.DeepEqual(test.expected, *execUser) {
+			t.Logf("got:      %#v", execUser)
+			t.Logf("expected: %#v", test.expected)
+			t.Fail()
+			continue
+		}
+	}
+}
+
+func TestInvalidGetExecUser(t *testing.T) {
+	const passwdContent = `
+root:x:0:0:root user:/root:/bin/bash
+adm:x:42:43:adm:/var/adm:/bin/false
+this is just some garbage data
+`
+	const groupContent = `
+root:x:0:root
+adm:x:43:
+grp:x:1234:root,adm
+this is just some garbage data
+`
+
+	tests := []string{
+		// No such user/group.
+		"notuser",
+		"notuser:notgroup",
+		"root:notgroup",
+		"notuser:adm",
+		"8888:notgroup",
+		"notuser:8888",
+
+		// Invalid user/group values.
+		"-1:0",
+		"0:-3",
+		"-5:-2",
+	}
+
+	for _, test := range tests {
+		passwd := strings.NewReader(passwdContent)
+		group := strings.NewReader(groupContent)
+
+		execUser, err := GetExecUser(test, nil, passwd, group)
+		if err == nil {
+			t.Logf("got unexpected success when parsing '%s': %#v", test, execUser)
+			t.Fail()
+			continue
+		}
+	}
+}
+
+func TestGetExecUserNilSources(t *testing.T) {
+	const passwdContent = `
+root:x:0:0:root user:/root:/bin/bash
+adm:x:42:43:adm:/var/adm:/bin/false
+this is just some garbage data
+`
+	const groupContent = `
+root:x:0:root
+adm:x:43:
+grp:x:1234:root,adm
+this is just some garbage data
+`
+
+	defaultExecUser := ExecUser{
+		Uid:   8888,
+		Gid:   8888,
+		Sgids: []int{8888},
+		Home:  "/8888",
+	}
+
+	tests := []struct {
+		ref           string
+		passwd, group bool
+		expected      ExecUser
+	}{
+		{
+			ref:    "",
+			passwd: false,
+			group:  false,
+			expected: ExecUser{
+				Uid:   8888,
+				Gid:   8888,
+				Sgids: []int{8888},
+				Home:  "/8888",
+			},
+		},
+		{
+			ref:    "root",
+			passwd: true,
+			group:  false,
+			expected: ExecUser{
+				Uid:   0,
+				Gid:   0,
+				Sgids: []int{8888},
+				Home:  "/root",
+			},
+		},
+		{
+			ref:    "0",
+			passwd: false,
+			group:  false,
+			expected: ExecUser{
+				Uid:   0,
+				Gid:   8888,
+				Sgids: []int{8888},
+				Home:  "/8888",
+			},
+		},
+		{
+			ref:    "0:0",
+			passwd: false,
+			group:  false,
+			expected: ExecUser{
+				Uid:   0,
+				Gid:   0,
+				Sgids: []int{8888},
+				Home:  "/8888",
+			},
+		},
+	}
+
+	for _, test := range tests {
+		var passwd, group io.Reader
+
+		if test.passwd {
+			passwd = strings.NewReader(passwdContent)
+		}
+
+		if test.group {
+			group = strings.NewReader(groupContent)
+		}
+
+		execUser, err := GetExecUser(test.ref, &defaultExecUser, passwd, group)
+		if err != nil {
+			t.Logf("got unexpected error when parsing '%s': %s", test.ref, err.Error())
+			t.Fail()
+			continue
+		}
+
+		if !reflect.DeepEqual(test.expected, *execUser) {
+			t.Logf("got:      %#v", execUser)
+			t.Logf("expected: %#v", test.expected)
+			t.Fail()
+			continue
+		}
+	}
+}

+ 112 - 0
libnetwork/client/client.go

@@ -0,0 +1,112 @@
+package client
+
+import (
+	"errors"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"os"
+	"reflect"
+	"strings"
+
+	flag "github.com/docker/docker/pkg/mflag"
+)
+
+// CallFunc provides environment specific call utility to invoke backend functions from UI
+type CallFunc func(string, string, interface{}, map[string][]string) (io.ReadCloser, int, error)
+
+// NetworkCli is the UI object for network subcmds
+type NetworkCli struct {
+	out  io.Writer
+	err  io.Writer
+	call CallFunc
+}
+
+// NewNetworkCli is a conveninent 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 {
+	var errStr string
+	if len(args) > 1 {
+		method, exists := cli.getMethod(args[:2]...)
+		if exists {
+			return method(chain, args[2:]...)
+		}
+	}
+	if len(args) > 0 {
+		method, exists := cli.getMethod(args[0])
+		if !exists {
+			errStr = fmt.Sprintf("%s: '%s' is not a %s command. See '%s --help'.\n", chain, args[0], chain, chain)
+			fmt.Fprintf(cli.err, errStr)
+			return errors.New(errStr)
+		}
+		return method(chain, args[1:]...)
+	}
+	errStr = fmt.Sprintf("'%s' is not a valid command. See '%s --help'.\n", chain, chain)
+	fmt.Fprintf(cli.err, errStr)
+	return errors.New(errStr)
+}
+
+// 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() {
+		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)
+		flags.PrintDefaults()
+		os.Exit(0)
+	}
+	return flags
+}
+
+func readBody(stream io.ReadCloser, 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
+}

+ 178 - 0
libnetwork/client/client_test.go

@@ -0,0 +1,178 @@
+package client
+
+import (
+	"bytes"
+	"io"
+	"testing"
+)
+
+// nopCloser is used to provide a dummy CallFunc for Cmd()
+type nopCloser struct {
+	io.Reader
+}
+
+func (nopCloser) Close() error { return nil }
+
+func TestClientDummyCommand(t *testing.T) {
+	var out, errOut bytes.Buffer
+	cFunc := func(method, path string, data interface{}, headers map[string][]string) (io.ReadCloser, int, error) {
+		return nopCloser{bytes.NewBufferString("")}, 200, nil
+	}
+	cli := NewNetworkCli(&out, &errOut, cFunc)
+
+	err := cli.Cmd("docker", "dummy")
+	if err == nil {
+		t.Fatalf("Incorrect Command must fail")
+	}
+}
+
+func TestClientNoCommand(t *testing.T) {
+	var out, errOut bytes.Buffer
+	cFunc := func(method, path string, data interface{}, headers map[string][]string) (io.ReadCloser, int, error) {
+		return nopCloser{bytes.NewBufferString("")}, 200, nil
+	}
+	cli := NewNetworkCli(&out, &errOut, cFunc)
+
+	err := cli.Cmd("docker")
+	if err == nil {
+		t.Fatalf("Incorrect Command must fail")
+	}
+}
+
+func TestClientNetworkCreate(t *testing.T) {
+	var out, errOut bytes.Buffer
+	cFunc := func(method, path string, data interface{}, headers map[string][]string) (io.ReadCloser, int, error) {
+		return nopCloser{bytes.NewBufferString("")}, 200, nil
+	}
+	cli := NewNetworkCli(&out, &errOut, cFunc)
+
+	err := cli.Cmd("docker", "network", "create", "test")
+	if err != nil {
+		t.Fatal(err.Error())
+	}
+}
+
+func TestClientNetworkCreateWithDriver(t *testing.T) {
+	var out, errOut bytes.Buffer
+	cFunc := func(method, path string, data interface{}, headers map[string][]string) (io.ReadCloser, int, error) {
+		return nopCloser{bytes.NewBufferString("")}, 200, nil
+	}
+	cli := NewNetworkCli(&out, &errOut, cFunc)
+
+	err := cli.Cmd("docker", "network", "create", "-f=dummy", "test")
+	if err == nil {
+		t.Fatalf("Passing incorrect flags to the create command must fail")
+	}
+
+	err = cli.Cmd("docker", "network", "create", "-d=dummy", "test")
+	if err != nil {
+		t.Fatalf(err.Error())
+	}
+}
+
+func TestClientNetworkRm(t *testing.T) {
+	var out, errOut bytes.Buffer
+	cFunc := func(method, path string, data interface{}, headers map[string][]string) (io.ReadCloser, int, error) {
+		return nopCloser{bytes.NewBufferString("")}, 200, nil
+	}
+	cli := NewNetworkCli(&out, &errOut, cFunc)
+
+	err := cli.Cmd("docker", "network", "rm", "test")
+	if err != nil {
+		t.Fatal(err.Error())
+	}
+}
+
+func TestClientNetworkLs(t *testing.T) {
+	var out, errOut bytes.Buffer
+	networks := "db,web,test"
+	cFunc := func(method, path string, data interface{}, headers map[string][]string) (io.ReadCloser, int, error) {
+		return nopCloser{bytes.NewBufferString(networks)}, 200, nil
+	}
+	cli := NewNetworkCli(&out, &errOut, cFunc)
+
+	err := cli.Cmd("docker", "network", "ls")
+	if err != nil {
+		t.Fatal(err.Error())
+	}
+	if out.String() != networks {
+		t.Fatal("Network List command fail to return the intended list")
+	}
+}
+
+func TestClientNetworkInfo(t *testing.T) {
+	var out, errOut bytes.Buffer
+	info := "dummy info"
+	cFunc := func(method, path string, data interface{}, headers map[string][]string) (io.ReadCloser, int, error) {
+		return nopCloser{bytes.NewBufferString(info)}, 200, nil
+	}
+	cli := NewNetworkCli(&out, &errOut, cFunc)
+
+	err := cli.Cmd("docker", "network", "info", "test")
+	if err != nil {
+		t.Fatal(err.Error())
+	}
+	if out.String() != info {
+		t.Fatal("Network List command fail to return the intended list")
+	}
+}
+
+func TestClientNetworkJoin(t *testing.T) {
+	var out, errOut bytes.Buffer
+	cFunc := func(method, path string, data interface{}, headers map[string][]string) (io.ReadCloser, int, error) {
+		return nopCloser{bytes.NewBufferString("")}, 200, nil
+	}
+	cli := NewNetworkCli(&out, &errOut, cFunc)
+
+	err := cli.Cmd("docker", "network", "join", "db1", "dbnet", "db1-ep")
+	if err != nil {
+		t.Fatal(err.Error())
+	}
+}
+
+func TestClientNetworkLeave(t *testing.T) {
+	var out, errOut bytes.Buffer
+	cFunc := func(method, path string, data interface{}, headers map[string][]string) (io.ReadCloser, int, error) {
+		return nopCloser{bytes.NewBufferString("")}, 200, nil
+	}
+	cli := NewNetworkCli(&out, &errOut, cFunc)
+
+	err := cli.Cmd("docker", "network", "leave", "db1", "dbnet")
+	if err != nil {
+		t.Fatal(err.Error())
+	}
+}
+
+// Docker Flag processing in flag.go uses os.Exit(0) for --help
+// TODO : Handle the --help test-case in the IT when CLI is available
+/*
+func TestClientNetworkCreateHelp(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, cFunc)
+
+	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 paramater case.
+// TODO : Handle the missing argument case in the IT when CLI is available
+/*
+func TestClientNetworkCreateMissingArgument(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, cFunc)
+
+	err := cli.Cmd("docker", "network", "create")
+	if err != nil {
+		t.Fatal(err.Error())
+	}
+}
+*/

+ 136 - 0
libnetwork/client/network.go

@@ -0,0 +1,136 @@
+package client
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+
+	flag "github.com/docker/docker/pkg/mflag"
+)
+
+// CmdNetworkCreate handles Network Create UI
+func (cli *NetworkCli) CmdNetworkCreate(chain string, args ...string) error {
+	cmd := cli.Subcmd(chain, "create", "NETWORK-NAME", chain+" create", false)
+	flDriver := cmd.String([]string{"d", "-driver"}, "", "Driver to manage the Network")
+	cmd.Require(flag.Min, 1)
+	err := cmd.ParseFlags(args, true)
+	if err != nil {
+		return err
+	}
+	if *flDriver == "" {
+		*flDriver = "bridge"
+	}
+	// TODO : Proper Backend handling
+	obj, _, err := readBody(cli.call("POST", "/networks/"+args[0], nil, nil))
+	if err != nil {
+		fmt.Fprintf(cli.err, "%s", err.Error())
+		return err
+	}
+	if _, err := io.Copy(cli.out, bytes.NewReader(obj)); err != nil {
+		return err
+	}
+	return nil
+}
+
+// CmdNetworkRm handles Network Delete UI
+func (cli *NetworkCli) CmdNetworkRm(chain string, args ...string) error {
+	cmd := cli.Subcmd(chain, "rm", "NETWORK-NAME", chain+" rm", false)
+	cmd.Require(flag.Min, 1)
+	err := cmd.ParseFlags(args, true)
+	if err != nil {
+		return err
+	}
+	// TODO : Proper Backend handling
+	obj, _, err := readBody(cli.call("DELETE", "/networks/"+args[0], nil, nil))
+	if err != nil {
+		fmt.Fprintf(cli.err, "%s", err.Error())
+		return err
+	}
+	if _, err := io.Copy(cli.out, bytes.NewReader(obj)); 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", "", chain+" ls", false)
+	err := cmd.ParseFlags(args, true)
+	if err != nil {
+		return err
+	}
+	// TODO : Proper Backend handling
+	obj, _, err := readBody(cli.call("GET", "/networks", nil, nil))
+	if err != nil {
+		fmt.Fprintf(cli.err, "%s", err.Error())
+		return err
+	}
+	if _, err := io.Copy(cli.out, bytes.NewReader(obj)); err != nil {
+		return err
+	}
+	return nil
+}
+
+// CmdNetworkInfo handles Network Info UI
+func (cli *NetworkCli) CmdNetworkInfo(chain string, args ...string) error {
+	cmd := cli.Subcmd(chain, "info", "NETWORK-NAME", chain+" info", false)
+	cmd.Require(flag.Min, 1)
+	err := cmd.ParseFlags(args, true)
+	if err != nil {
+		return err
+	}
+	// TODO : Proper Backend handling
+	obj, _, err := readBody(cli.call("GET", "/networks/"+args[0], nil, nil))
+	if err != nil {
+		fmt.Fprintf(cli.err, "%s", err.Error())
+		return err
+	}
+	if _, err := io.Copy(cli.out, bytes.NewReader(obj)); err != nil {
+		return err
+	}
+	return nil
+}
+
+// CmdNetworkJoin handles the UI to let a Container join a Network via an endpoint
+// Sample UI : <chain> network join <container-name/id> <network-name/id> [<endpoint-name>]
+func (cli *NetworkCli) CmdNetworkJoin(chain string, args ...string) error {
+	cmd := cli.Subcmd(chain, "join", "CONTAINER-NAME/ID NETWORK-NAME/ID [ENDPOINT-NAME]",
+		chain+" join", false)
+	cmd.Require(flag.Min, 2)
+	err := cmd.ParseFlags(args, true)
+	if err != nil {
+		return err
+	}
+	// TODO : Proper Backend handling
+	obj, _, err := readBody(cli.call("POST", "/endpoints/", nil, nil))
+	if err != nil {
+		fmt.Fprintf(cli.err, "%s", err.Error())
+		return err
+	}
+	if _, err := io.Copy(cli.out, bytes.NewReader(obj)); err != nil {
+		return err
+	}
+	return nil
+}
+
+// CmdNetworkLeave handles the UI to let a Container disconnect from a Network
+// Sample UI : <chain> network leave <container-name/id> <network-name/id>
+func (cli *NetworkCli) CmdNetworkLeave(chain string, args ...string) error {
+	cmd := cli.Subcmd(chain, "leave", "CONTAINER-NAME/ID NETWORK-NAME/ID",
+		chain+" leave", false)
+	cmd.Require(flag.Min, 2)
+	err := cmd.ParseFlags(args, true)
+	if err != nil {
+		return err
+	}
+	// TODO : Proper Backend handling
+	obj, _, err := readBody(cli.call("PUT", "/endpoints/", nil, nil))
+	if err != nil {
+		fmt.Fprintf(cli.err, "%s", err.Error())
+		return err
+	}
+	if _, err := io.Copy(cli.out, bytes.NewReader(obj)); err != nil {
+		return err
+	}
+	return nil
+}