From 6f66ea4ff5d750eefd2ddc4151164bb1cc065bcb Mon Sep 17 00:00:00 2001 From: rsteube Date: Tue, 10 May 2022 18:56:29 +0200 Subject: [PATCH] docker-compose: move actions --- .../cmd/action/container.go | 16 +++ .../cmd/action/service.go | 29 +--- pkg/actions/tools/docker/compose/compose.go | 2 + pkg/actions/tools/docker/compose/service.go | 130 ++++++++++++++++++ 4 files changed, 154 insertions(+), 23 deletions(-) create mode 100644 completers/docker-compose_completer/cmd/action/container.go create mode 100644 pkg/actions/tools/docker/compose/compose.go create mode 100644 pkg/actions/tools/docker/compose/service.go diff --git a/completers/docker-compose_completer/cmd/action/container.go b/completers/docker-compose_completer/cmd/action/container.go new file mode 100644 index 0000000000..03fad90b8a --- /dev/null +++ b/completers/docker-compose_completer/cmd/action/container.go @@ -0,0 +1,16 @@ +package action + +import ( + "github.com/rsteube/carapace" + "github.com/rsteube/carapace-bin/pkg/actions/tools/docker/compose" + "github.com/spf13/cobra" +) + +func ActionContainers(cmd *cobra.Command, opts compose.ContainerOpts) carapace.Action { + files, err := cmd.Root().Flags().GetStringArray("file") + if err != nil { + return carapace.ActionMessage(err.Error()) + } + opts.Files = files + return compose.ActionContainers(opts) +} diff --git a/completers/docker-compose_completer/cmd/action/service.go b/completers/docker-compose_completer/cmd/action/service.go index 78340607cc..805b8f7a5f 100644 --- a/completers/docker-compose_completer/cmd/action/service.go +++ b/completers/docker-compose_completer/cmd/action/service.go @@ -2,10 +2,9 @@ package action import ( "encoding/json" - "fmt" - "strings" "github.com/rsteube/carapace" + "github.com/rsteube/carapace-bin/pkg/actions/tools/docker/compose" "github.com/spf13/cobra" ) @@ -33,25 +32,9 @@ func actionConfig(cmd *cobra.Command, f func(c config) carapace.Action) carapace } func ActionServices(cmd *cobra.Command) carapace.Action { - return actionConfig(cmd, func(c config) carapace.Action { - vals := make([]string, 0) - for name, service := range c.Services { - description := service.Image - if strings.TrimSpace(description) == "" { - description = fmt.Sprintf("%v/%v", service.Build.Context, service.Build.Dockerfile) - } - vals = append(vals, name, description) - } - return carapace.ActionValuesDescribed(vals...) - }) -} - -func ActionContainers(cmd *cobra.Command, status string) carapace.Action { - return actionExecCompose(cmd, "ps", "--status", status)(func(output []byte) carapace.Action { - lines := strings.Split(string(output), "\n") - if lines[0] != "" { - return carapace.ActionValues(lines[:len(lines)-1]...) - } - return carapace.ActionValues() - }) + files, err := cmd.Root().Flags().GetStringArray("file") + if err != nil { + return carapace.ActionMessage(err.Error()) + } + return compose.ActionServices(files...) } diff --git a/pkg/actions/tools/docker/compose/compose.go b/pkg/actions/tools/docker/compose/compose.go new file mode 100644 index 0000000000..f33a695a16 --- /dev/null +++ b/pkg/actions/tools/docker/compose/compose.go @@ -0,0 +1,2 @@ +// package compose contains docker-compose related actions +package compose diff --git a/pkg/actions/tools/docker/compose/service.go b/pkg/actions/tools/docker/compose/service.go new file mode 100644 index 0000000000..a8b194a112 --- /dev/null +++ b/pkg/actions/tools/docker/compose/service.go @@ -0,0 +1,130 @@ +package compose + +import ( + "encoding/json" + "fmt" + "strings" + + "github.com/rsteube/carapace" + "github.com/rsteube/carapace/pkg/style" +) + +type config struct { + Services map[string]struct { + Image string + Build struct { + Context string + Dockerfile string + } + } + Volumes map[string]struct { + Name string + } +} + +func actionExecCompose(files []string, arg ...string) func(f func(output []byte) carapace.Action) carapace.Action { + return func(f func(output []byte) carapace.Action) carapace.Action { + return carapace.ActionCallback(func(c carapace.Context) carapace.Action { + a := []string{"compose"} + for _, file := range files { + a = append(a, "--file", file) + } + a = append(a, arg...) + return carapace.ActionExecCommand("docker", a...)(f) + }) + } +} + +func actionConfig(files []string, f func(c config) carapace.Action) carapace.Action { + return actionExecCompose(files, "convert", "--format", "json")(func(output []byte) carapace.Action { + var c config + if err := json.Unmarshal(output, &c); err != nil { + return carapace.ActionMessage(err.Error()) + } + return f(c) + }) +} + +// ActionServices completes services +// elvish (ghcr.io/rsteube/carapace:v0.12.4) +// fish (ghcr.io/rsteube/carapace:v0.12.4) +func ActionServices(files ...string) carapace.Action { + return actionConfig(files, func(c config) carapace.Action { + vals := make([]string, 0) + for name, service := range c.Services { + description := service.Image + if strings.TrimSpace(description) == "" { + description = fmt.Sprintf("%v/%v", service.Build.Context, service.Build.Dockerfile) + } + vals = append(vals, name, description) + } + return carapace.ActionValuesDescribed(vals...) + }) +} + +type container struct { + Name string + State string +} + +type ContainerOpts struct { + Files []string + Paused bool + Restarting bool + Removing bool + Running bool + Dead bool + Created bool + Exited bool +} + +func (o *ContainerOpts) Default() { + o.Paused = true + o.Restarting = true + o.Removing = true + o.Running = true + o.Dead = true + o.Created = true + o.Exited = true +} + +func (o ContainerOpts) includeState(s string) bool { + switch s { + case "paused": + return o.Paused + case "restarting": + return o.Restarting + case "removing": + return o.Removing + case "running": + return o.Running + case "dead": + return o.Dead + case "created": + return o.Created + case "exited": + return o.Exited + default: + return false + } +} + +// ActionContainers completes containers +// carapace-bin-bash-1 (exited) +// carapace-bin-elvish-1 (running) +func ActionContainers(opts ContainerOpts) carapace.Action { + return actionExecCompose(opts.Files, "ps", "--format", "json", "--all")(func(output []byte) carapace.Action { + var containers []container + if err := json.Unmarshal(output, &containers); err != nil { + return carapace.ActionMessage(err.Error()) + } + + vals := make([]string, 0) + for _, c := range containers { + if opts.includeState(c.State) { + vals = append(vals, c.Name, c.State, style.ForKeyword(c.State)) + } + } + return carapace.ActionStyledValuesDescribed(vals...) + }) +}