Skip to content

Commit

Permalink
Merge pull request #1118 from rsteube/docker-compose-actions
Browse files Browse the repository at this point in the history
docker-compose: move actions
  • Loading branch information
rsteube authored May 12, 2022
2 parents 48b1585 + 6f66ea4 commit 9cef6ee
Show file tree
Hide file tree
Showing 4 changed files with 154 additions and 23 deletions.
16 changes: 16 additions & 0 deletions completers/docker-compose_completer/cmd/action/container.go
Original file line number Diff line number Diff line change
@@ -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)
}
29 changes: 6 additions & 23 deletions completers/docker-compose_completer/cmd/action/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)

Expand Down Expand Up @@ -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...)
}
2 changes: 2 additions & 0 deletions pkg/actions/tools/docker/compose/compose.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// package compose contains docker-compose related actions
package compose
130 changes: 130 additions & 0 deletions pkg/actions/tools/docker/compose/service.go
Original file line number Diff line number Diff line change
@@ -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...)
})
}

0 comments on commit 9cef6ee

Please sign in to comment.