From d25a282ef9029e70dd46db6e14722dbd05a51dbd Mon Sep 17 00:00:00 2001 From: Darren Shepherd Date: Tue, 22 Sep 2015 11:13:53 -0700 Subject: [PATCH] Bump godep for libcompose --- Godeps/Godeps.json | 12 + .../autogen/dockerversion/dockerversion.go | 1 + .../docker/libcompose/cli/app/app.go | 229 +++++++++++++++++ .../docker/libcompose/cli/app/types.go | 12 + .../docker/libcompose/cli/command/command.go | 230 ++++++++++++++++++ .../libcompose/cli/docker/app/commands.go | 58 +++++ .../libcompose/cli/docker/app/factory.go | 23 ++ 7 files changed, 565 insertions(+) create mode 100644 Godeps/_workspace/src/github.com/docker/libcompose/cli/app/app.go create mode 100644 Godeps/_workspace/src/github.com/docker/libcompose/cli/app/types.go create mode 100644 Godeps/_workspace/src/github.com/docker/libcompose/cli/command/command.go create mode 100644 Godeps/_workspace/src/github.com/docker/libcompose/cli/docker/app/commands.go create mode 100644 Godeps/_workspace/src/github.com/docker/libcompose/cli/docker/app/factory.go diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index 09aa80c3..66c6fc91 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -248,6 +248,18 @@ "Comment": "v1.4.1-5200-gf39987a", "Rev": "f39987afe8d611407887b3094c03d6ba6a766a67" }, + { + "ImportPath": "github.com/docker/libcompose/cli/app", + "Rev": "a77147c9909a0ee7055c896826a01cb55352b4d9" + }, + { + "ImportPath": "github.com/docker/libcompose/cli/command", + "Rev": "a77147c9909a0ee7055c896826a01cb55352b4d9" + }, + { + "ImportPath": "github.com/docker/libcompose/cli/docker/app", + "Rev": "a77147c9909a0ee7055c896826a01cb55352b4d9" + }, { "ImportPath": "github.com/docker/libcompose/cli/logger", "Rev": "a77147c9909a0ee7055c896826a01cb55352b4d9" diff --git a/Godeps/_workspace/src/github.com/docker/docker/autogen/dockerversion/dockerversion.go b/Godeps/_workspace/src/github.com/docker/docker/autogen/dockerversion/dockerversion.go index 4bb98119..1c2d3254 100644 --- a/Godeps/_workspace/src/github.com/docker/docker/autogen/dockerversion/dockerversion.go +++ b/Godeps/_workspace/src/github.com/docker/docker/autogen/dockerversion/dockerversion.go @@ -4,6 +4,7 @@ package dockerversion var ( GITCOMMIT string = "" VERSION string = "" + BUILDTIME string = "" IAMSTATIC string = "true" INITSHA1 string = "" diff --git a/Godeps/_workspace/src/github.com/docker/libcompose/cli/app/app.go b/Godeps/_workspace/src/github.com/docker/libcompose/cli/app/app.go new file mode 100644 index 00000000..b07f4ec9 --- /dev/null +++ b/Godeps/_workspace/src/github.com/docker/libcompose/cli/app/app.go @@ -0,0 +1,229 @@ +package app + +import ( + "fmt" + "log" + "os" + "strconv" + "strings" + + "github.com/Sirupsen/logrus" + "github.com/codegangsta/cli" + "github.com/docker/libcompose/project" +) + +// ProjectAction is an adapter to allow the use of ordinary functions as libcompose actions. +// Any function that has the appropriate signature can be register as an action on a codegansta/cli command. +// +// cli.Command{ +// Name: "ps", +// Usage: "List containers", +// Action: app.WithProject(factory, app.ProjectPs), +// } +type ProjectAction func(project *project.Project, c *cli.Context) + +// BeforeApp is an action that is executed before any cli command. +func BeforeApp(c *cli.Context) error { + if c.GlobalBool("verbose") { + logrus.SetLevel(logrus.DebugLevel) + } + logrus.Warning("Note: This is an experimental alternate implementation of the Compose CLI (https://github.com/docker/compose)") + return nil +} + +// WithProject is an helper function to create a cli.Command action with a ProjectFactory. +func WithProject(factory ProjectFactory, action ProjectAction) func(context *cli.Context) { + return func(context *cli.Context) { + p, err := factory.Create(context) + if err != nil { + log.Fatalf("Failed to read project: %v", err) + } + action(p, context) + } +} + +// ProjectPs lists the containers. +func ProjectPs(p *project.Project, c *cli.Context) { + allInfo := project.InfoSet{} + for name := range p.Configs { + service, err := p.CreateService(name) + if err != nil { + logrus.Fatal(err) + } + + info, err := service.Info() + if err != nil { + logrus.Fatal(err) + } + + allInfo = append(allInfo, info...) + } + + os.Stdout.WriteString(allInfo.String()) +} + +// ProjectPort prints the public port for a port binding. +func ProjectPort(p *project.Project, c *cli.Context) { + if len(c.Args()) != 2 { + logrus.Fatalf("Please pass arguments in the form: SERVICE PORT") + } + + index := c.Int("index") + protocol := c.String("protocol") + + service, err := p.CreateService(c.Args()[0]) + if err != nil { + logrus.Fatal(err) + } + + containers, err := service.Containers() + if err != nil { + logrus.Fatal(err) + } + + if index < 1 || index > len(containers) { + logrus.Fatalf("Invalid index %d", index) + } + + output, err := containers[index-1].Port(fmt.Sprintf("%s/%s", c.Args()[1], protocol)) + if err != nil { + logrus.Fatal(err) + } + fmt.Println(output) +} + +// ProjectDown brings all services down. +func ProjectDown(p *project.Project, c *cli.Context) { + err := p.Down(c.Args()...) + if err != nil { + logrus.Fatal(err) + } +} + +// ProjectBuild builds or rebuilds services. +func ProjectBuild(p *project.Project, c *cli.Context) { + err := p.Build(c.Args()...) + if err != nil { + logrus.Fatal(err) + } +} + +// ProjectCreate creates all services but do not start them. +func ProjectCreate(p *project.Project, c *cli.Context) { + err := p.Create(c.Args()...) + if err != nil { + logrus.Fatal(err) + } +} + +// ProjectUp brings all services up. +func ProjectUp(p *project.Project, c *cli.Context) { + err := p.Up(c.Args()...) + if err != nil { + logrus.Fatal(err) + } + + if !c.Bool("d") { + wait() + } +} + +// ProjectStart starts services. +func ProjectStart(p *project.Project, c *cli.Context) { + err := p.Start(c.Args()...) + if err != nil { + logrus.Fatal(err) + } +} + +// ProjectRestart restarts services. +func ProjectRestart(p *project.Project, c *cli.Context) { + err := p.Restart(c.Args()...) + if err != nil { + logrus.Fatal(err) + } +} + +// ProjectLog gets services logs. +func ProjectLog(p *project.Project, c *cli.Context) { + err := p.Log(c.Args()...) + if err != nil { + logrus.Fatal(err) + } + wait() +} + +// ProjectPull pulls images for services. +func ProjectPull(p *project.Project, c *cli.Context) { + err := p.Pull(c.Args()...) + if err != nil { + logrus.Fatal(err) + } +} + +// ProjectDelete delete services. +func ProjectDelete(p *project.Project, c *cli.Context) { + if !c.Bool("force") && len(c.Args()) == 0 { + logrus.Fatal("Will not remove all services with out --force") + } + err := p.Delete(c.Args()...) + if err != nil { + logrus.Fatal(err) + } +} + +// ProjectKill forces stop service containers. +func ProjectKill(p *project.Project, c *cli.Context) { + err := p.Kill(c.Args()...) + if err != nil { + logrus.Fatal(err) + } +} + +// ProjectScale scales services. +func ProjectScale(p *project.Project, c *cli.Context) { + // This code is a bit verbose but I wanted to parse everything up front + order := make([]string, 0, 0) + serviceScale := make(map[string]int) + services := make(map[string]project.Service) + + for _, arg := range c.Args() { + kv := strings.SplitN(arg, "=", 2) + if len(kv) != 2 { + logrus.Fatalf("Invalid scale parameter: %s", arg) + } + + name := kv[0] + + count, err := strconv.Atoi(kv[1]) + if err != nil { + logrus.Fatalf("Invalid scale parameter: %v", err) + } + + if _, ok := p.Configs[name]; !ok { + logrus.Fatalf("%s is not defined in the template", name) + } + + service, err := p.CreateService(name) + if err != nil { + logrus.Fatalf("Failed to lookup service: %s: %v", service, err) + } + + order = append(order, name) + serviceScale[name] = count + services[name] = service + } + + for _, name := range order { + scale := serviceScale[name] + logrus.Infof("Setting scale %s=%d...", name, scale) + err := services[name].Scale(scale) + if err != nil { + logrus.Fatalf("Failed to set the scale %s=%d: %v", name, scale, err) + } + } +} + +func wait() { + <-make(chan interface{}) +} diff --git a/Godeps/_workspace/src/github.com/docker/libcompose/cli/app/types.go b/Godeps/_workspace/src/github.com/docker/libcompose/cli/app/types.go new file mode 100644 index 00000000..71920c8a --- /dev/null +++ b/Godeps/_workspace/src/github.com/docker/libcompose/cli/app/types.go @@ -0,0 +1,12 @@ +package app + +import ( + "github.com/codegangsta/cli" + "github.com/docker/libcompose/project" +) + +// ProjectFactory is an interface that helps creating libcompose project. +type ProjectFactory interface { + // Create creates a libcompose project from the command line options (codegangsta cli context). + Create(c *cli.Context) (*project.Project, error) +} diff --git a/Godeps/_workspace/src/github.com/docker/libcompose/cli/command/command.go b/Godeps/_workspace/src/github.com/docker/libcompose/cli/command/command.go new file mode 100644 index 00000000..56499226 --- /dev/null +++ b/Godeps/_workspace/src/github.com/docker/libcompose/cli/command/command.go @@ -0,0 +1,230 @@ +package command + +import ( + "github.com/codegangsta/cli" + "github.com/docker/libcompose/cli/app" + "github.com/docker/libcompose/project" +) + +// CreateCommand defines the libcompose create subcommand. +func CreateCommand(factory app.ProjectFactory) cli.Command { + return cli.Command{ + Name: "create", + Usage: "Create all services but do not start", + Action: app.WithProject(factory, app.ProjectCreate), + } +} + +// BuildCommand defines the libcompose build subcommand. +func BuildCommand(factory app.ProjectFactory) cli.Command { + return cli.Command{ + Name: "build", + Usage: "Build or rebuild services.", + Action: app.WithProject(factory, app.ProjectBuild), + } +} + +// PsCommand defines the libcompose ps subcommand. +func PsCommand(factory app.ProjectFactory) cli.Command { + return cli.Command{ + Name: "ps", + Usage: "List containers", + Action: app.WithProject(factory, app.ProjectPs), + } +} + +// PortCommand defines the libcompose port subcommand. +func PortCommand(factory app.ProjectFactory) cli.Command { + return cli.Command{ + Name: "port", + Usage: "Print the public port for a port binding", + Action: app.WithProject(factory, app.ProjectPort), + Flags: []cli.Flag{ + cli.StringFlag{ + Name: "protocol", + Usage: "tcp or udp ", + Value: "tcp", + }, + cli.IntFlag{ + Name: "index", + Usage: "index of the container if there are multiple instances of a service", + Value: 1, + }, + }, + } +} + +// UpCommand defines the libcompose up subcommand. +func UpCommand(factory app.ProjectFactory) cli.Command { + return cli.Command{ + Name: "up", + Usage: "Bring all services up", + Action: app.WithProject(factory, app.ProjectUp), + Flags: []cli.Flag{ + cli.BoolFlag{ + Name: "d", + Usage: "Do not block and log", + }, + cli.BoolFlag{ + Name: "rebuild", + Usage: "Rebuild containers", + }, + }, + } +} + +// StartCommand defines the libcompose start subcommand. +func StartCommand(factory app.ProjectFactory) cli.Command { + return cli.Command{ + Name: "start", + Usage: "Start services", + Action: app.WithProject(factory, app.ProjectStart), + Flags: []cli.Flag{ + cli.BoolTFlag{ + Name: "d", + Usage: "Do not block and log", + }, + }, + } +} + +// PullCommand defines the libcompose pull subcommand. +func PullCommand(factory app.ProjectFactory) cli.Command { + return cli.Command{ + Name: "pull", + Usage: "Pulls images for services", + Action: app.WithProject(factory, app.ProjectPull), + } +} + +// LogsCommand defines the libcompose logs subcommand. +func LogsCommand(factory app.ProjectFactory) cli.Command { + return cli.Command{ + Name: "logs", + Usage: "Get service logs", + Action: app.WithProject(factory, app.ProjectLog), + Flags: []cli.Flag{ + cli.IntFlag{ + Name: "lines", + Usage: "number of lines to tail", + Value: 100, + }, + }, + } +} + +// RestartCommand defines the libcompose restart subcommand. +func RestartCommand(factory app.ProjectFactory) cli.Command { + return cli.Command{ + Name: "restart", + Usage: "Restart services", + Action: app.WithProject(factory, app.ProjectRestart), + Flags: []cli.Flag{ + cli.IntFlag{ + Name: "timeout,t", + Usage: "Specify a shutdown timeout in seconds.", + Value: 10, + }, + }, + } +} + +// StopCommand defines the libcompose stop subcommand. +func StopCommand(factory app.ProjectFactory) cli.Command { + return cli.Command{ + Name: "stop", + ShortName: "down", + Usage: "Stop services", + Action: app.WithProject(factory, app.ProjectDown), + Flags: []cli.Flag{ + cli.IntFlag{ + Name: "timeout,t", + Usage: "Specify a shutdown timeout in seconds.", + Value: 10, + }, + }, + } +} + +// ScaleCommand defines the libcompose scale subcommand. +func ScaleCommand(factory app.ProjectFactory) cli.Command { + return cli.Command{ + Name: "scale", + Usage: "Scale services", + Action: app.WithProject(factory, app.ProjectScale), + Flags: []cli.Flag{ + cli.IntFlag{ + Name: "timeout,t", + Usage: "Specify a shutdown timeout in seconds.", + Value: 10, + }, + }, + } +} + +// RmCommand defines the libcompose rm subcommand. +func RmCommand(factory app.ProjectFactory) cli.Command { + return cli.Command{ + Name: "rm", + Usage: "Delete services", + Action: app.WithProject(factory, app.ProjectDelete), + Flags: []cli.Flag{ + cli.BoolFlag{ + Name: "force,f", + Usage: "Allow deletion of all services", + }, + }, + } +} + +// KillCommand defines the libcompose kill subcommand. +func KillCommand(factory app.ProjectFactory) cli.Command { + return cli.Command{ + Name: "kill", + Usage: "Force stop service containers", + Action: app.WithProject(factory, app.ProjectKill), + Flags: []cli.Flag{ + cli.StringFlag{ + Name: "signal,s", + Usage: "SIGNAL to send to the container", + Value: "SIGKILL", + }, + }, + } +} + +// CommonFlags defines the flags that are in common for all subcommands. +func CommonFlags() []cli.Flag { + return []cli.Flag{ + cli.BoolFlag{ + Name: "verbose,debug", + }, + cli.StringFlag{ + Name: "file,f", + Usage: "Specify an alternate compose file (default: docker-compose.yml)", + Value: "docker-compose.yml", + EnvVar: "COMPOSE_FILE", + }, + cli.StringFlag{ + Name: "project-name,p", + Usage: "Specify an alternate project name (default: directory name)", + }, + } +} + +// Populate updates the specified project context based on command line arguments and subcommands. +func Populate(context *project.Context, c *cli.Context) { + context.ComposeFile = c.GlobalString("file") + context.ProjectName = c.GlobalString("project-name") + + if c.Command.Name == "logs" { + context.Log = true + } else if c.Command.Name == "up" { + context.Log = !c.Bool("d") + context.Rebuild = c.Bool("rebuild") + } else if c.Command.Name == "stop" || c.Command.Name == "restart" || c.Command.Name == "scale" { + context.Timeout = c.Int("timeout") + } else if c.Command.Name == "kill" { + context.Signal = c.String("signal") + } +} diff --git a/Godeps/_workspace/src/github.com/docker/libcompose/cli/docker/app/commands.go b/Godeps/_workspace/src/github.com/docker/libcompose/cli/docker/app/commands.go new file mode 100644 index 00000000..88b891cd --- /dev/null +++ b/Godeps/_workspace/src/github.com/docker/libcompose/cli/docker/app/commands.go @@ -0,0 +1,58 @@ +package app + +import ( + "github.com/Sirupsen/logrus" + "github.com/codegangsta/cli" + "github.com/docker/libcompose/docker" +) + +// DockerClientFlags defines the flags that are specific to the docker client, +// like configdir or tls related flags. +func DockerClientFlags() []cli.Flag { + return []cli.Flag{ + cli.BoolFlag{ + Name: "tls", + Usage: "Use TLS; implied by --tlsverify", + }, + cli.BoolFlag{ + Name: "tlsverify", + Usage: "Use TLS and verify the remote", + EnvVar: "DOCKER_TLS_VERIFY", + }, + cli.StringFlag{ + Name: "tlscacert", + Usage: "Trust certs signed only by this CA", + }, + cli.StringFlag{ + Name: "tlscert", + Usage: "Path to TLS certificate file", + }, + cli.StringFlag{ + Name: "tlskey", + Usage: "Path to TLS key file", + }, + cli.StringFlag{ + Name: "configdir", + Usage: "Path to docker config dir, default ${HOME}/.docker", + }, + } +} + +// Populate updates the specified docker context based on command line arguments and subcommands. +func Populate(context *docker.Context, c *cli.Context) { + context.ConfigDir = c.String("configdir") + + opts := docker.ClientOpts{} + opts.TLS = c.GlobalBool("tls") + opts.TLSVerify = c.GlobalBool("tlsverify") + opts.TLSOptions.CAFile = c.GlobalString("tlscacert") + opts.TLSOptions.CertFile = c.GlobalString("tlscert") + opts.TLSOptions.KeyFile = c.GlobalString("tlskey") + + clientFactory, err := docker.NewDefaultClientFactory(opts) + if err != nil { + logrus.Fatalf("Failed to construct Docker client: %v", err) + } + + context.ClientFactory = clientFactory +} diff --git a/Godeps/_workspace/src/github.com/docker/libcompose/cli/docker/app/factory.go b/Godeps/_workspace/src/github.com/docker/libcompose/cli/docker/app/factory.go new file mode 100644 index 00000000..a1e4b2df --- /dev/null +++ b/Godeps/_workspace/src/github.com/docker/libcompose/cli/docker/app/factory.go @@ -0,0 +1,23 @@ +package app + +import ( + "github.com/codegangsta/cli" + "github.com/docker/libcompose/cli/command" + "github.com/docker/libcompose/cli/logger" + "github.com/docker/libcompose/docker" + "github.com/docker/libcompose/project" +) + +// ProjectFactory is a struct that hold the app.ProjectFactory implementation. +type ProjectFactory struct { +} + +// Create implements ProjectFactory.Create using docker client. +func (p *ProjectFactory) Create(c *cli.Context) (*project.Project, error) { + context := &docker.Context{} + context.LoggerFactory = logger.NewColorLoggerFactory() + Populate(context, c) + command.Populate(&context.Context, c) + + return docker.NewProject(context) +}