diff --git a/.docker.metadata b/.docker.metadata index cd01820..ebe6974 100644 --- a/.docker.metadata +++ b/.docker.metadata @@ -1,2 +1,5 @@ -71c867c07de3e8649a69b96d8b8b3402606208fe SOURCES/codegansta.tgz -56f5602688496486e3b753da762fc0bb97c34c7c SOURCES/v1.3.2.tar.gz +6c75e788ef57c21b7f159e18cb4532e3cd7a0e61 SOURCES/3d4fd2092b1e8086c75de3db69084820e4f6d075.tar.gz +97610677bcbe57346d871d4ab7a1408282ae4af6 SOURCES/d26b358badf659627988adb88c1ba1d64c6d2f16.tar.gz +6ecb9353954061970764dde46994b3eb936cdd29 SOURCES/docker-py-0.7.1.tar.gz +520fdcc115f16321e605cd0da833e5a790ff3846 SOURCES/fb94a2822356e0bb7a481a16d553b3c9de669eb8.tar.gz +c2866909e28d1a2f821f0c06f80f25c1c9adeff5 SOURCES/websocket-client-0.14.1.tar.gz diff --git a/.gitignore b/.gitignore index 2afe20b..4abb0ac 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,5 @@ -SOURCES/codegansta.tgz -SOURCES/v1.3.2.tar.gz +SOURCES/3d4fd2092b1e8086c75de3db69084820e4f6d075.tar.gz +SOURCES/d26b358badf659627988adb88c1ba1d64c6d2f16.tar.gz +SOURCES/docker-py-0.7.1.tar.gz +SOURCES/fb94a2822356e0bb7a481a16d553b3c9de669eb8.tar.gz +SOURCES/websocket-client-0.14.1.tar.gz diff --git a/README.debrand b/README.debrand deleted file mode 100644 index 01c46d2..0000000 --- a/README.debrand +++ /dev/null @@ -1,2 +0,0 @@ -Warning: This package was configured for automatic debranding, but the changes -failed to apply. diff --git a/SOURCES/0007-validate-image-ID-properly-before-load.patch b/SOURCES/0007-validate-image-ID-properly-before-load.patch deleted file mode 100644 index 22a23cc..0000000 --- a/SOURCES/0007-validate-image-ID-properly-before-load.patch +++ /dev/null @@ -1,104 +0,0 @@ -From 4dea7eefc1a7ff0083bf47cda22247067488ace0 Mon Sep 17 00:00:00 2001 -From: unclejack -Date: Thu, 27 Nov 2014 23:55:03 +0200 -Subject: [PATCH 7/9] validate image ID properly & before load - -Signed-off-by: Cristian Staretu ---- - graph/load.go | 5 +++++ - graph/tags_unit_test.go | 2 +- - registry/registry.go | 4 ++-- - utils/utils.go | 12 +++++++----- - 4 files changed, 15 insertions(+), 8 deletions(-) - -diff --git a/graph/load.go b/graph/load.go -index fcbeef6..f27aca4 100644 ---- a/graph/load.go -+++ b/graph/load.go -@@ -12,6 +12,7 @@ import ( - "github.com/docker/docker/pkg/archive" - "github.com/docker/docker/pkg/chrootarchive" - "github.com/docker/docker/pkg/log" -+ "github.com/docker/docker/utils" - ) - - // Loads a set of images into the repository. This is the complementary of ImageExport. -@@ -112,6 +113,10 @@ func (s *TagStore) recursiveLoad(eng *engine.Engine, address, tmpImageDir string - log.Debugf("Error unmarshalling json", err) - return err - } -+ if err := utils.ValidateID(img.ID); err != nil { -+ log.Debugf("Error validating ID: %s", err) -+ return err -+ } - if img.Parent != "" { - if !s.graph.Exists(img.Parent) { - if err := s.recursiveLoad(eng, img.Parent, tmpImageDir); err != nil { -diff --git a/graph/tags_unit_test.go b/graph/tags_unit_test.go -index da51254..bf94deb 100644 ---- a/graph/tags_unit_test.go -+++ b/graph/tags_unit_test.go -@@ -16,7 +16,7 @@ import ( - - const ( - testImageName = "myapp" -- testImageID = "foo" -+ testImageID = "1a2d3c4d4e5fa2d2a21acea242a5e2345d3aefc3e7dfa2a2a2a21a2a2ad2d234" - ) - - func fakeTar() (io.Reader, error) { -diff --git a/registry/registry.go b/registry/registry.go -index a03790a..e0285a2 100644 ---- a/registry/registry.go -+++ b/registry/registry.go -@@ -23,7 +23,6 @@ var ( - ErrInvalidRepositoryName = errors.New("Invalid repository name (ex: \"registry.domain.tld/myrepos\")") - ErrDoesNotExist = errors.New("Image does not exist") - errLoginRequired = errors.New("Authentication is required.") -- validHex = regexp.MustCompile(`^([a-f0-9]{64})$`) - validNamespace = regexp.MustCompile(`^([a-z0-9_]{4,30})$`) - validRepo = regexp.MustCompile(`^([a-z0-9-_.]+)$`) - ) -@@ -177,7 +176,8 @@ func validateRepositoryName(repositoryName string) error { - namespace = "library" - name = nameParts[0] - -- if validHex.MatchString(name) { -+ // the repository name must not be a valid image ID -+ if err := utils.ValidateID(name); err == nil { - return fmt.Errorf("Invalid repository name (%s), cannot specify 64-byte hexadecimal strings", name) - } - } else { -diff --git a/utils/utils.go b/utils/utils.go -index 792b80b..4c65f13 100644 ---- a/utils/utils.go -+++ b/utils/utils.go -@@ -31,6 +31,10 @@ type KeyValuePair struct { - Value string - } - -+var ( -+ validHex = regexp.MustCompile(`^([a-f0-9]{64})$`) -+) -+ - // Request a given URL and return an io.Reader - func Download(url string) (resp *http.Response, err error) { - if resp, err = http.Get(url); err != nil { -@@ -190,11 +194,9 @@ func GenerateRandomID() string { - } - - func ValidateID(id string) error { -- if id == "" { -- return fmt.Errorf("Id can't be empty") -- } -- if strings.Contains(id, ":") { -- return fmt.Errorf("Invalid character in id: ':'") -+ if ok := validHex.MatchString(id); !ok { -+ err := fmt.Errorf("image ID '%s' is invalid", id) -+ return err - } - return nil - } --- -1.9.3 (Apple Git-50) - diff --git a/SOURCES/README.docker-logrotate b/SOURCES/README.docker-logrotate new file mode 100644 index 0000000..e142ad1 --- /dev/null +++ b/SOURCES/README.docker-logrotate @@ -0,0 +1,17 @@ +This package will install the 'docker-logrotate' script to +/etc/cron.daily. This script will run logrotate on all running +containers and ignore all failures. + +This script is enabled by default. To disable it, +uncomment the line "LOGROTATE=false" in /etc/sysconfig/docker. + +Possible issues: +1. This assumes that logrotate is installed on containers to run +successfully. + +2. A race condition occurs if a container exits before 'docker +exec' run (though it's ignored) + +3. Not all containers may need this (whether logrotate is installed or not) + +Suggestions to improve this are welcome. diff --git a/SOURCES/codegangsta-cli.patch b/SOURCES/codegangsta-cli.patch new file mode 100644 index 0000000..efa62a4 --- /dev/null +++ b/SOURCES/codegangsta-cli.patch @@ -0,0 +1,2359 @@ +diff -uNr docker-6ee24211b4111e0b1e1bd7a46c5a3c4ced1b2ffa/vendor/src/github.com/codegangsta/cli/app.go docker-1/vendor/src/github.com/codegangsta/cli/app.go +--- docker-6ee24211b4111e0b1e1bd7a46c5a3c4ced1b2ffa/vendor/src/github.com/codegangsta/cli/app.go 1969-12-31 19:00:00.000000000 -0500 ++++ docker-1/vendor/src/github.com/codegangsta/cli/app.go 2015-01-16 03:56:49.105152140 -0500 +@@ -0,0 +1,248 @@ ++package cli ++ ++import ( ++ "fmt" ++ "io/ioutil" ++ "os" ++ "time" ++) ++ ++// App is the main structure of a cli application. It is recomended that ++// and app be created with the cli.NewApp() function ++type App struct { ++ // The name of the program. Defaults to os.Args[0] ++ Name string ++ // Description of the program. ++ Usage string ++ // Version of the program ++ Version string ++ // List of commands to execute ++ Commands []Command ++ // List of flags to parse ++ Flags []Flag ++ // Boolean to enable bash completion commands ++ EnableBashCompletion bool ++ // Boolean to hide built-in help command ++ HideHelp bool ++ // An action to execute when the bash-completion flag is set ++ BashComplete func(context *Context) ++ // An action to execute before any subcommands are run, but after the context is ready ++ // If a non-nil error is returned, no subcommands are run ++ Before func(context *Context) error ++ // The action to execute when no subcommands are specified ++ Action func(context *Context) ++ // Execute this function if the proper command cannot be found ++ CommandNotFound func(context *Context, command string) ++ // Compilation date ++ Compiled time.Time ++ // Author ++ Author string ++ // Author e-mail ++ Email string ++} ++ ++// Tries to find out when this binary was compiled. ++// Returns the current time if it fails to find it. ++func compileTime() time.Time { ++ info, err := os.Stat(os.Args[0]) ++ if err != nil { ++ return time.Now() ++ } ++ return info.ModTime() ++} ++ ++// Creates a new cli Application with some reasonable defaults for Name, Usage, Version and Action. ++func NewApp() *App { ++ return &App{ ++ Name: os.Args[0], ++ Usage: "A new cli application", ++ Version: "0.0.0", ++ BashComplete: DefaultAppComplete, ++ Action: helpCommand.Action, ++ Compiled: compileTime(), ++ Author: "Author", ++ Email: "unknown@email", ++ } ++} ++ ++// Entry point to the cli app. Parses the arguments slice and routes to the proper flag/args combination ++func (a *App) Run(arguments []string) error { ++ // append help to commands ++ if a.Command(helpCommand.Name) == nil && !a.HideHelp { ++ a.Commands = append(a.Commands, helpCommand) ++ a.appendFlag(HelpFlag) ++ } ++ ++ //append version/help flags ++ if a.EnableBashCompletion { ++ a.appendFlag(BashCompletionFlag) ++ } ++ a.appendFlag(VersionFlag) ++ ++ // parse flags ++ set := flagSet(a.Name, a.Flags) ++ set.SetOutput(ioutil.Discard) ++ err := set.Parse(arguments[1:]) ++ nerr := normalizeFlags(a.Flags, set) ++ if nerr != nil { ++ fmt.Println(nerr) ++ context := NewContext(a, set, set) ++ ShowAppHelp(context) ++ fmt.Println("") ++ return nerr ++ } ++ context := NewContext(a, set, set) ++ ++ if err != nil { ++ fmt.Printf("Incorrect Usage.\n\n") ++ ShowAppHelp(context) ++ fmt.Println("") ++ return err ++ } ++ ++ if checkCompletions(context) { ++ return nil ++ } ++ ++ if checkHelp(context) { ++ return nil ++ } ++ ++ if checkVersion(context) { ++ return nil ++ } ++ ++ if a.Before != nil { ++ err := a.Before(context) ++ if err != nil { ++ return err ++ } ++ } ++ ++ args := context.Args() ++ if args.Present() { ++ name := args.First() ++ c := a.Command(name) ++ if c != nil { ++ return c.Run(context) ++ } ++ } ++ ++ // Run default Action ++ a.Action(context) ++ return nil ++} ++ ++// Another entry point to the cli app, takes care of passing arguments and error handling ++func (a *App) RunAndExitOnError() { ++ if err := a.Run(os.Args); err != nil { ++ os.Stderr.WriteString(fmt.Sprintln(err)) ++ os.Exit(1) ++ } ++} ++ ++// Invokes the subcommand given the context, parses ctx.Args() to generate command-specific flags ++func (a *App) RunAsSubcommand(ctx *Context) error { ++ // append help to commands ++ if len(a.Commands) > 0 { ++ if a.Command(helpCommand.Name) == nil && !a.HideHelp { ++ a.Commands = append(a.Commands, helpCommand) ++ a.appendFlag(HelpFlag) ++ } ++ } ++ ++ // append flags ++ if a.EnableBashCompletion { ++ a.appendFlag(BashCompletionFlag) ++ } ++ ++ // parse flags ++ set := flagSet(a.Name, a.Flags) ++ set.SetOutput(ioutil.Discard) ++ err := set.Parse(ctx.Args().Tail()) ++ nerr := normalizeFlags(a.Flags, set) ++ context := NewContext(a, set, ctx.globalSet) ++ ++ if nerr != nil { ++ fmt.Println(nerr) ++ if len(a.Commands) > 0 { ++ ShowSubcommandHelp(context) ++ } else { ++ ShowCommandHelp(ctx, context.Args().First()) ++ } ++ fmt.Println("") ++ return nerr ++ } ++ ++ if err != nil { ++ fmt.Printf("Incorrect Usage.\n\n") ++ ShowSubcommandHelp(context) ++ return err ++ } ++ ++ if checkCompletions(context) { ++ return nil ++ } ++ ++ if len(a.Commands) > 0 { ++ if checkSubcommandHelp(context) { ++ return nil ++ } ++ } else { ++ if checkCommandHelp(ctx, context.Args().First()) { ++ return nil ++ } ++ } ++ ++ if a.Before != nil { ++ err := a.Before(context) ++ if err != nil { ++ return err ++ } ++ } ++ ++ args := context.Args() ++ if args.Present() { ++ name := args.First() ++ c := a.Command(name) ++ if c != nil { ++ return c.Run(context) ++ } ++ } ++ ++ // Run default Action ++ if len(a.Commands) > 0 { ++ a.Action(context) ++ } else { ++ a.Action(ctx) ++ } ++ ++ return nil ++} ++ ++// Returns the named command on App. Returns nil if the command does not exist ++func (a *App) Command(name string) *Command { ++ for _, c := range a.Commands { ++ if c.HasName(name) { ++ return &c ++ } ++ } ++ ++ return nil ++} ++ ++func (a *App) hasFlag(flag Flag) bool { ++ for _, f := range a.Flags { ++ if flag == f { ++ return true ++ } ++ } ++ ++ return false ++} ++ ++func (a *App) appendFlag(flag Flag) { ++ if !a.hasFlag(flag) { ++ a.Flags = append(a.Flags, flag) ++ } ++} +diff -uNr docker-6ee24211b4111e0b1e1bd7a46c5a3c4ced1b2ffa/vendor/src/github.com/codegangsta/cli/app_test.go docker-1/vendor/src/github.com/codegangsta/cli/app_test.go +--- docker-6ee24211b4111e0b1e1bd7a46c5a3c4ced1b2ffa/vendor/src/github.com/codegangsta/cli/app_test.go 1969-12-31 19:00:00.000000000 -0500 ++++ docker-1/vendor/src/github.com/codegangsta/cli/app_test.go 2015-01-16 03:56:49.104152140 -0500 +@@ -0,0 +1,399 @@ ++package cli_test ++ ++import ( ++ "fmt" ++ "os" ++ "testing" ++ ++ "github.com/codegangsta/cli" ++) ++ ++func ExampleApp() { ++ // set args for examples sake ++ os.Args = []string{"greet", "--name", "Jeremy"} ++ ++ app := cli.NewApp() ++ app.Name = "greet" ++ app.Flags = []cli.Flag{ ++ cli.StringFlag{Name: "name", Value: "bob", Usage: "a name to say"}, ++ } ++ app.Action = func(c *cli.Context) { ++ fmt.Printf("Hello %v\n", c.String("name")) ++ } ++ app.Run(os.Args) ++ // Output: ++ // Hello Jeremy ++} ++ ++func ExampleAppSubcommand() { ++ // set args for examples sake ++ os.Args = []string{"say", "hi", "english", "--name", "Jeremy"} ++ app := cli.NewApp() ++ app.Name = "say" ++ app.Commands = []cli.Command{ ++ { ++ Name: "hello", ++ ShortName: "hi", ++ Usage: "use it to see a description", ++ Description: "This is how we describe hello the function", ++ Subcommands: []cli.Command{ ++ { ++ Name: "english", ++ ShortName: "en", ++ Usage: "sends a greeting in english", ++ Description: "greets someone in english", ++ Flags: []cli.Flag{ ++ cli.StringFlag{Name: "name", Value: "Bob", Usage: "Name of the person to greet"}, ++ }, ++ Action: func(c *cli.Context) { ++ fmt.Println("Hello,", c.String("name")) ++ }, ++ }, ++ }, ++ }, ++ } ++ ++ app.Run(os.Args) ++ // Output: ++ // Hello, Jeremy ++} ++ ++func ExampleAppHelp() { ++ // set args for examples sake ++ os.Args = []string{"greet", "h", "describeit"} ++ ++ app := cli.NewApp() ++ app.Name = "greet" ++ app.Flags = []cli.Flag{ ++ cli.StringFlag{Name: "name", Value: "bob", Usage: "a name to say"}, ++ } ++ app.Commands = []cli.Command{ ++ { ++ Name: "describeit", ++ ShortName: "d", ++ Usage: "use it to see a description", ++ Description: "This is how we describe describeit the function", ++ Action: func(c *cli.Context) { ++ fmt.Printf("i like to describe things") ++ }, ++ }, ++ } ++ app.Run(os.Args) ++ // Output: ++ // NAME: ++ // describeit - use it to see a description ++ // ++ // USAGE: ++ // command describeit [arguments...] ++ // ++ // DESCRIPTION: ++ // This is how we describe describeit the function ++} ++ ++func ExampleAppBashComplete() { ++ // set args for examples sake ++ os.Args = []string{"greet", "--generate-bash-completion"} ++ ++ app := cli.NewApp() ++ app.Name = "greet" ++ app.EnableBashCompletion = true ++ app.Commands = []cli.Command{ ++ { ++ Name: "describeit", ++ ShortName: "d", ++ Usage: "use it to see a description", ++ Description: "This is how we describe describeit the function", ++ Action: func(c *cli.Context) { ++ fmt.Printf("i like to describe things") ++ }, ++ }, { ++ Name: "next", ++ Usage: "next example", ++ Description: "more stuff to see when generating bash completion", ++ Action: func(c *cli.Context) { ++ fmt.Printf("the next example") ++ }, ++ }, ++ } ++ ++ app.Run(os.Args) ++ // Output: ++ // describeit ++ // d ++ // next ++ // help ++ // h ++} ++ ++func TestApp_Run(t *testing.T) { ++ s := "" ++ ++ app := cli.NewApp() ++ app.Action = func(c *cli.Context) { ++ s = s + c.Args().First() ++ } ++ ++ err := app.Run([]string{"command", "foo"}) ++ expect(t, err, nil) ++ err = app.Run([]string{"command", "bar"}) ++ expect(t, err, nil) ++ expect(t, s, "foobar") ++} ++ ++var commandAppTests = []struct { ++ name string ++ expected bool ++}{ ++ {"foobar", true}, ++ {"batbaz", true}, ++ {"b", true}, ++ {"f", true}, ++ {"bat", false}, ++ {"nothing", false}, ++} ++ ++func TestApp_Command(t *testing.T) { ++ app := cli.NewApp() ++ fooCommand := cli.Command{Name: "foobar", ShortName: "f"} ++ batCommand := cli.Command{Name: "batbaz", ShortName: "b"} ++ app.Commands = []cli.Command{ ++ fooCommand, ++ batCommand, ++ } ++ ++ for _, test := range commandAppTests { ++ expect(t, app.Command(test.name) != nil, test.expected) ++ } ++} ++ ++func TestApp_CommandWithArgBeforeFlags(t *testing.T) { ++ var parsedOption, firstArg string ++ ++ app := cli.NewApp() ++ command := cli.Command{ ++ Name: "cmd", ++ Flags: []cli.Flag{ ++ cli.StringFlag{Name: "option", Value: "", Usage: "some option"}, ++ }, ++ Action: func(c *cli.Context) { ++ parsedOption = c.String("option") ++ firstArg = c.Args().First() ++ }, ++ } ++ app.Commands = []cli.Command{command} ++ ++ app.Run([]string{"", "cmd", "my-arg", "--option", "my-option"}) ++ ++ expect(t, parsedOption, "my-option") ++ expect(t, firstArg, "my-arg") ++} ++ ++func TestApp_Float64Flag(t *testing.T) { ++ var meters float64 ++ ++ app := cli.NewApp() ++ app.Flags = []cli.Flag{ ++ cli.Float64Flag{Name: "height", Value: 1.5, Usage: "Set the height, in meters"}, ++ } ++ app.Action = func(c *cli.Context) { ++ meters = c.Float64("height") ++ } ++ ++ app.Run([]string{"", "--height", "1.93"}) ++ expect(t, meters, 1.93) ++} ++ ++func TestApp_ParseSliceFlags(t *testing.T) { ++ var parsedOption, firstArg string ++ var parsedIntSlice []int ++ var parsedStringSlice []string ++ ++ app := cli.NewApp() ++ command := cli.Command{ ++ Name: "cmd", ++ Flags: []cli.Flag{ ++ cli.IntSliceFlag{Name: "p", Value: &cli.IntSlice{}, Usage: "set one or more ip addr"}, ++ cli.StringSliceFlag{Name: "ip", Value: &cli.StringSlice{}, Usage: "set one or more ports to open"}, ++ }, ++ Action: func(c *cli.Context) { ++ parsedIntSlice = c.IntSlice("p") ++ parsedStringSlice = c.StringSlice("ip") ++ parsedOption = c.String("option") ++ firstArg = c.Args().First() ++ }, ++ } ++ app.Commands = []cli.Command{command} ++ ++ app.Run([]string{"", "cmd", "my-arg", "-p", "22", "-p", "80", "-ip", "8.8.8.8", "-ip", "8.8.4.4"}) ++ ++ IntsEquals := func(a, b []int) bool { ++ if len(a) != len(b) { ++ return false ++ } ++ for i, v := range a { ++ if v != b[i] { ++ return false ++ } ++ } ++ return true ++ } ++ ++ StrsEquals := func(a, b []string) bool { ++ if len(a) != len(b) { ++ return false ++ } ++ for i, v := range a { ++ if v != b[i] { ++ return false ++ } ++ } ++ return true ++ } ++ var expectedIntSlice = []int{22, 80} ++ var expectedStringSlice = []string{"8.8.8.8", "8.8.4.4"} ++ ++ if !IntsEquals(parsedIntSlice, expectedIntSlice) { ++ t.Errorf("%v does not match %v", parsedIntSlice, expectedIntSlice) ++ } ++ ++ if !StrsEquals(parsedStringSlice, expectedStringSlice) { ++ t.Errorf("%v does not match %v", parsedStringSlice, expectedStringSlice) ++ } ++} ++ ++func TestApp_BeforeFunc(t *testing.T) { ++ beforeRun, subcommandRun := false, false ++ beforeError := fmt.Errorf("fail") ++ var err error ++ ++ app := cli.NewApp() ++ ++ app.Before = func(c *cli.Context) error { ++ beforeRun = true ++ s := c.String("opt") ++ if s == "fail" { ++ return beforeError ++ } ++ ++ return nil ++ } ++ ++ app.Commands = []cli.Command{ ++ cli.Command{ ++ Name: "sub", ++ Action: func(c *cli.Context) { ++ subcommandRun = true ++ }, ++ }, ++ } ++ ++ app.Flags = []cli.Flag{ ++ cli.StringFlag{Name: "opt"}, ++ } ++ ++ // run with the Before() func succeeding ++ err = app.Run([]string{"command", "--opt", "succeed", "sub"}) ++ ++ if err != nil { ++ t.Fatalf("Run error: %s", err) ++ } ++ ++ if beforeRun == false { ++ t.Errorf("Before() not executed when expected") ++ } ++ ++ if subcommandRun == false { ++ t.Errorf("Subcommand not executed when expected") ++ } ++ ++ // reset ++ beforeRun, subcommandRun = false, false ++ ++ // run with the Before() func failing ++ err = app.Run([]string{"command", "--opt", "fail", "sub"}) ++ ++ // should be the same error produced by the Before func ++ if err != beforeError { ++ t.Errorf("Run error expected, but not received") ++ } ++ ++ if beforeRun == false { ++ t.Errorf("Before() not executed when expected") ++ } ++ ++ if subcommandRun == true { ++ t.Errorf("Subcommand executed when NOT expected") ++ } ++ ++} ++ ++func TestAppHelpPrinter(t *testing.T) { ++ oldPrinter := cli.HelpPrinter ++ defer func() { ++ cli.HelpPrinter = oldPrinter ++ }() ++ ++ var wasCalled = false ++ cli.HelpPrinter = func(template string, data interface{}) { ++ wasCalled = true ++ } ++ ++ app := cli.NewApp() ++ app.Run([]string{"-h"}) ++ ++ if wasCalled == false { ++ t.Errorf("Help printer expected to be called, but was not") ++ } ++} ++ ++func TestAppCommandNotFound(t *testing.T) { ++ beforeRun, subcommandRun := false, false ++ app := cli.NewApp() ++ ++ app.CommandNotFound = func(c *cli.Context, command string) { ++ beforeRun = true ++ } ++ ++ app.Commands = []cli.Command{ ++ cli.Command{ ++ Name: "bar", ++ Action: func(c *cli.Context) { ++ subcommandRun = true ++ }, ++ }, ++ } ++ ++ app.Run([]string{"command", "foo"}) ++ ++ expect(t, beforeRun, true) ++ expect(t, subcommandRun, false) ++} ++ ++func TestGlobalFlagsInSubcommands(t *testing.T) { ++ subcommandRun := false ++ app := cli.NewApp() ++ ++ app.Flags = []cli.Flag{ ++ cli.BoolFlag{Name: "debug, d", Usage: "Enable debugging"}, ++ } ++ ++ app.Commands = []cli.Command{ ++ cli.Command{ ++ Name: "foo", ++ Subcommands: []cli.Command{ ++ { ++ Name: "bar", ++ Action: func(c *cli.Context) { ++ if c.GlobalBool("debug") { ++ subcommandRun = true ++ } ++ }, ++ }, ++ }, ++ }, ++ } ++ ++ app.Run([]string{"command", "-d", "foo", "bar"}) ++ ++ expect(t, subcommandRun, true) ++} +diff -uNr docker-6ee24211b4111e0b1e1bd7a46c5a3c4ced1b2ffa/vendor/src/github.com/codegangsta/cli/autocomplete/bash_autocomplete docker-1/vendor/src/github.com/codegangsta/cli/autocomplete/bash_autocomplete +--- docker-6ee24211b4111e0b1e1bd7a46c5a3c4ced1b2ffa/vendor/src/github.com/codegangsta/cli/autocomplete/bash_autocomplete 1969-12-31 19:00:00.000000000 -0500 ++++ docker-1/vendor/src/github.com/codegangsta/cli/autocomplete/bash_autocomplete 2015-01-16 03:56:49.103152140 -0500 +@@ -0,0 +1,13 @@ ++#! /bin/bash ++ ++_cli_bash_autocomplete() { ++ local cur prev opts base ++ COMPREPLY=() ++ cur="${COMP_WORDS[COMP_CWORD]}" ++ prev="${COMP_WORDS[COMP_CWORD-1]}" ++ opts=$( ${COMP_WORDS[@]:0:COMP_CWORD} --generate-bash-completion ) ++ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) ++ return 0 ++ } ++ ++ complete -F _cli_bash_autocomplete $PROG +\ No newline at end of file +diff -uNr docker-6ee24211b4111e0b1e1bd7a46c5a3c4ced1b2ffa/vendor/src/github.com/codegangsta/cli/cli.go docker-1/vendor/src/github.com/codegangsta/cli/cli.go +--- docker-6ee24211b4111e0b1e1bd7a46c5a3c4ced1b2ffa/vendor/src/github.com/codegangsta/cli/cli.go 1969-12-31 19:00:00.000000000 -0500 ++++ docker-1/vendor/src/github.com/codegangsta/cli/cli.go 2015-01-16 03:56:49.104152140 -0500 +@@ -0,0 +1,19 @@ ++// Package cli provides a minimal framework for creating and organizing command line ++// Go applications. cli is designed to be easy to understand and write, the most simple ++// cli application can be written as follows: ++// func main() { ++// cli.NewApp().Run(os.Args) ++// } ++// ++// Of course this application does not do much, so let's make this an actual application: ++// func main() { ++// app := cli.NewApp() ++// app.Name = "greet" ++// app.Usage = "say a greeting" ++// app.Action = func(c *cli.Context) { ++// println("Greetings") ++// } ++// ++// app.Run(os.Args) ++// } ++package cli +diff -uNr docker-6ee24211b4111e0b1e1bd7a46c5a3c4ced1b2ffa/vendor/src/github.com/codegangsta/cli/cli_test.go docker-1/vendor/src/github.com/codegangsta/cli/cli_test.go +--- docker-6ee24211b4111e0b1e1bd7a46c5a3c4ced1b2ffa/vendor/src/github.com/codegangsta/cli/cli_test.go 1969-12-31 19:00:00.000000000 -0500 ++++ docker-1/vendor/src/github.com/codegangsta/cli/cli_test.go 2015-01-16 03:56:49.105152140 -0500 +@@ -0,0 +1,88 @@ ++package cli_test ++ ++import ( ++ "os" ++ ++ "github.com/codegangsta/cli" ++) ++ ++func Example() { ++ app := cli.NewApp() ++ app.Name = "todo" ++ app.Usage = "task list on the command line" ++ app.Commands = []cli.Command{ ++ { ++ Name: "add", ++ ShortName: "a", ++ Usage: "add a task to the list", ++ Action: func(c *cli.Context) { ++ println("added task: ", c.Args().First()) ++ }, ++ }, ++ { ++ Name: "complete", ++ ShortName: "c", ++ Usage: "complete a task on the list", ++ Action: func(c *cli.Context) { ++ println("completed task: ", c.Args().First()) ++ }, ++ }, ++ } ++ ++ app.Run(os.Args) ++} ++ ++func ExampleSubcommand() { ++ app := cli.NewApp() ++ app.Name = "say" ++ app.Commands = []cli.Command{ ++ { ++ Name: "hello", ++ ShortName: "hi", ++ Usage: "use it to see a description", ++ Description: "This is how we describe hello the function", ++ Subcommands: []cli.Command{ ++ { ++ Name: "english", ++ ShortName: "en", ++ Usage: "sends a greeting in english", ++ Description: "greets someone in english", ++ Flags: []cli.Flag{ ++ cli.StringFlag{Name: "name", Value: "Bob", Usage: "Name of the person to greet"}, ++ }, ++ Action: func(c *cli.Context) { ++ println("Hello, ", c.String("name")) ++ }, ++ }, { ++ Name: "spanish", ++ ShortName: "sp", ++ Usage: "sends a greeting in spanish", ++ Flags: []cli.Flag{ ++ cli.StringFlag{Name: "surname", Value: "Jones", Usage: "Surname of the person to greet"}, ++ }, ++ Action: func(c *cli.Context) { ++ println("Hola, ", c.String("surname")) ++ }, ++ }, { ++ Name: "french", ++ ShortName: "fr", ++ Usage: "sends a greeting in french", ++ Flags: []cli.Flag{ ++ cli.StringFlag{Name: "nickname", Value: "Stevie", Usage: "Nickname of the person to greet"}, ++ }, ++ Action: func(c *cli.Context) { ++ println("Bonjour, ", c.String("nickname")) ++ }, ++ }, ++ }, ++ }, { ++ Name: "bye", ++ Usage: "says goodbye", ++ Action: func(c *cli.Context) { ++ println("bye") ++ }, ++ }, ++ } ++ ++ app.Run(os.Args) ++} +diff -uNr docker-6ee24211b4111e0b1e1bd7a46c5a3c4ced1b2ffa/vendor/src/github.com/codegangsta/cli/command.go docker-1/vendor/src/github.com/codegangsta/cli/command.go +--- docker-6ee24211b4111e0b1e1bd7a46c5a3c4ced1b2ffa/vendor/src/github.com/codegangsta/cli/command.go 1969-12-31 19:00:00.000000000 -0500 ++++ docker-1/vendor/src/github.com/codegangsta/cli/command.go 2015-01-16 03:56:49.105152140 -0500 +@@ -0,0 +1,141 @@ ++package cli ++ ++import ( ++ "fmt" ++ "io/ioutil" ++ "strings" ++) ++ ++// Command is a subcommand for a cli.App. ++type Command struct { ++ // The name of the command ++ Name string ++ // short name of the command. Typically one character ++ ShortName string ++ // A short description of the usage of this command ++ Usage string ++ // A longer explanation of how the command works ++ Description string ++ // The function to call when checking for bash command completions ++ BashComplete func(context *Context) ++ // An action to execute before any sub-subcommands are run, but after the context is ready ++ // If a non-nil error is returned, no sub-subcommands are run ++ Before func(context *Context) error ++ // The function to call when this command is invoked ++ Action func(context *Context) ++ // List of child commands ++ Subcommands []Command ++ // List of flags to parse ++ Flags []Flag ++ // Treat all flags as normal arguments if true ++ SkipFlagParsing bool ++ // Boolean to hide built-in help command ++ HideHelp bool ++} ++ ++// Invokes the command given the context, parses ctx.Args() to generate command-specific flags ++func (c Command) Run(ctx *Context) error { ++ ++ if len(c.Subcommands) > 0 || c.Before != nil { ++ return c.startApp(ctx) ++ } ++ ++ if !c.HideHelp { ++ // append help to flags ++ c.Flags = append( ++ c.Flags, ++ HelpFlag, ++ ) ++ } ++ ++ if ctx.App.EnableBashCompletion { ++ c.Flags = append(c.Flags, BashCompletionFlag) ++ } ++ ++ set := flagSet(c.Name, c.Flags) ++ set.SetOutput(ioutil.Discard) ++ ++ firstFlagIndex := -1 ++ for index, arg := range ctx.Args() { ++ if strings.HasPrefix(arg, "-") { ++ firstFlagIndex = index ++ break ++ } ++ } ++ ++ var err error ++ if firstFlagIndex > -1 && !c.SkipFlagParsing { ++ args := ctx.Args() ++ regularArgs := args[1:firstFlagIndex] ++ flagArgs := args[firstFlagIndex:] ++ err = set.Parse(append(flagArgs, regularArgs...)) ++ } else { ++ err = set.Parse(ctx.Args().Tail()) ++ } ++ ++ if err != nil { ++ fmt.Printf("Incorrect Usage.\n\n") ++ ShowCommandHelp(ctx, c.Name) ++ fmt.Println("") ++ return err ++ } ++ ++ nerr := normalizeFlags(c.Flags, set) ++ if nerr != nil { ++ fmt.Println(nerr) ++ fmt.Println("") ++ ShowCommandHelp(ctx, c.Name) ++ fmt.Println("") ++ return nerr ++ } ++ context := NewContext(ctx.App, set, ctx.globalSet) ++ ++ if checkCommandCompletions(context, c.Name) { ++ return nil ++ } ++ ++ if checkCommandHelp(context, c.Name) { ++ return nil ++ } ++ context.Command = c ++ c.Action(context) ++ return nil ++} ++ ++// Returns true if Command.Name or Command.ShortName matches given name ++func (c Command) HasName(name string) bool { ++ return c.Name == name || c.ShortName == name ++} ++ ++func (c Command) startApp(ctx *Context) error { ++ app := NewApp() ++ ++ // set the name and usage ++ app.Name = fmt.Sprintf("%s %s", ctx.App.Name, c.Name) ++ if c.Description != "" { ++ app.Usage = c.Description ++ } else { ++ app.Usage = c.Usage ++ } ++ ++ // set the flags and commands ++ app.Commands = c.Subcommands ++ app.Flags = c.Flags ++ app.HideHelp = c.HideHelp ++ ++ // bash completion ++ app.EnableBashCompletion = ctx.App.EnableBashCompletion ++ if c.BashComplete != nil { ++ app.BashComplete = c.BashComplete ++ } ++ ++ // set the actions ++ app.Before = c.Before ++ if c.Action != nil { ++ app.Action = c.Action ++ } else { ++ app.Action = helpSubcommand.Action ++ } ++ ++ return app.RunAsSubcommand(ctx) ++} +diff -uNr docker-6ee24211b4111e0b1e1bd7a46c5a3c4ced1b2ffa/vendor/src/github.com/codegangsta/cli/command_test.go docker-1/vendor/src/github.com/codegangsta/cli/command_test.go +--- docker-6ee24211b4111e0b1e1bd7a46c5a3c4ced1b2ffa/vendor/src/github.com/codegangsta/cli/command_test.go 1969-12-31 19:00:00.000000000 -0500 ++++ docker-1/vendor/src/github.com/codegangsta/cli/command_test.go 2015-01-16 03:56:49.104152140 -0500 +@@ -0,0 +1,48 @@ ++package cli_test ++ ++import ( ++ "flag" ++ "github.com/codegangsta/cli" ++ "testing" ++) ++ ++func TestCommandDoNotIgnoreFlags(t *testing.T) { ++ app := cli.NewApp() ++ set := flag.NewFlagSet("test", 0) ++ test := []string{"blah", "blah", "-break"} ++ set.Parse(test) ++ ++ c := cli.NewContext(app, set, set) ++ ++ command := cli.Command { ++ Name: "test-cmd", ++ ShortName: "tc", ++ Usage: "this is for testing", ++ Description: "testing", ++ Action: func(_ *cli.Context) { }, ++ } ++ err := command.Run(c) ++ ++ expect(t, err.Error(), "flag provided but not defined: -break") ++} ++ ++func TestCommandIgnoreFlags(t *testing.T) { ++ app := cli.NewApp() ++ set := flag.NewFlagSet("test", 0) ++ test := []string{"blah", "blah"} ++ set.Parse(test) ++ ++ c := cli.NewContext(app, set, set) ++ ++ command := cli.Command { ++ Name: "test-cmd", ++ ShortName: "tc", ++ Usage: "this is for testing", ++ Description: "testing", ++ Action: func(_ *cli.Context) { }, ++ SkipFlagParsing: true, ++ } ++ err := command.Run(c) ++ ++ expect(t, err, nil) ++} +diff -uNr docker-6ee24211b4111e0b1e1bd7a46c5a3c4ced1b2ffa/vendor/src/github.com/codegangsta/cli/context.go docker-1/vendor/src/github.com/codegangsta/cli/context.go +--- docker-6ee24211b4111e0b1e1bd7a46c5a3c4ced1b2ffa/vendor/src/github.com/codegangsta/cli/context.go 1969-12-31 19:00:00.000000000 -0500 ++++ docker-1/vendor/src/github.com/codegangsta/cli/context.go 2015-01-16 03:56:49.104152140 -0500 +@@ -0,0 +1,280 @@ ++package cli ++ ++import ( ++ "errors" ++ "flag" ++ "strconv" ++ "strings" ++) ++ ++// Context is a type that is passed through to ++// each Handler action in a cli application. Context ++// can be used to retrieve context-specific Args and ++// parsed command-line options. ++type Context struct { ++ App *App ++ Command Command ++ flagSet *flag.FlagSet ++ globalSet *flag.FlagSet ++ setFlags map[string]bool ++} ++ ++// Creates a new context. For use in when invoking an App or Command action. ++func NewContext(app *App, set *flag.FlagSet, globalSet *flag.FlagSet) *Context { ++ return &Context{App: app, flagSet: set, globalSet: globalSet} ++} ++ ++// Looks up the value of a local int flag, returns 0 if no int flag exists ++func (c *Context) Int(name string) int { ++ return lookupInt(name, c.flagSet) ++} ++ ++// Looks up the value of a local float64 flag, returns 0 if no float64 flag exists ++func (c *Context) Float64(name string) float64 { ++ return lookupFloat64(name, c.flagSet) ++} ++ ++// Looks up the value of a local bool flag, returns false if no bool flag exists ++func (c *Context) Bool(name string) bool { ++ return lookupBool(name, c.flagSet) ++} ++ ++// Looks up the value of a local boolT flag, returns false if no bool flag exists ++func (c *Context) BoolT(name string) bool { ++ return lookupBoolT(name, c.flagSet) ++} ++ ++// Looks up the value of a local string flag, returns "" if no string flag exists ++func (c *Context) String(name string) string { ++ return lookupString(name, c.flagSet) ++} ++ ++// Looks up the value of a local string slice flag, returns nil if no string slice flag exists ++func (c *Context) StringSlice(name string) []string { ++ return lookupStringSlice(name, c.flagSet) ++} ++ ++// Looks up the value of a local int slice flag, returns nil if no int slice flag exists ++func (c *Context) IntSlice(name string) []int { ++ return lookupIntSlice(name, c.flagSet) ++} ++ ++// Looks up the value of a local generic flag, returns nil if no generic flag exists ++func (c *Context) Generic(name string) interface{} { ++ return lookupGeneric(name, c.flagSet) ++} ++ ++// Looks up the value of a global int flag, returns 0 if no int flag exists ++func (c *Context) GlobalInt(name string) int { ++ return lookupInt(name, c.globalSet) ++} ++ ++// Looks up the value of a global bool flag, returns false if no bool flag exists ++func (c *Context) GlobalBool(name string) bool { ++ return lookupBool(name, c.globalSet) ++} ++ ++// Looks up the value of a global string flag, returns "" if no string flag exists ++func (c *Context) GlobalString(name string) string { ++ return lookupString(name, c.globalSet) ++} ++ ++// Looks up the value of a global string slice flag, returns nil if no string slice flag exists ++func (c *Context) GlobalStringSlice(name string) []string { ++ return lookupStringSlice(name, c.globalSet) ++} ++ ++// Looks up the value of a global int slice flag, returns nil if no int slice flag exists ++func (c *Context) GlobalIntSlice(name string) []int { ++ return lookupIntSlice(name, c.globalSet) ++} ++ ++// Looks up the value of a global generic flag, returns nil if no generic flag exists ++func (c *Context) GlobalGeneric(name string) interface{} { ++ return lookupGeneric(name, c.globalSet) ++} ++ ++// Determines if the flag was actually set exists ++func (c *Context) IsSet(name string) bool { ++ if c.setFlags == nil { ++ c.setFlags = make(map[string]bool) ++ c.flagSet.Visit(func(f *flag.Flag) { ++ c.setFlags[f.Name] = true ++ }) ++ } ++ return c.setFlags[name] == true ++} ++ ++type Args []string ++ ++// Returns the command line arguments associated with the context. ++func (c *Context) Args() Args { ++ args := Args(c.flagSet.Args()) ++ return args ++} ++ ++// Returns the nth argument, or else a blank string ++func (a Args) Get(n int) string { ++ if len(a) > n { ++ return a[n] ++ } ++ return "" ++} ++ ++// Returns the first argument, or else a blank string ++func (a Args) First() string { ++ return a.Get(0) ++} ++ ++// Return the rest of the arguments (not the first one) ++// or else an empty string slice ++func (a Args) Tail() []string { ++ if len(a) >= 2 { ++ return []string(a)[1:] ++ } ++ return []string{} ++} ++ ++// Checks if there are any arguments present ++func (a Args) Present() bool { ++ return len(a) != 0 ++} ++ ++// Swaps arguments at the given indexes ++func (a Args) Swap(from, to int) error { ++ if from >= len(a) || to >= len(a) { ++ return errors.New("index out of range") ++ } ++ a[from], a[to] = a[to], a[from] ++ return nil ++} ++ ++func lookupInt(name string, set *flag.FlagSet) int { ++ f := set.Lookup(name) ++ if f != nil { ++ val, err := strconv.Atoi(f.Value.String()) ++ if err != nil { ++ return 0 ++ } ++ return val ++ } ++ ++ return 0 ++} ++ ++func lookupFloat64(name string, set *flag.FlagSet) float64 { ++ f := set.Lookup(name) ++ if f != nil { ++ val, err := strconv.ParseFloat(f.Value.String(), 64) ++ if err != nil { ++ return 0 ++ } ++ return val ++ } ++ ++ return 0 ++} ++ ++func lookupString(name string, set *flag.FlagSet) string { ++ f := set.Lookup(name) ++ if f != nil { ++ return f.Value.String() ++ } ++ ++ return "" ++} ++ ++func lookupStringSlice(name string, set *flag.FlagSet) []string { ++ f := set.Lookup(name) ++ if f != nil { ++ return (f.Value.(*StringSlice)).Value() ++ ++ } ++ ++ return nil ++} ++ ++func lookupIntSlice(name string, set *flag.FlagSet) []int { ++ f := set.Lookup(name) ++ if f != nil { ++ return (f.Value.(*IntSlice)).Value() ++ ++ } ++ ++ return nil ++} ++ ++func lookupGeneric(name string, set *flag.FlagSet) interface{} { ++ f := set.Lookup(name) ++ if f != nil { ++ return f.Value ++ } ++ return nil ++} ++ ++func lookupBool(name string, set *flag.FlagSet) bool { ++ f := set.Lookup(name) ++ if f != nil { ++ val, err := strconv.ParseBool(f.Value.String()) ++ if err != nil { ++ return false ++ } ++ return val ++ } ++ ++ return false ++} ++ ++func lookupBoolT(name string, set *flag.FlagSet) bool { ++ f := set.Lookup(name) ++ if f != nil { ++ val, err := strconv.ParseBool(f.Value.String()) ++ if err != nil { ++ return true ++ } ++ return val ++ } ++ ++ return false ++} ++ ++func copyFlag(name string, ff *flag.Flag, set *flag.FlagSet) { ++ switch ff.Value.(type) { ++ case *StringSlice: ++ default: ++ set.Set(name, ff.Value.String()) ++ } ++} ++ ++func normalizeFlags(flags []Flag, set *flag.FlagSet) error { ++ visited := make(map[string]bool) ++ set.Visit(func(f *flag.Flag) { ++ visited[f.Name] = true ++ }) ++ for _, f := range flags { ++ parts := strings.Split(f.getName(), ",") ++ if len(parts) == 1 { ++ continue ++ } ++ var ff *flag.Flag ++ for _, name := range parts { ++ name = strings.Trim(name, " ") ++ if visited[name] { ++ if ff != nil { ++ return errors.New("Cannot use two forms of the same flag: " + name + " " + ff.Name) ++ } ++ ff = set.Lookup(name) ++ } ++ } ++ if ff == nil { ++ continue ++ } ++ for _, name := range parts { ++ name = strings.Trim(name, " ") ++ if !visited[name] { ++ copyFlag(name, ff, set) ++ } ++ } ++ } ++ return nil ++} +diff -uNr docker-6ee24211b4111e0b1e1bd7a46c5a3c4ced1b2ffa/vendor/src/github.com/codegangsta/cli/context_test.go docker-1/vendor/src/github.com/codegangsta/cli/context_test.go +--- docker-6ee24211b4111e0b1e1bd7a46c5a3c4ced1b2ffa/vendor/src/github.com/codegangsta/cli/context_test.go 1969-12-31 19:00:00.000000000 -0500 ++++ docker-1/vendor/src/github.com/codegangsta/cli/context_test.go 2015-01-16 03:56:49.104152140 -0500 +@@ -0,0 +1,68 @@ ++package cli_test ++ ++import ( ++ "flag" ++ "github.com/codegangsta/cli" ++ "testing" ++) ++ ++func TestNewContext(t *testing.T) { ++ set := flag.NewFlagSet("test", 0) ++ set.Int("myflag", 12, "doc") ++ globalSet := flag.NewFlagSet("test", 0) ++ globalSet.Int("myflag", 42, "doc") ++ command := cli.Command{Name: "mycommand"} ++ c := cli.NewContext(nil, set, globalSet) ++ c.Command = command ++ expect(t, c.Int("myflag"), 12) ++ expect(t, c.GlobalInt("myflag"), 42) ++ expect(t, c.Command.Name, "mycommand") ++} ++ ++func TestContext_Int(t *testing.T) { ++ set := flag.NewFlagSet("test", 0) ++ set.Int("myflag", 12, "doc") ++ c := cli.NewContext(nil, set, set) ++ expect(t, c.Int("myflag"), 12) ++} ++ ++func TestContext_String(t *testing.T) { ++ set := flag.NewFlagSet("test", 0) ++ set.String("myflag", "hello world", "doc") ++ c := cli.NewContext(nil, set, set) ++ expect(t, c.String("myflag"), "hello world") ++} ++ ++func TestContext_Bool(t *testing.T) { ++ set := flag.NewFlagSet("test", 0) ++ set.Bool("myflag", false, "doc") ++ c := cli.NewContext(nil, set, set) ++ expect(t, c.Bool("myflag"), false) ++} ++ ++func TestContext_BoolT(t *testing.T) { ++ set := flag.NewFlagSet("test", 0) ++ set.Bool("myflag", true, "doc") ++ c := cli.NewContext(nil, set, set) ++ expect(t, c.BoolT("myflag"), true) ++} ++ ++func TestContext_Args(t *testing.T) { ++ set := flag.NewFlagSet("test", 0) ++ set.Bool("myflag", false, "doc") ++ c := cli.NewContext(nil, set, set) ++ set.Parse([]string{"--myflag", "bat", "baz"}) ++ expect(t, len(c.Args()), 2) ++ expect(t, c.Bool("myflag"), true) ++} ++ ++func TestContext_IsSet(t *testing.T) { ++ set := flag.NewFlagSet("test", 0) ++ set.Bool("myflag", false, "doc") ++ set.String("otherflag", "hello world", "doc") ++ c := cli.NewContext(nil, set, set) ++ set.Parse([]string{"--myflag", "bat", "baz"}) ++ expect(t, c.IsSet("myflag"), true) ++ expect(t, c.IsSet("otherflag"), false) ++ expect(t, c.IsSet("bogusflag"), false) ++} +diff -uNr docker-6ee24211b4111e0b1e1bd7a46c5a3c4ced1b2ffa/vendor/src/github.com/codegangsta/cli/flag.go docker-1/vendor/src/github.com/codegangsta/cli/flag.go +--- docker-6ee24211b4111e0b1e1bd7a46c5a3c4ced1b2ffa/vendor/src/github.com/codegangsta/cli/flag.go 1969-12-31 19:00:00.000000000 -0500 ++++ docker-1/vendor/src/github.com/codegangsta/cli/flag.go 2015-01-16 03:56:49.103152140 -0500 +@@ -0,0 +1,280 @@ ++package cli ++ ++import ( ++ "flag" ++ "fmt" ++ "strconv" ++ "strings" ++) ++ ++// This flag enables bash-completion for all commands and subcommands ++var BashCompletionFlag = BoolFlag{"generate-bash-completion", ""} ++ ++// This flag prints the version for the application ++var VersionFlag = BoolFlag{"version, v", "print the version"} ++ ++// This flag prints the help for all commands and subcommands ++var HelpFlag = BoolFlag{"help, h", "show help"} ++ ++// Flag is a common interface related to parsing flags in cli. ++// For more advanced flag parsing techniques, it is recomended that ++// this interface be implemented. ++type Flag interface { ++ fmt.Stringer ++ // Apply Flag settings to the given flag set ++ Apply(*flag.FlagSet) ++ getName() string ++} ++ ++func flagSet(name string, flags []Flag) *flag.FlagSet { ++ set := flag.NewFlagSet(name, flag.ContinueOnError) ++ ++ for _, f := range flags { ++ f.Apply(set) ++ } ++ return set ++} ++ ++func eachName(longName string, fn func(string)) { ++ parts := strings.Split(longName, ",") ++ for _, name := range parts { ++ name = strings.Trim(name, " ") ++ fn(name) ++ } ++} ++ ++// Generic is a generic parseable type identified by a specific flag ++type Generic interface { ++ Set(value string) error ++ String() string ++} ++ ++// GenericFlag is the flag type for types implementing Generic ++type GenericFlag struct { ++ Name string ++ Value Generic ++ Usage string ++} ++ ++func (f GenericFlag) String() string { ++ return fmt.Sprintf("%s%s %v\t`%v` %s", prefixFor(f.Name), f.Name, f.Value, "-"+f.Name+" option -"+f.Name+" option", f.Usage) ++} ++ ++func (f GenericFlag) Apply(set *flag.FlagSet) { ++ eachName(f.Name, func(name string) { ++ set.Var(f.Value, name, f.Usage) ++ }) ++} ++ ++func (f GenericFlag) getName() string { ++ return f.Name ++} ++ ++type StringSlice []string ++ ++func (f *StringSlice) Set(value string) error { ++ *f = append(*f, value) ++ return nil ++} ++ ++func (f *StringSlice) String() string { ++ return fmt.Sprintf("%s", *f) ++} ++ ++func (f *StringSlice) Value() []string { ++ return *f ++} ++ ++type StringSliceFlag struct { ++ Name string ++ Value *StringSlice ++ Usage string ++} ++ ++func (f StringSliceFlag) String() string { ++ firstName := strings.Trim(strings.Split(f.Name, ",")[0], " ") ++ pref := prefixFor(firstName) ++ return fmt.Sprintf("%s '%v'\t%v", prefixedNames(f.Name), pref+firstName+" option "+pref+firstName+" option", f.Usage) ++} ++ ++func (f StringSliceFlag) Apply(set *flag.FlagSet) { ++ eachName(f.Name, func(name string) { ++ set.Var(f.Value, name, f.Usage) ++ }) ++} ++ ++func (f StringSliceFlag) getName() string { ++ return f.Name ++} ++ ++type IntSlice []int ++ ++func (f *IntSlice) Set(value string) error { ++ ++ tmp, err := strconv.Atoi(value) ++ if err != nil { ++ return err ++ } else { ++ *f = append(*f, tmp) ++ } ++ return nil ++} ++ ++func (f *IntSlice) String() string { ++ return fmt.Sprintf("%d", *f) ++} ++ ++func (f *IntSlice) Value() []int { ++ return *f ++} ++ ++type IntSliceFlag struct { ++ Name string ++ Value *IntSlice ++ Usage string ++} ++ ++func (f IntSliceFlag) String() string { ++ firstName := strings.Trim(strings.Split(f.Name, ",")[0], " ") ++ pref := prefixFor(firstName) ++ return fmt.Sprintf("%s '%v'\t%v", prefixedNames(f.Name), pref+firstName+" option "+pref+firstName+" option", f.Usage) ++} ++ ++func (f IntSliceFlag) Apply(set *flag.FlagSet) { ++ eachName(f.Name, func(name string) { ++ set.Var(f.Value, name, f.Usage) ++ }) ++} ++ ++func (f IntSliceFlag) getName() string { ++ return f.Name ++} ++ ++type BoolFlag struct { ++ Name string ++ Usage string ++} ++ ++func (f BoolFlag) String() string { ++ return fmt.Sprintf("%s\t%v", prefixedNames(f.Name), f.Usage) ++} ++ ++func (f BoolFlag) Apply(set *flag.FlagSet) { ++ eachName(f.Name, func(name string) { ++ set.Bool(name, false, f.Usage) ++ }) ++} ++ ++func (f BoolFlag) getName() string { ++ return f.Name ++} ++ ++type BoolTFlag struct { ++ Name string ++ Usage string ++} ++ ++func (f BoolTFlag) String() string { ++ return fmt.Sprintf("%s\t%v", prefixedNames(f.Name), f.Usage) ++} ++ ++func (f BoolTFlag) Apply(set *flag.FlagSet) { ++ eachName(f.Name, func(name string) { ++ set.Bool(name, true, f.Usage) ++ }) ++} ++ ++func (f BoolTFlag) getName() string { ++ return f.Name ++} ++ ++type StringFlag struct { ++ Name string ++ Value string ++ Usage string ++} ++ ++func (f StringFlag) String() string { ++ var fmtString string ++ fmtString = "%s %v\t%v" ++ ++ if len(f.Value) > 0 { ++ fmtString = "%s '%v'\t%v" ++ } else { ++ fmtString = "%s %v\t%v" ++ } ++ ++ return fmt.Sprintf(fmtString, prefixedNames(f.Name), f.Value, f.Usage) ++} ++ ++func (f StringFlag) Apply(set *flag.FlagSet) { ++ eachName(f.Name, func(name string) { ++ set.String(name, f.Value, f.Usage) ++ }) ++} ++ ++func (f StringFlag) getName() string { ++ return f.Name ++} ++ ++type IntFlag struct { ++ Name string ++ Value int ++ Usage string ++} ++ ++func (f IntFlag) String() string { ++ return fmt.Sprintf("%s '%v'\t%v", prefixedNames(f.Name), f.Value, f.Usage) ++} ++ ++func (f IntFlag) Apply(set *flag.FlagSet) { ++ eachName(f.Name, func(name string) { ++ set.Int(name, f.Value, f.Usage) ++ }) ++} ++ ++func (f IntFlag) getName() string { ++ return f.Name ++} ++ ++type Float64Flag struct { ++ Name string ++ Value float64 ++ Usage string ++} ++ ++func (f Float64Flag) String() string { ++ return fmt.Sprintf("%s '%v'\t%v", prefixedNames(f.Name), f.Value, f.Usage) ++} ++ ++func (f Float64Flag) Apply(set *flag.FlagSet) { ++ eachName(f.Name, func(name string) { ++ set.Float64(name, f.Value, f.Usage) ++ }) ++} ++ ++func (f Float64Flag) getName() string { ++ return f.Name ++} ++ ++func prefixFor(name string) (prefix string) { ++ if len(name) == 1 { ++ prefix = "-" ++ } else { ++ prefix = "--" ++ } ++ ++ return ++} ++ ++func prefixedNames(fullName string) (prefixed string) { ++ parts := strings.Split(fullName, ",") ++ for i, name := range parts { ++ name = strings.Trim(name, " ") ++ prefixed += prefixFor(name) + name ++ if i < len(parts)-1 { ++ prefixed += ", " ++ } ++ } ++ return ++} +diff -uNr docker-6ee24211b4111e0b1e1bd7a46c5a3c4ced1b2ffa/vendor/src/github.com/codegangsta/cli/flag_test.go docker-1/vendor/src/github.com/codegangsta/cli/flag_test.go +--- docker-6ee24211b4111e0b1e1bd7a46c5a3c4ced1b2ffa/vendor/src/github.com/codegangsta/cli/flag_test.go 1969-12-31 19:00:00.000000000 -0500 ++++ docker-1/vendor/src/github.com/codegangsta/cli/flag_test.go 2015-01-16 03:56:49.103152140 -0500 +@@ -0,0 +1,194 @@ ++package cli_test ++ ++import ( ++ "github.com/codegangsta/cli" ++ ++ "fmt" ++ "reflect" ++ "strings" ++ "testing" ++) ++ ++var boolFlagTests = []struct { ++ name string ++ expected string ++}{ ++ {"help", "--help\t"}, ++ {"h", "-h\t"}, ++} ++ ++func TestBoolFlagHelpOutput(t *testing.T) { ++ ++ for _, test := range boolFlagTests { ++ flag := cli.BoolFlag{Name: test.name} ++ output := flag.String() ++ ++ if output != test.expected { ++ t.Errorf("%s does not match %s", output, test.expected) ++ } ++ } ++} ++ ++var stringFlagTests = []struct { ++ name string ++ value string ++ expected string ++}{ ++ {"help", "", "--help \t"}, ++ {"h", "", "-h \t"}, ++ {"h", "", "-h \t"}, ++ {"test", "Something", "--test 'Something'\t"}, ++} ++ ++func TestStringFlagHelpOutput(t *testing.T) { ++ ++ for _, test := range stringFlagTests { ++ flag := cli.StringFlag{Name: test.name, Value: test.value} ++ output := flag.String() ++ ++ if output != test.expected { ++ t.Errorf("%s does not match %s", output, test.expected) ++ } ++ } ++} ++ ++var intFlagTests = []struct { ++ name string ++ expected string ++}{ ++ {"help", "--help '0'\t"}, ++ {"h", "-h '0'\t"}, ++} ++ ++func TestIntFlagHelpOutput(t *testing.T) { ++ ++ for _, test := range intFlagTests { ++ flag := cli.IntFlag{Name: test.name} ++ output := flag.String() ++ ++ if output != test.expected { ++ t.Errorf("%s does not match %s", output, test.expected) ++ } ++ } ++} ++ ++var float64FlagTests = []struct { ++ name string ++ expected string ++}{ ++ {"help", "--help '0'\t"}, ++ {"h", "-h '0'\t"}, ++} ++ ++func TestFloat64FlagHelpOutput(t *testing.T) { ++ ++ for _, test := range float64FlagTests { ++ flag := cli.Float64Flag{Name: test.name} ++ output := flag.String() ++ ++ if output != test.expected { ++ t.Errorf("%s does not match %s", output, test.expected) ++ } ++ } ++} ++ ++func TestParseMultiString(t *testing.T) { ++ (&cli.App{ ++ Flags: []cli.Flag{ ++ cli.StringFlag{Name: "serve, s"}, ++ }, ++ Action: func(ctx *cli.Context) { ++ if ctx.String("serve") != "10" { ++ t.Errorf("main name not set") ++ } ++ if ctx.String("s") != "10" { ++ t.Errorf("short name not set") ++ } ++ }, ++ }).Run([]string{"run", "-s", "10"}) ++} ++ ++func TestParseMultiStringSlice(t *testing.T) { ++ (&cli.App{ ++ Flags: []cli.Flag{ ++ cli.StringSliceFlag{Name: "serve, s", Value: &cli.StringSlice{}}, ++ }, ++ Action: func(ctx *cli.Context) { ++ if !reflect.DeepEqual(ctx.StringSlice("serve"), []string{"10", "20"}) { ++ t.Errorf("main name not set") ++ } ++ if !reflect.DeepEqual(ctx.StringSlice("s"), []string{"10", "20"}) { ++ t.Errorf("short name not set") ++ } ++ }, ++ }).Run([]string{"run", "-s", "10", "-s", "20"}) ++} ++ ++func TestParseMultiInt(t *testing.T) { ++ a := cli.App{ ++ Flags: []cli.Flag{ ++ cli.IntFlag{Name: "serve, s"}, ++ }, ++ Action: func(ctx *cli.Context) { ++ if ctx.Int("serve") != 10 { ++ t.Errorf("main name not set") ++ } ++ if ctx.Int("s") != 10 { ++ t.Errorf("short name not set") ++ } ++ }, ++ } ++ a.Run([]string{"run", "-s", "10"}) ++} ++ ++func TestParseMultiBool(t *testing.T) { ++ a := cli.App{ ++ Flags: []cli.Flag{ ++ cli.BoolFlag{Name: "serve, s"}, ++ }, ++ Action: func(ctx *cli.Context) { ++ if ctx.Bool("serve") != true { ++ t.Errorf("main name not set") ++ } ++ if ctx.Bool("s") != true { ++ t.Errorf("short name not set") ++ } ++ }, ++ } ++ a.Run([]string{"run", "--serve"}) ++} ++ ++type Parser [2]string ++ ++func (p *Parser) Set(value string) error { ++ parts := strings.Split(value, ",") ++ if len(parts) != 2 { ++ return fmt.Errorf("invalid format") ++ } ++ ++ (*p)[0] = parts[0] ++ (*p)[1] = parts[1] ++ ++ return nil ++} ++ ++func (p *Parser) String() string { ++ return fmt.Sprintf("%s,%s", p[0], p[1]) ++} ++ ++func TestParseGeneric(t *testing.T) { ++ a := cli.App{ ++ Flags: []cli.Flag{ ++ cli.GenericFlag{Name: "serve, s", Value: &Parser{}}, ++ }, ++ Action: func(ctx *cli.Context) { ++ if !reflect.DeepEqual(ctx.Generic("serve"), &Parser{"10", "20"}) { ++ t.Errorf("main name not set") ++ } ++ if !reflect.DeepEqual(ctx.Generic("s"), &Parser{"10", "20"}) { ++ t.Errorf("short name not set") ++ } ++ }, ++ } ++ a.Run([]string{"run", "-s", "10,20"}) ++} +diff -uNr docker-6ee24211b4111e0b1e1bd7a46c5a3c4ced1b2ffa/vendor/src/github.com/codegangsta/cli/helpers_test.go docker-1/vendor/src/github.com/codegangsta/cli/helpers_test.go +--- docker-6ee24211b4111e0b1e1bd7a46c5a3c4ced1b2ffa/vendor/src/github.com/codegangsta/cli/helpers_test.go 1969-12-31 19:00:00.000000000 -0500 ++++ docker-1/vendor/src/github.com/codegangsta/cli/helpers_test.go 2015-01-16 03:56:49.104152140 -0500 +@@ -0,0 +1,19 @@ ++package cli_test ++ ++import ( ++ "reflect" ++ "testing" ++) ++ ++/* Test Helpers */ ++func expect(t *testing.T, a interface{}, b interface{}) { ++ if a != b { ++ t.Errorf("Expected %v (type %v) - Got %v (type %v)", b, reflect.TypeOf(b), a, reflect.TypeOf(a)) ++ } ++} ++ ++func refute(t *testing.T, a interface{}, b interface{}) { ++ if a == b { ++ t.Errorf("Did not expect %v (type %v) - Got %v (type %v)", b, reflect.TypeOf(b), a, reflect.TypeOf(a)) ++ } ++} +diff -uNr docker-6ee24211b4111e0b1e1bd7a46c5a3c4ced1b2ffa/vendor/src/github.com/codegangsta/cli/help.go docker-1/vendor/src/github.com/codegangsta/cli/help.go +--- docker-6ee24211b4111e0b1e1bd7a46c5a3c4ced1b2ffa/vendor/src/github.com/codegangsta/cli/help.go 1969-12-31 19:00:00.000000000 -0500 ++++ docker-1/vendor/src/github.com/codegangsta/cli/help.go 2015-01-16 03:56:49.104152140 -0500 +@@ -0,0 +1,213 @@ ++package cli ++ ++import ( ++ "fmt" ++ "os" ++ "text/tabwriter" ++ "text/template" ++) ++ ++// The text template for the Default help topic. ++// cli.go uses text/template to render templates. You can ++// render custom help text by setting this variable. ++var AppHelpTemplate = `NAME: ++ {{.Name}} - {{.Usage}} ++ ++USAGE: ++ {{.Name}} {{ if .Flags }}[global options] {{ end }}command{{ if .Flags }} [command options]{{ end }} [arguments...] ++ ++VERSION: ++ {{.Version}} ++ ++COMMANDS: ++ {{range .Commands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}} ++ {{end}}{{ if .Flags }} ++GLOBAL OPTIONS: ++ {{range .Flags}}{{.}} ++ {{end}}{{ end }} ++` ++ ++// The text template for the command help topic. ++// cli.go uses text/template to render templates. You can ++// render custom help text by setting this variable. ++var CommandHelpTemplate = `NAME: ++ {{.Name}} - {{.Usage}} ++ ++USAGE: ++ command {{.Name}}{{ if .Flags }} [command options]{{ end }} [arguments...] ++ ++DESCRIPTION: ++ {{.Description}}{{ if .Flags }} ++ ++OPTIONS: ++ {{range .Flags}}{{.}} ++ {{end}}{{ end }} ++` ++ ++// The text template for the subcommand help topic. ++// cli.go uses text/template to render templates. You can ++// render custom help text by setting this variable. ++var SubcommandHelpTemplate = `NAME: ++ {{.Name}} - {{.Usage}} ++ ++USAGE: ++ {{.Name}} command{{ if .Flags }} [command options]{{ end }} [arguments...] ++ ++COMMANDS: ++ {{range .Commands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}} ++ {{end}}{{ if .Flags }} ++OPTIONS: ++ {{range .Flags}}{{.}} ++ {{end}}{{ end }} ++` ++ ++var helpCommand = Command{ ++ Name: "help", ++ ShortName: "h", ++ Usage: "Shows a list of commands or help for one command", ++ Action: func(c *Context) { ++ args := c.Args() ++ if args.Present() { ++ ShowCommandHelp(c, args.First()) ++ } else { ++ ShowAppHelp(c) ++ } ++ }, ++} ++ ++var helpSubcommand = Command{ ++ Name: "help", ++ ShortName: "h", ++ Usage: "Shows a list of commands or help for one command", ++ Action: func(c *Context) { ++ args := c.Args() ++ if args.Present() { ++ ShowCommandHelp(c, args.First()) ++ } else { ++ ShowSubcommandHelp(c) ++ } ++ }, ++} ++ ++// Prints help for the App ++var HelpPrinter = printHelp ++ ++func ShowAppHelp(c *Context) { ++ HelpPrinter(AppHelpTemplate, c.App) ++} ++ ++// Prints the list of subcommands as the default app completion method ++func DefaultAppComplete(c *Context) { ++ for _, command := range c.App.Commands { ++ fmt.Println(command.Name) ++ if command.ShortName != "" { ++ fmt.Println(command.ShortName) ++ } ++ } ++} ++ ++// Prints help for the given command ++func ShowCommandHelp(c *Context, command string) { ++ for _, c := range c.App.Commands { ++ if c.HasName(command) { ++ HelpPrinter(CommandHelpTemplate, c) ++ return ++ } ++ } ++ ++ if c.App.CommandNotFound != nil { ++ c.App.CommandNotFound(c, command) ++ } else { ++ fmt.Printf("No help topic for '%v'\n", command) ++ } ++} ++ ++// Prints help for the given subcommand ++func ShowSubcommandHelp(c *Context) { ++ HelpPrinter(SubcommandHelpTemplate, c.App) ++} ++ ++// Prints the version number of the App ++func ShowVersion(c *Context) { ++ fmt.Printf("%v version %v\n", c.App.Name, c.App.Version) ++} ++ ++// Prints the lists of commands within a given context ++func ShowCompletions(c *Context) { ++ a := c.App ++ if a != nil && a.BashComplete != nil { ++ a.BashComplete(c) ++ } ++} ++ ++// Prints the custom completions for a given command ++func ShowCommandCompletions(ctx *Context, command string) { ++ c := ctx.App.Command(command) ++ if c != nil && c.BashComplete != nil { ++ c.BashComplete(ctx) ++ } ++} ++ ++func printHelp(templ string, data interface{}) { ++ w := tabwriter.NewWriter(os.Stdout, 0, 8, 1, '\t', 0) ++ t := template.Must(template.New("help").Parse(templ)) ++ err := t.Execute(w, data) ++ if err != nil { ++ panic(err) ++ } ++ w.Flush() ++} ++ ++func checkVersion(c *Context) bool { ++ if c.GlobalBool("version") { ++ ShowVersion(c) ++ return true ++ } ++ ++ return false ++} ++ ++func checkHelp(c *Context) bool { ++ if c.GlobalBool("h") || c.GlobalBool("help") { ++ ShowAppHelp(c) ++ return true ++ } ++ ++ return false ++} ++ ++func checkCommandHelp(c *Context, name string) bool { ++ if c.Bool("h") || c.Bool("help") { ++ ShowCommandHelp(c, name) ++ return true ++ } ++ ++ return false ++} ++ ++func checkSubcommandHelp(c *Context) bool { ++ if c.GlobalBool("h") || c.GlobalBool("help") { ++ ShowSubcommandHelp(c) ++ return true ++ } ++ ++ return false ++} ++ ++func checkCompletions(c *Context) bool { ++ if c.GlobalBool(BashCompletionFlag.Name) && c.App.EnableBashCompletion { ++ ShowCompletions(c) ++ return true ++ } ++ ++ return false ++} ++ ++func checkCommandCompletions(c *Context, name string) bool { ++ if c.Bool(BashCompletionFlag.Name) && c.App.EnableBashCompletion { ++ ShowCommandCompletions(c, name) ++ return true ++ } ++ ++ return false ++} +diff -uNr docker-6ee24211b4111e0b1e1bd7a46c5a3c4ced1b2ffa/vendor/src/github.com/codegangsta/cli/LICENSE docker-1/vendor/src/github.com/codegangsta/cli/LICENSE +--- docker-6ee24211b4111e0b1e1bd7a46c5a3c4ced1b2ffa/vendor/src/github.com/codegangsta/cli/LICENSE 1969-12-31 19:00:00.000000000 -0500 ++++ docker-1/vendor/src/github.com/codegangsta/cli/LICENSE 2015-01-16 03:56:49.105152140 -0500 +@@ -0,0 +1,21 @@ ++Copyright (C) 2013 Jeremy Saenz ++All Rights Reserved. ++ ++MIT LICENSE ++ ++Permission is hereby granted, free of charge, to any person obtaining a copy of ++this software and associated documentation files (the "Software"), to deal in ++the Software without restriction, including without limitation the rights to ++use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of ++the Software, and to permit persons to whom the Software is furnished to do so, ++subject to the following conditions: ++ ++The above copyright notice and this permission notice shall be included in all ++copies or substantial portions of the Software. ++ ++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS ++FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR ++COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER ++IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN ++CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +diff -uNr docker-6ee24211b4111e0b1e1bd7a46c5a3c4ced1b2ffa/vendor/src/github.com/codegangsta/cli/README.md docker-1/vendor/src/github.com/codegangsta/cli/README.md +--- docker-6ee24211b4111e0b1e1bd7a46c5a3c4ced1b2ffa/vendor/src/github.com/codegangsta/cli/README.md 1969-12-31 19:00:00.000000000 -0500 ++++ docker-1/vendor/src/github.com/codegangsta/cli/README.md 2015-01-16 03:56:49.105152140 -0500 +@@ -0,0 +1,257 @@ ++[![Build Status](https://travis-ci.org/codegangsta/cli.png?branch=master)](https://travis-ci.org/codegangsta/cli) ++ ++# cli.go ++cli.go is simple, fast, and fun package for building command line apps in Go. The goal is to enable developers to write fast and distributable command line applications in an expressive way. ++ ++You can view the API docs here: ++http://godoc.org/github.com/codegangsta/cli ++ ++## Overview ++Command line apps are usually so tiny that there is absolutely no reason why your code should *not* be self-documenting. Things like generating help text and parsing command flags/options should not hinder productivity when writing a command line app. ++ ++This is where cli.go comes into play. cli.go makes command line programming fun, organized, and expressive! ++ ++## Installation ++Make sure you have a working Go environment (go 1.1 is *required*). [See the install instructions](http://golang.org/doc/install.html). ++ ++To install cli.go, simply run: ++``` ++$ go get github.com/codegangsta/cli ++``` ++ ++Make sure your PATH includes to the `$GOPATH/bin` directory so your commands can be easily used: ++``` ++export PATH=$PATH:$GOPATH/bin ++``` ++ ++## Getting Started ++One of the philosophies behind cli.go is that an API should be playful and full of discovery. So a cli.go app can be as little as one line of code in `main()`. ++ ++``` go ++package main ++ ++import ( ++ "os" ++ "github.com/codegangsta/cli" ++) ++ ++func main() { ++ cli.NewApp().Run(os.Args) ++} ++``` ++ ++This app will run and show help text, but is not very useful. Let's give an action to execute and some help documentation: ++ ++``` go ++package main ++ ++import ( ++ "os" ++ "github.com/codegangsta/cli" ++) ++ ++func main() { ++ app := cli.NewApp() ++ app.Name = "boom" ++ app.Usage = "make an explosive entrance" ++ app.Action = func(c *cli.Context) { ++ println("boom! I say!") ++ } ++ ++ app.Run(os.Args) ++} ++``` ++ ++Running this already gives you a ton of functionality, plus support for things like subcommands and flags, which are covered below. ++ ++## Example ++ ++Being a programmer can be a lonely job. Thankfully by the power of automation that is not the case! Let's create a greeter app to fend off our demons of loneliness! ++ ++``` go ++/* greet.go */ ++package main ++ ++import ( ++ "os" ++ "github.com/codegangsta/cli" ++) ++ ++func main() { ++ app := cli.NewApp() ++ app.Name = "greet" ++ app.Usage = "fight the loneliness!" ++ app.Action = func(c *cli.Context) { ++ println("Hello friend!") ++ } ++ ++ app.Run(os.Args) ++} ++``` ++ ++Install our command to the `$GOPATH/bin` directory: ++ ++``` ++$ go install ++``` ++ ++Finally run our new command: ++ ++``` ++$ greet ++Hello friend! ++``` ++ ++cli.go also generates some bitchass help text: ++``` ++$ greet help ++NAME: ++ greet - fight the loneliness! ++ ++USAGE: ++ greet [global options] command [command options] [arguments...] ++ ++VERSION: ++ 0.0.0 ++ ++COMMANDS: ++ help, h Shows a list of commands or help for one command ++ ++GLOBAL OPTIONS ++ --version Shows version information ++``` ++ ++### Arguments ++You can lookup arguments by calling the `Args` function on cli.Context. ++ ++``` go ++... ++app.Action = func(c *cli.Context) { ++ println("Hello", c.Args()[0]) ++} ++... ++``` ++ ++### Flags ++Setting and querying flags is simple. ++``` go ++... ++app.Flags = []cli.Flag { ++ cli.StringFlag{Name: "lang", Value: "english", Usage: "language for the greeting"}, ++} ++app.Action = func(c *cli.Context) { ++ name := "someone" ++ if len(c.Args()) > 0 { ++ name = c.Args()[0] ++ } ++ if c.String("lang") == "spanish" { ++ println("Hola", name) ++ } else { ++ println("Hello", name) ++ } ++} ++... ++``` ++ ++#### Alternate Names ++ ++You can set alternate (or short) names for flags by providing a comma-delimited list for the Name. e.g. ++ ++``` go ++app.Flags = []cli.Flag { ++ cli.StringFlag{Name: "lang, l", Value: "english", Usage: "language for the greeting"}, ++} ++``` ++ ++That flag can then be set with `--lang spanish` or `-l spanish`. Note that giving two different forms of the same flag in the same command invocation is an error. ++ ++### Subcommands ++ ++Subcommands can be defined for a more git-like command line app. ++```go ++... ++app.Commands = []cli.Command{ ++ { ++ Name: "add", ++ ShortName: "a", ++ Usage: "add a task to the list", ++ Action: func(c *cli.Context) { ++ println("added task: ", c.Args().First()) ++ }, ++ }, ++ { ++ Name: "complete", ++ ShortName: "c", ++ Usage: "complete a task on the list", ++ Action: func(c *cli.Context) { ++ println("completed task: ", c.Args().First()) ++ }, ++ }, ++ { ++ Name: "template", ++ ShortName: "r", ++ Usage: "options for task templates", ++ Subcommands: []cli.Command{ ++ { ++ Name: "add", ++ Usage: "add a new template", ++ Action: func(c *cli.Context) { ++ println("new task template: ", c.Args().First()) ++ }, ++ }, ++ { ++ Name: "remove", ++ Usage: "remove an existing template", ++ Action: func(c *cli.Context) { ++ println("removed task template: ", c.Args().First()) ++ }, ++ }, ++ }, ++ }, ++} ++... ++``` ++ ++### Bash Completion ++ ++You can enable completion commands by setting the EnableBashCompletion ++flag on the App object. By default, this setting will only auto-complete to ++show an app's subcommands, but you can write your own completion methods for ++the App or its subcommands. ++```go ++... ++var tasks = []string{"cook", "clean", "laundry", "eat", "sleep", "code"} ++app := cli.NewApp() ++app.EnableBashCompletion = true ++app.Commands = []cli.Command{ ++ { ++ Name: "complete", ++ ShortName: "c", ++ Usage: "complete a task on the list", ++ Action: func(c *cli.Context) { ++ println("completed task: ", c.Args().First()) ++ }, ++ BashComplete: func(c *cli.Context) { ++ // This will complete if no args are passed ++ if len(c.Args()) > 0 { ++ return ++ } ++ for _, t := range tasks { ++ println(t) ++ } ++ }, ++ } ++} ++... ++``` ++ ++#### To Enable ++ ++Source the autocomplete/bash_autocomplete file in your .bashrc file while ++setting the PROG variable to the name of your program: ++ ++`PROG=myprogram source /.../cli/autocomplete/bash_autocomplete` ++ ++ ++## About ++cli.go is written by none other than the [Code Gangsta](http://codegangsta.io) +diff -uNr docker-6ee24211b4111e0b1e1bd7a46c5a3c4ced1b2ffa/vendor/src/github.com/codegangsta/cli/.travis.yml docker-1/vendor/src/github.com/codegangsta/cli/.travis.yml +--- docker-6ee24211b4111e0b1e1bd7a46c5a3c4ced1b2ffa/vendor/src/github.com/codegangsta/cli/.travis.yml 1969-12-31 19:00:00.000000000 -0500 ++++ docker-1/vendor/src/github.com/codegangsta/cli/.travis.yml 2015-01-16 03:56:49.104152140 -0500 +@@ -0,0 +1,6 @@ ++language: go ++go: 1.1 ++ ++script: ++- go vet ./... ++- go test -v ./... diff --git a/SOURCES/docker-cert-path.patch b/SOURCES/docker-cert-path.patch new file mode 100644 index 0000000..62d337c --- /dev/null +++ b/SOURCES/docker-cert-path.patch @@ -0,0 +1,35 @@ +From 2bc25525096c60d32c49c506477e3585e8613182 Mon Sep 17 00:00:00 2001 +From: Jessica Frazelle +Date: Tue, 9 Dec 2014 14:18:25 -0800 +Subject: [PATCH] Change cert path to /etc/docker for root user + +Docker-DCO-1.1-Signed-off-by: Jessica Frazelle (github: jfrazelle) +--- + docker/flags.go | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/docker/flags.go b/docker/flags.go +index 6601b4f..0866519 100644 +--- a/docker/flags.go ++++ b/docker/flags.go +@@ -3,6 +3,7 @@ package main + import ( + "fmt" + "os" ++ "os/user" + "path/filepath" + "runtime" + +@@ -17,7 +18,11 @@ var ( + + func init() { + if dockerCertPath == "" { +- dockerCertPath = filepath.Join(getHomeDir(), ".docker") ++ if currentUser, err := user.Current(); err != nil || currentUser.Uid == "0" { ++ dockerCertPath = "/etc/docker" ++ } else { ++ dockerCertPath = filepath.Join(getHomeDir(), ".docker") ++ } + } + } + diff --git a/SOURCES/docker-logrotate.sh b/SOURCES/docker-logrotate.sh new file mode 100644 index 0000000..27fb979 --- /dev/null +++ b/SOURCES/docker-logrotate.sh @@ -0,0 +1,11 @@ +#!/bin/sh + +LOGROTATE=true +[ -f /etc/sysconfig/docker ] && source /etc/sysconfig/docker + +if [ $LOGROTATE == true ]; then + for id in $(docker ps -q); do + exec $(docker exec $id logrotate -s /var/log/logstatus /etc/logrotate.conf > /dev/null 2&>1) + done +fi +exit 0 diff --git a/SOURCES/docker-network.sysconfig b/SOURCES/docker-network.sysconfig new file mode 100644 index 0000000..048d158 --- /dev/null +++ b/SOURCES/docker-network.sysconfig @@ -0,0 +1,2 @@ +# /etc/sysconfig/docker-network +DOCKER_NETWORK_OPTIONS= diff --git a/SOURCES/docker-py-remove-lock.patch b/SOURCES/docker-py-remove-lock.patch new file mode 100644 index 0000000..087e1ab --- /dev/null +++ b/SOURCES/docker-py-remove-lock.patch @@ -0,0 +1,41 @@ +From 8699e821282802626210fd1d78f982975611f3ed Mon Sep 17 00:00:00 2001 +From: Lokesh Mandvekar +Date: Fri, 23 Jan 2015 17:43:42 -0500 +Subject: [PATCH] remove lock for rhel7 + +Signed-off-by: Lokesh Mandvekar +--- + docker/unixconn/unixconn.py | 17 ++++++++--------- + 1 file changed, 8 insertions(+), 9 deletions(-) + +diff --git a/docker/unixconn/unixconn.py b/docker/unixconn/unixconn.py +index 1f18060..57c98a5 100644 +--- a/docker/unixconn/unixconn.py ++++ b/docker/unixconn/unixconn.py +@@ -72,15 +72,14 @@ class UnixAdapter(requests.adapters.HTTPAdapter): + super(UnixAdapter, self).__init__() + + def get_connection(self, socket_path, proxies=None): +- with self.pools.lock: +- pool = self.pools.get(socket_path) +- if pool: +- return pool +- +- pool = UnixHTTPConnectionPool( +- self.base_url, socket_path, self.timeout +- ) +- self.pools[socket_path] = pool ++ pool = self.pools.get(socket_path) ++ if pool: ++ return pool ++ ++ pool = UnixHTTPConnectionPool( ++ self.base_url, socket_path, self.timeout ++ ) ++ self.pools[socket_path] = pool + + return pool + +-- +1.8.3.1 + diff --git a/SOURCES/docker.service b/SOURCES/docker.service index 469bdb4..ad4fcf4 100644 --- a/SOURCES/docker.service +++ b/SOURCES/docker.service @@ -1,17 +1,22 @@ [Unit] Description=Docker Application Container Engine Documentation=http://docs.docker.com -After=network.target docker.socket -Requires=docker.socket +After=network.target [Service] Type=notify EnvironmentFile=-/etc/sysconfig/docker EnvironmentFile=-/etc/sysconfig/docker-storage -ExecStart=/usr/bin/docker -d $OPTIONS $DOCKER_STORAGE_OPTIONS +EnvironmentFile=-/etc/sysconfig/docker-network +ExecStart=/usr/bin/docker -d $OPTIONS \ + $DOCKER_STORAGE_OPTIONS \ + $DOCKER_NETWORK_OPTIONS \ + $ADD_REGISTRY \ + $BLOCK_REGISTRY \ + $INSECURE_REGISTRY LimitNOFILE=1048576 LimitNPROC=1048576 -MountFlags=private +MountFlags=slave [Install] WantedBy=multi-user.target diff --git a/SOURCES/docker.sysconfig b/SOURCES/docker.sysconfig index 1613870..b01c93c 100644 --- a/SOURCES/docker.sysconfig +++ b/SOURCES/docker.sysconfig @@ -1,9 +1,35 @@ # /etc/sysconfig/docker # Modify these options if you want to change the way the docker daemon runs -OPTIONS=--selinux-enabled -H fd:// +OPTIONS='--selinux-enabled' + +DOCKER_CERT_PATH=/etc/docker + +# If you want to add your own registry to be used for docker search and docker pull use the +# ADD_REGISTRY option to list a set of comma separated registries. +# Note the last registry added will be the first regisry searched. +# +ADD_REGISTRY='--add-registry registry.access.redhat.com' + +# If you want to block registries from being used, use the +# BLOCK_REGISTRY option to list a set of comma separated registries, and uncommenting +# it. For example adding docker.io will stop users from downloading images from docker.io +# BLOCK_REGISTRY='--block-registry ' + +# If you have a registry secured with https but do not have proper certs destributed, you can +# tell docker to not look for full authorization by adding the registry to the +# INSECURE_REGISTRY line and uncommentin it. +# INSECURE_REGISTRY='--insecure-registry' + +# On an SELinux system, if you remove the --selinux-enabled option, you +# also need to turn on the docker_transition_unconfined boolean. +# setsebool -P docker_transition_unconfined 1 # Location used for temporary files, such as those created by # docker load and build operations. Default is /var/lib/docker/tmp # Can be overriden by setting the following environment variable. # DOCKER_TMPDIR=/var/tmp + +# Controls the /etc/cron.daily/docker-logrotate cron job status. +# To disable, uncomment the line below. +# LOGROTATE=false diff --git a/SOURCES/secrets.patch b/SOURCES/secrets.patch deleted file mode 100644 index dd5e12e..0000000 --- a/SOURCES/secrets.patch +++ /dev/null @@ -1,217 +0,0 @@ -From ed97ccf535888a5e1fa2cadf42d01089e1192e06 Mon Sep 17 00:00:00 2001 -From: Dan Walsh -Date: Thu, 13 Nov 2014 15:28:39 -0500 -Subject: [PATCH] Super Secrets Patch - -Docker-DCO-1.1-Signed-off-by: Dan Walsh (github: rhatdan) ---- - daemon/container.go | 48 +++++++++++++++++++++++++++++- - daemon/secrets.go | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++++ - daemon/volumes.go | 11 +++++++ - graph/graph.go | 1 + - 4 files changed, 145 insertions(+), 1 deletion(-) - create mode 100644 daemon/secrets.go - -diff --git a/daemon/container.go b/daemon/container.go -index 2ac8316..b754105 100644 ---- a/daemon/container.go -+++ b/daemon/container.go -@@ -338,11 +338,28 @@ func (container *Container) Start() (err error) { - if err := populateCommand(container, env); err != nil { - return err - } -+ if err := container.setupSecretFiles(); err != nil { -+ return err -+ } - if err := container.setupMounts(); err != nil { - return err - } - -- return container.waitForStart() -+ if err := container.waitForStart(); err != nil { -+ return err -+ } -+ -+ // Now the container is running, unmount the secrets on the host -+ secretsPath, err := container.secretsPath() -+ if err != nil { -+ return err -+ } -+ -+ if err := syscall.Unmount(secretsPath, syscall.MNT_DETACH); err != nil { -+ return err -+ } -+ -+ return nil - } - - func (container *Container) Run() error { -@@ -793,6 +810,10 @@ func (container *Container) jsonPath() (string, error) { - return container.getRootResourcePath("config.json") - } - -+func (container *Container) secretsPath() (string, error) { -+ return container.getRootResourcePath("secrets") -+} -+ - // This method must be exported to be used from the lxc template - // This directory is only usable when the container is running - func (container *Container) RootfsPath() string { -@@ -1064,6 +1085,31 @@ func (container *Container) verifyDaemonSettings() { - } - } - -+func (container *Container) setupSecretFiles() error { -+ secretsPath, err := container.secretsPath() -+ if err != nil { -+ return err -+ } -+ -+ if err := os.MkdirAll(secretsPath, 0700); err != nil { -+ return err -+ } -+ -+ if err := syscall.Mount("tmpfs", secretsPath, "tmpfs", uintptr(syscall.MS_NOEXEC|syscall.MS_NOSUID|syscall.MS_NODEV), label.FormatMountLabel("", container.GetMountLabel())); err != nil { -+ return fmt.Errorf("mounting secret tmpfs: %s", err) -+ } -+ -+ data, err := getHostSecretData() -+ if err != nil { -+ return err -+ } -+ for _, s := range data { -+ s.SaveTo(secretsPath) -+ } -+ -+ return nil -+} -+ - func (container *Container) setupLinkedContainers() ([]string, error) { - var ( - env []string -diff --git a/daemon/secrets.go b/daemon/secrets.go -new file mode 100644 -index 0000000..8bd97a5 ---- /dev/null -+++ b/daemon/secrets.go -@@ -0,0 +1,86 @@ -+package daemon -+ -+import ( -+ "io/ioutil" -+ "os" -+ "path/filepath" -+) -+ -+type Secret struct { -+ Name string -+ IsDir bool -+ HostBased bool -+} -+ -+type SecretData struct { -+ Name string -+ Data []byte -+} -+ -+func (s SecretData) SaveTo(dir string) error { -+ path := filepath.Join(dir, s.Name) -+ if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil && !os.IsExist(err) { -+ return err -+ } -+ if err := ioutil.WriteFile(path, s.Data, 0755); err != nil { -+ return err -+ } -+ return nil -+} -+ -+func readAll(root, prefix string) ([]SecretData, error) { -+ path := filepath.Join(root, prefix) -+ -+ data := []SecretData{} -+ -+ files, err := ioutil.ReadDir(path) -+ if err != nil { -+ if os.IsNotExist(err) { -+ return data, nil -+ } -+ -+ return nil, err -+ } -+ -+ for _, f := range files { -+ fileData, err := readFile(root, filepath.Join(prefix, f.Name())) -+ if err != nil { -+ // If the file did not exist, might be a dangling symlink -+ // Ignore the error -+ if os.IsNotExist(err) { -+ continue -+ } -+ return nil, err -+ } -+ data = append(data, fileData...) -+ } -+ -+ return data, nil -+} -+ -+func readFile(root, name string) ([]SecretData, error) { -+ path := filepath.Join(root, name) -+ -+ s, err := os.Stat(path) -+ if err != nil { -+ return nil, err -+ } -+ -+ if s.IsDir() { -+ dirData, err := readAll(root, name) -+ if err != nil { -+ return nil, err -+ } -+ return dirData, nil -+ } else { -+ bytes, err := ioutil.ReadFile(path) -+ if err != nil { -+ return nil, err -+ } -+ return []SecretData{{Name: name, Data: bytes}}, nil -+ } -+} -+ -+func getHostSecretData() ([]SecretData, error) { -+ return readAll("/usr/share/rhel/secrets", "") -+} -diff --git a/daemon/volumes.go b/daemon/volumes.go -index 6523dae..322d3f4 100644 ---- a/daemon/volumes.go -+++ b/daemon/volumes.go -@@ -260,6 +260,17 @@ func (container *Container) setupMounts() error { - }) - } - -+ secretsPath, err := container.secretsPath() -+ if err != nil { -+ return err -+ } -+ -+ mounts = append(mounts, execdriver.Mount{ -+ Source: secretsPath, -+ Destination: "/run/secrets", -+ Writable: true, -+ }) -+ - container.command.Mounts = mounts - return nil - } -diff --git a/graph/graph.go b/graph/graph.go -index 720f6e6..647b64d 100644 ---- a/graph/graph.go -+++ b/graph/graph.go -@@ -242,6 +242,7 @@ func SetupInitLayer(initLayer string) error { - "/etc/hostname": "file", - "/dev/console": "file", - "/etc/mtab": "/proc/mounts", -+ "/run/secrets": "dir", - } { - parts := strings.Split(pth, "/") - prev := "/" diff --git a/SOURCES/urlparse.patch b/SOURCES/urlparse.patch new file mode 100644 index 0000000..8e1ae7a --- /dev/null +++ b/SOURCES/urlparse.patch @@ -0,0 +1,15 @@ +diff -uNr websocket/__init__.py websocket-1/__init__.py +--- websocket/__init__.py 2014-05-07 21:53:31.000000000 -0400 ++++ websocket-1/__init__.py 2015-01-23 12:34:41.231543225 -0500 +@@ -40,7 +40,10 @@ + + HAVE_SSL = False + +-from six.moves.urllib.parse import urlparse ++try: ++ from six.moves.urllib.parse import urlparse ++except: ++ import urlparse + if six.PY3: + from base64 import encodebytes as base64encode + else: diff --git a/SPECS/docker.spec b/SPECS/docker.spec index 7b381a5..fc44a58 100644 --- a/SPECS/docker.spec +++ b/SPECS/docker.spec @@ -1,6 +1,18 @@ # modifying the dockerinit binary breaks the SHA1 sum check by docker %global __os_install_post %{_rpmconfigdir}/brp-compress +# no python3 subpackage for docker-py +%global with_python3 0 + +# for python-websocket-client, prefix with w_ +%global w_modname websocket +%global w_distname websocket-client +%global w_eggname websocket_client +%global w_version 0.14.1 + +# for docker-python, prefix with dp_ +%global dp_version 0.7.1 + #debuginfo not supported with Go %global debug_package %{nil} %global provider_tld com @@ -8,29 +20,47 @@ %global project docker %global repo docker %global common_path %{provider}.%{provider_tld}/%{project} +%global d_version 1.4.1 %global import_path %{common_path}/%{repo} %global import_path_libcontainer %{common_path}/libcontainer -%global commit 39fa2faad2f3d6fa5133de4eb740677202f53ef4 +%global commit d26b358badf659627988adb88c1ba1d64c6d2f16 %global shortcommit %(c=%{commit}; echo ${c:0:7}) +%global atom_commit 3d4fd2092b1e8086c75de3db69084820e4f6d075 + +%global utils_commit fb94a2822356e0bb7a481a16d553b3c9de669eb8 + Name: docker -Version: 1.3.2 -Release: 4%{?dist} +Version: %{d_version} +Release: 37%{?dist} Summary: Automates deployment of containerized applications License: ASL 2.0 URL: http://www.docker.com # only x86_64 for now: https://github.com/docker/docker/issues/136 ExclusiveArch: x86_64 -Source0: https://%{import_path}/archive/v%{version}.tar.gz -Patch1: go-md2man.patch -Patch2: 0007-validate-image-ID-properly-before-load.patch -Patch3: secrets.patch +#Source0: https://%{import_path}/archive/v%{version}.tar.gz +Source0: https://github.com/rhatdan/docker/archive/%{commit}.tar.gz Source1: docker.service -Source2: codegansta.tgz Source3: docker.sysconfig -Source5: docker-storage.sysconfig +Source4: docker-storage.sysconfig +Source5: docker-logrotate.sh +Source6: README.docker-logrotate +Source7: docker-network.sysconfig +# Source8 is the source tarball for python-websocket-client +Source8: http://pypi.python.org/packages/source/w/%{w_distname}/%{w_distname}-%{w_version}.tar.gz +# Source9 is the source tarball for docker-py +Source9: http://pypi.python.org/packages/source/d/docker-py/docker-py-%{dp_version}.tar.gz +# Source10 is the source tarball for atomic +Source10: https://github.com/rhatdan/atom/archive/%{atom_commit}.tar.gz +# Source11 is the source tarball for dockertarsum and docker-fetch +Source11: https://github.com/vbatts/docker-utils/archive/%{utils_commit}.tar.gz +Patch1: go-md2man.patch +Patch2: docker-cert-path.patch +Patch3: codegangsta-cli.patch +Patch4: urlparse.patch +Patch5: docker-py-remove-lock.patch BuildRequires: glibc-static BuildRequires: golang >= 1.3.1 BuildRequires: device-mapper-devel @@ -38,14 +68,14 @@ BuildRequires: btrfs-progs-devel BuildRequires: sqlite-devel BuildRequires: pkgconfig(systemd) # appropriate systemd version as per rhbz#1171054 -Requires: systemd-units >= 208-11.el7_0.5 +Requires: systemd # need xz to work with ubuntu images Requires: xz Requires: device-mapper-libs >= 1.02.90-1 -Provides: lxc-docker = %{version} -Provides: docker = %{version} -Provides: docker-io = %{version} -Provides: nsinit +Requires: subscription-manager +Provides: lxc-docker = %{d_version}-%{release} +Provides: docker = %{d_version}-%{release} +Provides: docker-io = %{d_version}-%{release} %description Docker is an open-source engine that automates the deployment of any @@ -57,139 +87,86 @@ and between virtually any server. The same container that a developer builds and tests on a laptop will run at scale, in production*, on VMs, bare-metal servers, OpenStack clusters, public instances, or combinations of the above. -%package devel -BuildRequires: golang >= 1.3.1 -Requires: golang >= 1.3.1 -Summary: A golang registry for global request variables (source libraries) -Provides: docker-pkg-devel docker-io-devel docker-io-pkg-devel -Provides: golang(%{import_path}) = %{version}-%{release} -Provides: golang(%{import_path}/api) = %{version}-%{release} -Provides: golang(%{import_path}/api/client) = %{version}-%{release} -Provides: golang(%{import_path}/api/server) = %{version}-%{release} -Provides: golang(%{import_path}/builder) = %{version}-%{release} -Provides: golang(%{import_path}/builder/parser) = %{version}-%{release} -Provides: golang(%{import_path}/builder/parser/dumper) = %{version}-%{release} -Provides: golang(%{import_path}/builtins) = %{version}-%{release} -Provides: golang(%{import_path}/contrib/docker-device-tool) = %{version}-%{release} -Provides: golang(%{import_path}/contrib/host-integration) = %{version}-%{release} -Provides: golang(%{import_path}/daemon) = %{version}-%{release} -Provides: golang(%{import_path}/daemon/execdriver) = %{version}-%{release} -Provides: golang(%{import_path}/daemon/execdriver/execdrivers) = %{version}-%{release} -Provides: golang(%{import_path}/daemon/execdriver/lxc) = %{version}-%{release} -Provides: golang(%{import_path}/daemon/execdriver/native) = %{version}-%{release} -Provides: golang(%{import_path}/daemon/execdriver/native/template) = %{version}-%{release} -Provides: golang(%{import_path}/daemon/graphdriver) = %{version}-%{release} -Provides: golang(%{import_path}/daemon/graphdriver/aufs) = %{version}-%{release} -Provides: golang(%{import_path}/daemon/graphdriver/btrfs) = %{version}-%{release} -Provides: golang(%{import_path}/daemon/graphdriver/devmapper) = %{version}-%{release} -Provides: golang(%{import_path}/daemon/graphdriver/graphtest) = %{version}-%{release} -Provides: golang(%{import_path}/daemon/graphdriver/vfs) = %{version}-%{release} -Provides: golang(%{import_path}/daemon/networkdriver) = %{version}-%{release} -Provides: golang(%{import_path}/daemon/networkdriver/bridge) = %{version}-%{release} -Provides: golang(%{import_path}/daemon/networkdriver/ipallocator) = %{version}-%{release} -Provides: golang(%{import_path}/daemon/networkdriver/portallocator) = %{version}-%{release} -Provides: golang(%{import_path}/daemon/networkdriver/portmapper) = %{version}-%{release} -Provides: golang(%{import_path}/dockerversion) = %{version}-%{release} -Provides: golang(%{import_path}/engine) = %{version}-%{release} -Provides: golang(%{import_path}/events) = %{version}-%{release} -Provides: golang(%{import_path}/graph) = %{version}-%{release} -Provides: golang(%{import_path}/image) = %{version}-%{release} -Provides: golang(%{import_path}/integration) = %{version}-%{release} -Provides: golang(%{import_path}/integration-cli) = %{version}-%{release} -Provides: golang(%{import_path}/links) = %{version}-%{release} -Provides: golang(%{import_path}/nat) = %{version}-%{release} -Provides: golang(%{import_path}/opts) = %{version}-%{release} -Provides: golang(%{import_path}/registry) = %{version}-%{release} -Provides: golang(%{import_path}/runconfig) = %{version}-%{release} -Provides: golang(%{import_path}/trust) = %{version}-%{release} -Provides: golang(%{import_path}/utils) = %{version}-%{release} -Provides: golang(%{import_path}/volumes) = %{version}-%{release} -Provides: golang(%{import_path}/pkg/archive) = %{version}-%{release} -Provides: golang(%{import_path}/pkg/broadcastwriter) = %{version}-%{release} -Provides: golang(%{import_path}/pkg/chrootarchive) = %{version}-%{release} -Provides: golang(%{import_path}/pkg/fileutils) = %{version}-%{release} -Provides: golang(%{import_path}/pkg/graphdb) = %{version}-%{release} -Provides: golang(%{import_path}/pkg/httputils) = %{version}-%{release} -Provides: golang(%{import_path}/pkg/ioutils) = %{version}-%{release} -Provides: golang(%{import_path}/pkg/iptables) = %{version}-%{release} -Provides: golang(%{import_path}/pkg/jsonlog) = %{version}-%{release} -Provides: golang(%{import_path}/pkg/listenbuffer) = %{version}-%{release} -Provides: golang(%{import_path}/pkg/log) = %{version}-%{release} -Provides: golang(%{import_path}/pkg/mflag) = %{version}-%{release} -Provides: golang(%{import_path}/pkg/mflag/example) = %{version}-%{release} -Provides: golang(%{import_path}/pkg/mount) = %{version}-%{release} -Provides: golang(%{import_path}/pkg/namesgenerator) = %{version}-%{release} -Provides: golang(%{import_path}/pkg/networkfs/etchosts) = %{version}-%{release} -Provides: golang(%{import_path}/pkg/networkfs/resolvconf) = %{version}-%{release} -Provides: golang(%{import_path}/pkg/parsers) = %{version}-%{release} -Provides: golang(%{import_path}/pkg/parsers/filters) = %{version}-%{release} -Provides: golang(%{import_path}/pkg/parsers/kernel) = %{version}-%{release} -Provides: golang(%{import_path}/pkg/parsers/operatingsystem) = %{version}-%{release} -Provides: golang(%{import_path}/pkg/pools) = %{version}-%{release} -Provides: golang(%{import_path}/pkg/promise) = %{version}-%{release} -Provides: golang(%{import_path}/pkg/proxy) = %{version}-%{release} -Provides: golang(%{import_path}/pkg/reexec) = %{version}-%{release} -Provides: golang(%{import_path}/pkg/signal) = %{version}-%{release} -Provides: golang(%{import_path}/pkg/stdcopy) = %{version}-%{release} -Provides: golang(%{import_path}/pkg/symlink) = %{version}-%{release} -Provides: golang(%{import_path}/pkg/sysinfo) = %{version}-%{release} -Provides: golang(%{import_path}/pkg/system) = %{version}-%{release} -Provides: golang(%{import_path}/pkg/systemd) = %{version}-%{release} -Provides: golang(%{import_path}/pkg/tailfile) = %{version}-%{release} -Provides: golang(%{import_path}/pkg/tarsum) = %{version}-%{release} -Provides: golang(%{import_path}/pkg/term) = %{version}-%{release} -Provides: golang(%{import_path}/pkg/testutils) = %{version}-%{release} -Provides: golang(%{import_path}/pkg/timeutils) = %{version}-%{release} -Provides: golang(%{import_path}/pkg/truncindex) = %{version}-%{release} -Provides: golang(%{import_path}/pkg/units) = %{version}-%{release} -Provides: golang(%{import_path}/pkg/version) = %{version}-%{release} -Provides: golang(%{import_path_libcontainer}) = %{version}-%{release} -Provides: golang(%{import_path_libcontainer}/apparmor) = %{version}-%{release} -Provides: golang(%{import_path_libcontainer}/cgroups) = %{version}-%{release} -Provides: golang(%{import_path_libcontainer}/cgroups/fs) = %{version}-%{release} -Provides: golang(%{import_path_libcontainer}/cgroups/systemd) = %{version}-%{release} -Provides: golang(%{import_path_libcontainer}/console) = %{version}-%{release} -Provides: golang(%{import_path_libcontainer}/devices) = %{version}-%{release} -Provides: golang(%{import_path_libcontainer}/label) = %{version}-%{release} -Provides: golang(%{import_path_libcontainer}/mount) = %{version}-%{release} -Provides: golang(%{import_path_libcontainer}/mount/nodes) = %{version}-%{release} -Provides: golang(%{import_path_libcontainer}/namespaces) = %{version}-%{release} -Provides: golang(%{import_path_libcontainer}/namespaces/nsenter) = %{version}-%{release} -Provides: golang(%{import_path_libcontainer}/netlink) = %{version}-%{release} -Provides: golang(%{import_path_libcontainer}/network) = %{version}-%{release} -Provides: golang(%{import_path_libcontainer}/nsinit) = %{version}-%{release} -Provides: golang(%{import_path_libcontainer}/security/capabilities) = %{version}-%{release} -Provides: golang(%{import_path_libcontainer}/security/restrict) = %{version}-%{release} -Provides: golang(%{import_path_libcontainer}/selinux) = %{version}-%{release} -Provides: golang(%{import_path_libcontainer}/syncpipe) = %{version}-%{release} -Provides: golang(%{import_path_libcontainer}/system) = %{version}-%{release} -Provides: golang(%{import_path_libcontainer}/user) = %{version}-%{release} -Provides: golang(%{import_path_libcontainer}/utils) = %{version}-%{release} -Provides: golang(%{import_path_libcontainer}/xattr) = %{version}-%{release} - -Obsoletes: golang-github-docker-libcontainer-devel - -%description devel -This is the source libraries for docker. +%package logrotate +Summary: cron job to run logrotate on docker containers +Requires: docker = %{version}-%{release} +Provides: docker-io-logrotate = %{version}-%{release} + +%description logrotate +This package installs %{summary}. logrotate is assumed to be installed on +containers for this to work, failures are silently ignored. + +%package -n python-%{w_distname} +Summary: WebSocket client for python +Version: %{w_version} +License: LGPLv2 +BuildArch: noarch + +%description -n python-%{w_distname} +python-websocket-client module is WebSocket client for python. This +provides the low level APIs for WebSocket. All APIs are the synchronous +functions. + +python-websocket-client supports only hybi-13. + +%package python +Version: %{dp_version} +License: ASL 2.0 +Summary: An API client for docker written in Python +BuildRequires: python2-devel +BuildRequires: python-setuptools +BuildRequires: python-tools +BuildRequires: python-requests +Requires: docker >= %{d_version}-%{release} +Requires: python-requests +Requires: python-%{w_distname} >= 0.11.0 +Requires: python-six >= 1.3.0 +Requires: python-argparse +Provides: python-docker-py = %{dp_version}-%{release} +Provides: python-docker = %{dp_version}-%{release} + +%description python +%{summary} %prep -%setup -qn docker-%{version} +%setup -qn docker-%{commit} %patch1 -p1 %patch2 -p1 %patch3 -p1 -rm daemon/*.orig -tar zxf %{SOURCE2} +cp %{SOURCE6} . + +# untar docker-utils tarball +tar zxf %{SOURCE11} + +# untar python-websocket-client tarball +tar zxf %{SOURCE8} +rm -rf %{w_distname}-%{w_version}/%{w_distname}.egg-info +pushd %{w_distname}-%{w_version}/websocket +%patch4 -p1 +popd + +# untar docker-py tarball +tar zxf %{SOURCE9} +pushd docker-py-%{dp_version} +%patch5 -p1 +popd + +# untar atom +tar zxf %{SOURCE10} +sed -i '/pylint/d' atom-%{atom_commit}/Makefile +cp atom-%{atom_commit}/docs/* ./docs/man/. %build mkdir _build pushd _build - mkdir -p src/github.com/docker + mkdir -p src/github.com/{docker,vbatts} ln -s $(dirs +1 -l) src/github.com/docker/docker + ln -s $(dirs +1 -l)/docker-utils-%{utils_commit} src/github.com/vbatts/docker-utils popd -export DOCKER_GITCOMMIT="%{shortcommit}/%{version}" -export DOCKER_BUILDTAGS='selinux' +export DOCKER_GITCOMMIT="%{shortcommit}/%{d_version}" +export DOCKER_BUILDTAGS='selinux btrfs_noversion' export GOPATH=$(pwd)/_build:$(pwd)/vendor:%{gopath} # build docker binary @@ -198,10 +175,11 @@ cp contrib/syntax/vim/LICENSE LICENSE-vim-syntax cp contrib/syntax/vim/README.md README-vim-syntax.md pushd $(pwd)/_build/src -# build nsinit -go build github.com/docker/libcontainer/nsinit # build go-md2man for building manpages go build github.com/cpuguy83/go-md2man +# build dockertarsum and docker-fetch(commented out) +go build github.com/vbatts/docker-utils/cmd/docker-fetch +go build github.com/vbatts/docker-utils/cmd/dockertarsum popd cp _build/src/go-md2man docs/man/. @@ -209,14 +187,33 @@ sed -i 's/go-md2man/.\/go-md2man/' docs/man/md2man-all.sh # build manpages docs/man/md2man-all.sh +# build python-websocket-client +pushd %{w_distname}-%{w_version} +%{__python} setup.py build +popd + +# build docker-py +pushd docker-py-%{dp_version} +%{__python} setup.py build +popd + +# build atomic +pushd atom-%{atom_commit} +make all +popd + %install # install binary install -d %{buildroot}%{_bindir} -install -p -m 755 bundles/%{version}/dynbinary/docker-%{version} %{buildroot}%{_bindir}/docker +install -p -m 755 bundles/%{d_version}-dev/dynbinary/docker-%{d_version}-dev %{buildroot}%{_bindir}/docker + +# install dockertarsum and docker-fetch +install -p -m 755 _build/src/docker-fetch %{buildroot}%{_bindir} +install -p -m 755 _build/src/dockertarsum %{buildroot}%{_bindir} # install dockerinit install -d %{buildroot}%{_libexecdir}/docker -install -p -m 755 bundles/%{version}/dynbinary/dockerinit-%{version} %{buildroot}%{_libexecdir}/docker/dockerinit +install -p -m 755 bundles/%{d_version}-dev/dynbinary/dockerinit-%{d_version}-dev %{buildroot}%{_libexecdir}/docker/dockerinit # install manpages install -d %{buildroot}%{_mandir}/man1 @@ -228,9 +225,15 @@ install -p -m 644 docs/man/man5/* %{buildroot}%{_mandir}/man5 install -d %{buildroot}%{_datadir}/bash-completion/completions/ install -p -m 644 contrib/completion/bash/docker %{buildroot}%{_datadir}/bash-completion/completions/ -# install zsh completion -install -d %{buildroot}%{_datadir}/zsh/site-functions -install -p -m 644 contrib/completion/zsh/_docker %{buildroot}%{_datadir}/zsh/site-functions +# install fish completion +# create, install and own /usr/share/fish/vendor_completions.d until +# upstream fish provides it +install -dp %{buildroot}%{_datadir}/fish/vendor_completions.d +install -p -m 644 contrib/completion/fish/docker.fish %{buildroot}%{_datadir}/fish/vendor_completions.d + +# install container logrotate cron script +install -dp %{buildroot}%{_sysconfdir}/cron.daily/ +install -p -m 755 %{SOURCE5} %{buildroot}%{_sysconfdir}/cron.daily/docker-logrotate # install vim syntax highlighting install -d %{buildroot}%{_datadir}/vim/vimfiles/{doc,ftdetect,syntax} @@ -238,6 +241,10 @@ install -p -m 644 contrib/syntax/vim/doc/dockerfile.txt %{buildroot}%{_datadir}/ install -p -m 644 contrib/syntax/vim/ftdetect/dockerfile.vim %{buildroot}%{_datadir}/vim/vimfiles/ftdetect install -p -m 644 contrib/syntax/vim/syntax/dockerfile.vim %{buildroot}%{_datadir}/vim/vimfiles/syntax +# install zsh completion +install -d %{buildroot}%{_datadir}/zsh/site-functions +install -p -m 644 contrib/completion/zsh/_docker %{buildroot}%{_datadir}/zsh/site-functions + # install udev rules install -d %{buildroot}%{_sysconfdir}/udev/rules.d install -p -m 755 contrib/udev/80-docker.rules %{buildroot}%{_sysconfdir}/udev/rules.d @@ -248,54 +255,68 @@ install -d -m 700 %{buildroot}%{_sharedstatedir}/docker # install systemd/init scripts install -d %{buildroot}%{_unitdir} install -p -m 644 %{SOURCE1} %{buildroot}%{_unitdir} -install -p -m 644 contrib/init/systemd/docker.socket %{buildroot}%{_unitdir} + # for additional args install -d %{buildroot}%{_sysconfdir}/sysconfig/ install -p -m 644 %{SOURCE3} %{buildroot}%{_sysconfdir}/sysconfig/docker -install -p -m 644 %{SOURCE5} %{buildroot}%{_sysconfdir}/sysconfig/docker-storage +install -p -m 644 %{SOURCE4} %{buildroot}%{_sysconfdir}/sysconfig/docker-storage +install -p -m 644 %{SOURCE7} %{buildroot}%{_sysconfdir}/sysconfig/docker-network # install secrets dir -#install -d -p -m 750 %{buildroot}/%{_datadir}/rhel/secrets +install -d -p -m 750 %{buildroot}/%{_datadir}/rhel/secrets # rhbz#1110876 - update symlinks for subscription management -#ln -s %{_sysconfdir}/pki/entitlement %{buildroot}%{_datadir}/rhel/secrets/etc-pki-entitlement -#ln -s %{_sysconfdir}/rhsm %{buildroot}%{_datadir}/rhel/secrets/rhsm -#ln -s %{_sysconfdir}/yum.repos.d/redhat.repo %{buildroot}%{_datadir}/rhel/secrets/rhel7.repo +ln -s %{_sysconfdir}/pki/entitlement %{buildroot}%{_datadir}/rhel/secrets/etc-pki-entitlement +ln -s %{_sysconfdir}/rhsm %{buildroot}%{_datadir}/rhel/secrets/rhsm +ln -s %{_sysconfdir}/yum.repos.d/redhat.repo %{buildroot}%{_datadir}/rhel/secrets/rhel7.repo -mkdir -p %{buildroot}/etc/docker/certs.d/ -#ln -s /etc/rhsm/ca/redhat-uep.pem %{buildroot}/etc/docker/certs.d/redhat.com/redhat-ca.crt +mkdir -p %{buildroot}/etc/docker/certs.d/redhat.com +ln -s /etc/rhsm/ca/redhat-uep.pem %{buildroot}/etc/docker/certs.d/redhat.com/redhat-ca.crt -# Install nsinit -install -d -p %{buildroot}%{gopath}/src/%{import_path_libcontainer}/nsinit -cp -pav vendor/src/%{import_path_libcontainer}/nsinit/*.go %{buildroot}%{gopath}/src/%{import_path_libcontainer}/nsinit -install -d %{buildroot}%{_bindir} -install -p -m 755 ./_build/src/nsinit %{buildroot}%{_bindir}/nsinit - -# Install libcontainer -for dir in . apparmor cgroups cgroups/fs cgroups/systemd \ - console devices label mount mount/nodes namespaces \ - netlink network nsinit security/capabilities \ - security/restrict selinux syncpipe system user utils xattr -do - install -d -p %{buildroot}%{gopath}/src/%{import_path_libcontainer}/$dir - cp -pav vendor/src/%{import_path_libcontainer}/$dir/*.go %{buildroot}%{gopath}/src/%{import_path_libcontainer}/$dir -done - -# sources -install -d -p %{buildroot}/%{gopath}/src/%{import_path} - -for dir in api builder builtins contrib/docker-device-tool \ - contrib/host-integration daemon docker dockerinit \ - dockerversion engine events graph \ - image links nat opts pkg registry runconfig \ - trust utils volumes -do - echo $dir - cp -pav $dir %{buildroot}/%{gopath}/src/%{import_path}/ -done -find %{buildroot}/%{gopath}/src/%{import_path}/ -name \*.registry -delete +# install docker config directory +install -dp %{buildroot}%{_sysconfdir}/docker/ + +# install python-websocket-client +pushd %{w_distname}-%{w_version} +%{__python} setup.py install -O1 --skip-build --root=%{buildroot} +mv %{buildroot}/%{_bindir}/wsdump.py \ + %{buildroot}/%{_bindir}/wsdump + +# unbundle cacert (python-websocket-client) +rm %{buildroot}/%{python2_sitelib}/%{w_modname}/cacert.pem +# And link in the mozilla ca (python-websocket-client) +ln -s /etc/pki/tls/cert.pem \ + %{buildroot}/%{python2_sitelib}/%{w_modname}/cacert.pem + +# remove tests that got installed into the buildroot (python-websocket-client) +rm -rf %{buildroot}/%{python2_sitelib}/tests/ + +# Remove executable bit from installed files. (python-websocket-client) +find %{buildroot}/%{python2_sitelib} -type f -exec chmod -x {} \; +popd + +# install docker-py +pushd docker-py-%{dp_version} +%{__python} setup.py install --root %{buildroot} +popd + +# install atomic +pushd atom-%{atom_commit} +make install DESTDIR=%{buildroot} +popd + +%check +[ ! -e /run/docker.sock ] || { + mkdir test_dir + pushd test_dir + git clone https://%{import_path} + pushd docker + make test + popd + popd +} %pre -getent group docker > /dev/null || %{_sbindir}/groupadd -r docker +getent passwd dockerroot > /dev/null || %{_sbindir}/useradd -r -d %{_sharedstatedir}/docker -s /sbin/nologin -c "Docker User" dockerroot exit 0 %post @@ -310,41 +331,197 @@ exit 0 %files %doc AUTHORS CHANGELOG.md CONTRIBUTING.md MAINTAINERS NOTICE %doc LICENSE* README*.md -%{_mandir}/man1/* +%{_mandir}/man1/docker* %{_mandir}/man5/* %{_bindir}/docker -#%dir %{_datadir}/rhel -#%dir %{_datadir}/rhel/secrets -#%{_datadir}/rhel/secrets/etc-pki-entitlement -#%{_datadir}/rhel/secrets/rhel7.repo -#%{_datadir}/rhel/secrets/rhsm -%dir %{_libexecdir}/docker -%{_libexecdir}/docker/dockerinit +%dir %{_datadir}/rhel +%dir %{_datadir}/rhel/secrets +%{_datadir}/rhel/secrets/etc-pki-entitlement +%{_datadir}/rhel/secrets/rhel7.repo +%{_datadir}/rhel/secrets/rhsm +%{_libexecdir}/docker %{_unitdir}/docker.service -%{_unitdir}/docker.socket %config(noreplace) %{_sysconfdir}/sysconfig/docker %config(noreplace) %{_sysconfdir}/sysconfig/docker-storage -%{_sysconfdir}/docker/certs.d +%config(noreplace) %{_sysconfdir}/sysconfig/docker-network %{_datadir}/bash-completion/completions/docker -%{_datadir}/zsh/site-functions/_docker %dir %{_sharedstatedir}/docker %dir %{_sysconfdir}/udev/rules.d %{_sysconfdir}/udev/rules.d/80-docker.rules +%dir %{_datadir}/fish/vendor_completions.d/ +%{_datadir}/fish/vendor_completions.d/docker.fish %dir %{_datadir}/vim/vimfiles/doc %{_datadir}/vim/vimfiles/doc/dockerfile.txt %dir %{_datadir}/vim/vimfiles/ftdetect %{_datadir}/vim/vimfiles/ftdetect/dockerfile.vim %dir %{_datadir}/vim/vimfiles/syntax %{_datadir}/vim/vimfiles/syntax/dockerfile.vim -%{_bindir}/nsinit - -%files devel -%doc AUTHORS CHANGELOG.md CONTRIBUTING.md LICENSE MAINTAINERS NOTICE README.md -%{gopath}/src/%{common_path}/* +%dir %{_datadir}/zsh/site-functions +%{_datadir}/zsh/site-functions/_docker +%{_sysconfdir}/docker +%{_bindir}/docker-fetch +%{_bindir}/dockertarsum + +%files logrotate +%doc README.docker-logrotate +%{_sysconfdir}/cron.daily/docker-logrotate + +%files -n python-websocket-client +%doc %{w_distname}-%{w_version}/{README.rst,LICENSE} +%{python2_sitelib}/%{w_modname}/ +%{python2_sitelib}/%{w_eggname}*%{w_version}* +%{_bindir}/wsdump + +%files python +%doc docker-py-%{dp_version}/{LICENSE,README.md} +%config(noreplace) %{_sysconfdir}/sysconfig/atomic +%{python_sitelib}/docker +%{python_sitelib}/docker_py-%{dp_version}-py2*.egg-info +%{python_sitelib}/atomic*.egg-info +%{_sysconfdir}/profile.d/atomic.sh +%{_bindir}/atomic +%{_mandir}/man1/atomic* %changelog -* Wed Dec 10 2014 Jim Perrin - 1.3.2-4 -- Comment out subscription secret bits in the spec. +* Fri Jan 30 2015 Lokesh Mandvekar - 1.4.1-37 +- add extra options to /etc/sysconfig/docker to add/block registries +- build atom commit#3d4fd20 + +* Fri Jan 30 2015 Lokesh Mandvekar - 1.4.1-36 +- remove dependency on python-backports + +* Fri Jan 30 2015 Lokesh Mandvekar - 1.4.1-35 +- build atomic rhatdan/master commit#973142b +- build docker rhatdan/1.4.1-beta2 commit#d26b358 + +* Fri Jan 30 2015 Michal Minar - 1.4.1-34 +- added patch fixed tagging issue + +* Fri Jan 30 2015 Michal Minar - 1.4.1-33 +- build docker rhatdan/1.4.1-beta2 commit#b024f0f +- --registry-(replace|preprend) replaced with --(add|block)-registry + +* Thu Jan 29 2015 Lokesh Mandvekar - 1.4.1-32 +- build atom commit#567c2c8 + +* Thu Jan 29 2015 Lokesh Mandvekar - 1.4.1-31 +- build atom commit#b9e02ad + +* Wed Jan 28 2015 Lokesh Mandvekar - 1.4.1-30 +- Require python-backports >= 1.0-8 for docker-python + +* Wed Jan 28 2015 Lokesh Mandvekar - 1.4.1-29 +- build docker rhatdan/1.4.1-beta2 commit#0af307b +- --registry-replace|prepend flags via Michal Minar +- build atomic rhatdan/master commit#37f9be0 + +* Tue Jan 27 2015 Lokesh Mandvekar - 1.4.1-27 +- patch to avoid crash in atomic host + +* Tue Jan 27 2015 Lokesh Mandvekar - 1.4.1-26 +- build docker rhatdan/1.4.1-beta2 commit#0b4cade +- build atomic rhatdan/master commit#b8c7b9d +- build docker-utils vbatts/master commit#fb94a28 + +* Fri Jan 23 2015 Lokesh Mandvekar - 1.4.1-25 +- build atomic commit#fcbc57b with fix for install/upgrade/status +- build docker rhatdan/1.4.1-beta2 commit#f476836 + +* Fri Jan 23 2015 Lokesh Mandvekar - 1.4.1-24 +- install dockertarsum from github.com/vbatts/docker-utils + +* Fri Jan 23 2015 Lokesh Mandvekar - 1.4.1-23 +- build rhatdan/atom commit#ef16d40 +- try urlparse from six, else from argparse + +* Fri Jan 23 2015 Lokesh Mandvekar - 1.4.1-22 +- use python-argparse to provide urlparse + +* Fri Jan 23 2015 Lokesh Mandvekar - 1.4.1-21 +- move atomic bits into -python subpackage + +* Fri Jan 23 2015 Lokesh Mandvekar - 1.4.1-20 +- update atom commit#10fc4c8 + +* Fri Jan 23 2015 Lokesh Mandvekar - 1.4.1-19 +- build rhatdan/1.4.1-beta2 commit#35a8dc5 +- --registry-prepend instead of --registry-append + +* Thu Jan 22 2015 Lokesh Mandvekar - 1.4.1-18 +- don't install nsinit + +* Thu Jan 22 2015 Lokesh Mandvekar - 1.4.1-17 +- install atomic and manpages +- don't provide -devel subpackage + +* Thu Jan 22 2015 Lokesh Mandvekar - 1.4.1-16 +- install python-websocket-client and python-docker as subpackages + +* Thu Jan 22 2015 Lokesh Mandvekar - 1.4.1-15 +- build rhatdan/1.4.1-beta2 commit#06670da +- install subscription manager + +* Tue Jan 20 2015 Lokesh Mandvekar - 1.4.1-14 +- increment release number to avoid conflict with 7.0 + +* Tue Jan 20 2015 Lokesh Mandvekar - 1.4.1-13 +- build rhatdan/1.4.1-beta2 commit#2de8e5d +- Resolves: rhbz#1180718 - MountFlags=slave in unitfile + +* Mon Jan 19 2015 Lokesh Mandvekar - 1.4.1-12 +- build rhatdan/1.4.1-beta2 commit#218805f + +* Mon Jan 19 2015 Lokesh Mandvekar - 1.4.1-11 +- build rhatdan/1.4.1-beta2 commit#4b7addf + +* Fri Jan 16 2015 Lokesh Mandvekar - 1.4.1-10 +- build rhatdan/1.4.1-beta2 commit #a0c7884 +- socket activation not used +- include docker_transition_unconfined boolean info and disable socket +activation in /etc/sysconfig/docker +- docker group not created + +* Fri Jan 16 2015 Lokesh Mandvekar - 1.4.1-9 +- run all tests and not just unit tests +- replace codegansta.tgz with codegangsta-cli.patch + +* Thu Jan 15 2015 Lokesh Mandvekar - 1.4.1-8 +- build rhatdan/1.4.1-beta2 commit #6ee2421 + +* Wed Jan 14 2015 Lokesh Mandvekar - 1.4.1-7 +- build rhatdan/1.4.1-beta2 01a64e011da131869b42be8b2f11f540fd4b8f33 +- run tests inside a docker repo during check phase + +* Mon Jan 12 2015 Lokesh Mandvekar - 1.4.1-6 +- build rhatdan/1.4.1-beta2 01a64e011da131869b42be8b2f11f540fd4b8f33 + +* Wed Jan 07 2015 Lokesh Mandvekar - 1.4.1-5 +- own /etc/docker +- include check for unit tests + +* Fri Dec 19 2014 Lokesh Mandvekar - 1.4.1-4 +- Install vim and shell completion files in main package itself + +* Thu Dec 18 2014 Lokesh Mandvekar - 1.4.1-3 +- rename cron script +- change enable/disable to true/false + +* Thu Dec 18 2014 Lokesh Mandvekar - 1.4.1-2 +- Enable the logrotate cron job by default, disable via sysconfig variable +- Install docker-network and docker-container-logrotate sysconfig files + +* Thu Dec 18 2014 Lokesh Mandvekar - 1.4.1-1 +- Resolves: rhbz#1174351 - update to 1.4.1 +- Provide subpackages for fish and zsh completion and vim syntax highlighting +- Provide subpackage to run logrotate on running containers as a daily cron +job + +* Mon Dec 15 2014 Lokesh Mandvekar - 1.4.0-1 +- Resolves: rhbz#1174266 - update to 1.4.0 +- Fixes: CVE-2014-9357, CVE-2014-9358 +- uses /etc/docker as cert path +- create dockerroot user +- skip btrfs version check * Fri Dec 05 2014 Lokesh Mandvekar - 1.3.2-4 - update libcontainer paths