feat: add uc CLI argument completion for machines, services, volumes (#309)

* Allow for argument completion

This shows for a single command on how to complete service names in the
cluster: `uc inspect <TAB>` will complete using ListServices

See: #307

Signed-off-by: Miek Gieben <miek@miek.nl>

* All cluster interactions can be completed

Signed-off-by: Miek Gieben <miek@miek.nl>

* Machines -m flag completion

Signed-off-by: Miek Gieben <miek@miek.nl>

* Add completion for "ctx use"

Signed-off-by: Miek Gieben <miek@miek.nl>

* Complete from compose file too

Signed-off-by: Miek Gieben <miek@miek.nl>

* Allow for argument completion

This shows for a single command on how to complete service names in the
cluster: `uc inspect <TAB>` will complete using ListServices

See: #307

Signed-off-by: Miek Gieben <miek@miek.nl>

* All cluster interactions can be completed

Signed-off-by: Miek Gieben <miek@miek.nl>

* Machines -m flag completion

Signed-off-by: Miek Gieben <miek@miek.nl>

* Add completion for "ctx use"

Signed-off-by: Miek Gieben <miek@miek.nl>

* Complete from compose file too

Signed-off-by: Miek Gieben <miek@miek.nl>

* Move to better place

Signed-off-by: Miek Gieben <miek@miek.nl>

* Adjust imports

Signed-off-by: Miek Gieben <miek@miek.nl>

* prefix match for context too

Signed-off-by: Miek Gieben <miek@miek.nl>

---------

Signed-off-by: Miek Gieben <miek@miek.nl>
This commit is contained in:
Miek Gieben
2026-04-29 12:18:05 +10:00
committed by GitHub
parent e7a62f6908
commit 4a12217e65
27 changed files with 291 additions and 0 deletions
+6
View File
@@ -6,6 +6,7 @@ import (
composecli "github.com/compose-spec/compose-go/v2/cli"
"github.com/psviderski/uncloud/internal/cli"
"github.com/psviderski/uncloud/internal/cli/completion"
"github.com/psviderski/uncloud/pkg/client/compose"
"github.com/spf13/cobra"
)
@@ -50,6 +51,9 @@ to cluster machines or --push-registry to upload them to external registries.`,
return runBuild(cmd.Context(), uncli, opts)
},
GroupID: "service",
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]cobra.Completion, cobra.ShellCompDirective) {
return completion.ComposeServices(cmd.Context(), args, toComplete, opts.files, opts.profiles)
},
}
cmd.Flags().StringArrayVar(&opts.BuildArgs, "build-arg", nil,
@@ -76,6 +80,8 @@ to cluster machines or --push-registry to upload them to external registries.`,
cmd.Flags().BoolVar(&opts.PushRegistry, "push-registry", false,
"Upload the built images to external registries (e.g., Docker Hub) after building.")
completion.MachinesFlag(cmd)
return cmd
}
+3
View File
@@ -7,6 +7,7 @@ import (
"github.com/alecthomas/chroma/v2/quick"
"github.com/psviderski/uncloud/internal/cli"
"github.com/psviderski/uncloud/internal/cli/completion"
"github.com/spf13/cobra"
)
@@ -33,6 +34,8 @@ func NewConfigCommand() *cobra.Command {
cmd.Flags().BoolVar(&opts.noColor, "no-color", false,
"Disable syntax highlighting for the output.")
completion.MachinesFlag(cmd)
return cmd
}
+3
View File
@@ -13,6 +13,7 @@ import (
"github.com/docker/cli/cli/streams"
"github.com/docker/compose/v2/pkg/progress"
"github.com/psviderski/uncloud/internal/cli"
"github.com/psviderski/uncloud/internal/cli/completion"
"github.com/psviderski/uncloud/internal/cli/tui"
"github.com/psviderski/uncloud/internal/machine/api/pb"
"github.com/psviderski/uncloud/pkg/api"
@@ -48,6 +49,8 @@ func NewDeployCommand() *cobra.Command {
"Machine names or IDs to deploy to. Can be specified multiple times or as a comma-separated "+
"list. (default is all machines)")
completion.MachinesFlag(cmd)
return cmd
}
+8
View File
@@ -7,6 +7,7 @@ import (
"charm.land/huh/v2"
"github.com/psviderski/uncloud/internal/cli"
"github.com/psviderski/uncloud/internal/cli/completion"
"github.com/spf13/cobra"
)
@@ -29,6 +30,13 @@ func NewUseCommand() *cobra.Command {
return selectContext(uncli)
},
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]cobra.Completion, cobra.ShellCompDirective) {
if len(args) > 0 {
return nil, cobra.ShellCompDirectiveNoFileComp
}
uncli := cmd.Context().Value("cli").(*cli.CLI)
return completion.Contexts(cmd.Context(), uncli, args, toComplete)
},
}
return cmd
+4
View File
@@ -11,6 +11,7 @@ import (
"github.com/docker/compose/v2/pkg/progress"
"github.com/docker/docker/pkg/stringid"
"github.com/psviderski/uncloud/internal/cli"
"github.com/psviderski/uncloud/internal/cli/completion"
"github.com/psviderski/uncloud/internal/cli/logs"
"github.com/psviderski/uncloud/internal/cli/tui"
"github.com/psviderski/uncloud/pkg/api"
@@ -48,6 +49,9 @@ func NewDeployCommand() *cobra.Command {
return runDeploy(cmd.Context(), uncli, opts)
},
GroupID: "service",
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]cobra.Completion, cobra.ShellCompDirective) {
return completion.ComposeServices(cmd.Context(), args, toComplete, opts.files, opts.profiles)
},
}
cmd.Flags().StringArrayVar(&opts.BuildServicesOptions.BuildArgs, "build-arg", nil,
+3
View File
@@ -16,6 +16,7 @@ import (
"github.com/docker/go-units"
"github.com/psviderski/uncloud/internal/cli"
"github.com/psviderski/uncloud/internal/cli/completion"
"github.com/psviderski/uncloud/internal/cli/tui"
"github.com/psviderski/uncloud/pkg/api"
"github.com/spf13/cobra"
@@ -62,6 +63,8 @@ func NewListCommand() *cobra.Command {
"Filter images by machine name or ID. Can be specified multiple times or as a comma-separated list. "+
"(default is include all machines)")
completion.MachinesFlag(cmd)
return cmd
}
+3
View File
@@ -7,6 +7,7 @@ import (
"github.com/containerd/platforms"
"github.com/docker/compose/v2/pkg/progress"
"github.com/psviderski/uncloud/internal/cli"
"github.com/psviderski/uncloud/internal/cli/completion"
"github.com/psviderski/uncloud/pkg/client"
"github.com/spf13/cobra"
)
@@ -54,6 +55,8 @@ The image is uploaded to all cluster machines (default) or the specified machine
"Local Docker must be configured to use containerd image store to support multi-platform images.",
)
completion.MachinesFlag(cmd)
return cmd
}
+8
View File
@@ -14,6 +14,7 @@ import (
"github.com/docker/compose/v2/pkg/progress"
"github.com/docker/docker/api/types/container"
"github.com/psviderski/uncloud/internal/cli"
"github.com/psviderski/uncloud/internal/cli/completion"
"github.com/psviderski/uncloud/internal/cli/tui"
"github.com/psviderski/uncloud/internal/machine/api/pb"
"github.com/psviderski/uncloud/pkg/api"
@@ -37,6 +38,13 @@ func NewRmCommand() *cobra.Command {
uncli := cmd.Context().Value("cli").(*cli.CLI)
return remove(cmd.Context(), uncli, args[0], opts)
},
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]cobra.Completion, cobra.ShellCompDirective) {
if len(args) > 0 {
return nil, cobra.ShellCompDirectiveNoFileComp
}
uncli := cmd.Context().Value("cli").(*cli.CLI)
return completion.Machines(cmd.Context(), uncli, args, toComplete)
},
}
cmd.Flags().BoolVarP(&opts.yes, "yes", "y", false,
+8
View File
@@ -7,6 +7,7 @@ import (
"strings"
"github.com/psviderski/uncloud/internal/cli"
"github.com/psviderski/uncloud/internal/cli/completion"
"github.com/psviderski/uncloud/internal/machine/api/pb"
"github.com/psviderski/uncloud/internal/machine/network"
"github.com/spf13/cobra"
@@ -46,6 +47,13 @@ At least one flag must be specified to perform an update.`,
uncli := cmd.Context().Value("cli").(*cli.CLI)
return update(cmd.Context(), uncli, cmd, opts, args[0])
},
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]cobra.Completion, cobra.ShellCompDirective) {
if len(args) > 0 {
return nil, cobra.ShellCompDirectiveNoFileComp
}
uncli := cmd.Context().Value("cli").(*cli.CLI)
return completion.Machines(cmd.Context(), uncli, args, toComplete)
},
}
cmd.Flags().StringVar(
+8
View File
@@ -7,6 +7,7 @@ import (
"github.com/docker/cli/cli/streams"
"github.com/psviderski/uncloud/internal/cli"
"github.com/psviderski/uncloud/internal/cli/completion"
"github.com/psviderski/uncloud/internal/cli/tui"
"github.com/psviderski/uncloud/pkg/api"
"github.com/spf13/cobra"
@@ -55,6 +56,13 @@ If the service has multiple replicas and no container ID is specified, the comma
return runExec(cmd.Context(), uncli, serviceName, command, opts)
},
GroupID: groupID,
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]cobra.Completion, cobra.ShellCompDirective) {
if len(args) > 0 {
return nil, cobra.ShellCompDirectiveNoFileComp
}
uncli := cmd.Context().Value("cli").(*cli.CLI)
return completion.Services(cmd.Context(), uncli, args, toComplete)
},
}
execCmd.Flags().BoolVarP(&opts.detach, "detach", "d", false, "Detached mode: run command in the background")
+8
View File
@@ -9,6 +9,7 @@ import (
"github.com/docker/docker/pkg/stringid"
"github.com/docker/go-units"
"github.com/psviderski/uncloud/internal/cli"
"github.com/psviderski/uncloud/internal/cli/completion"
"github.com/psviderski/uncloud/internal/cli/tui"
"github.com/psviderski/uncloud/pkg/api"
"github.com/spf13/cobra"
@@ -30,6 +31,13 @@ func NewInspectCommand(groupID string) *cobra.Command {
return inspect(cmd.Context(), uncli, opts)
},
GroupID: groupID,
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]cobra.Completion, cobra.ShellCompDirective) {
if len(args) > 0 {
return nil, cobra.ShellCompDirectiveNoFileComp
}
uncli := cmd.Context().Value("cli").(*cli.CLI)
return completion.Services(cmd.Context(), uncli, args, toComplete)
},
}
return cmd
}
+9
View File
@@ -8,6 +8,7 @@ import (
mapset "github.com/deckarep/golang-set/v2"
"github.com/psviderski/uncloud/internal/cli"
"github.com/psviderski/uncloud/internal/cli/completion"
"github.com/psviderski/uncloud/internal/cli/logs"
"github.com/psviderski/uncloud/internal/cli/tui"
"github.com/psviderski/uncloud/pkg/api"
@@ -61,12 +62,20 @@ If no services are specified, streams logs from all services defined in the Comp
return runLogs(cmd.Context(), uncli, args, options)
},
GroupID: groupID,
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]cobra.Completion, cobra.ShellCompDirective) {
uncli := cmd.Context().Value("cli").(*cli.CLI)
return completion.Services(cmd.Context(), uncli, args, toComplete)
},
}
cmd.Flags().StringSliceVar(&options.Files, "file", nil,
"One or more Compose files to load service names from when no services are specified. (default compose.yaml)")
cmd.Flags().AddFlagSet(logs.Flags(&options))
completion.MachinesFlag(cmd)
completion.MachinesFlag(cmd)
return cmd
}
+5
View File
@@ -6,6 +6,7 @@ import (
"github.com/docker/compose/v2/pkg/progress"
"github.com/psviderski/uncloud/internal/cli"
"github.com/psviderski/uncloud/internal/cli/completion"
"github.com/spf13/cobra"
)
@@ -31,6 +32,10 @@ directives in image Dockerfiles) are automatically removed with their containers
return rm(cmd.Context(), uncli, opts)
},
GroupID: groupID,
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]cobra.Completion, cobra.ShellCompDirective) {
uncli := cmd.Context().Value("cli").(*cli.CLI)
return completion.Services(cmd.Context(), uncli, args, toComplete)
},
}
return cmd
}
+3
View File
@@ -11,6 +11,7 @@ import (
"github.com/docker/docker/daemon/names"
"github.com/docker/go-units"
"github.com/psviderski/uncloud/internal/cli"
"github.com/psviderski/uncloud/internal/cli/completion"
"github.com/psviderski/uncloud/internal/secret"
"github.com/psviderski/uncloud/pkg/api"
"github.com/psviderski/uncloud/pkg/client/deploy"
@@ -124,6 +125,8 @@ func NewRunCommand(groupID string) *cobra.Command {
" -v /data/uploads:/app/uploads Bind mount /data/uploads host directory to /app/uploads in container\n"+
" -v /host/path:/container/path:ro Bind mount a host directory or file as read-only")
completion.MachinesFlag(cmd)
return cmd
}
+8
View File
@@ -11,6 +11,7 @@ import (
"charm.land/lipgloss/v2"
"github.com/docker/compose/v2/pkg/progress"
"github.com/psviderski/uncloud/internal/cli"
"github.com/psviderski/uncloud/internal/cli/completion"
"github.com/psviderski/uncloud/internal/cli/tui"
"github.com/psviderski/uncloud/pkg/api"
"github.com/spf13/cobra"
@@ -44,6 +45,13 @@ func NewScaleCommand(groupID string) *cobra.Command {
return scale(cmd.Context(), uncli, opts)
},
GroupID: groupID,
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]cobra.Completion, cobra.ShellCompDirective) {
if len(args) > 0 {
return nil, cobra.ShellCompDirectiveNoFileComp
}
uncli := cmd.Context().Value("cli").(*cli.CLI)
return completion.Services(cmd.Context(), uncli, args, toComplete)
},
}
cmd.Flags().BoolVarP(&opts.yes, "yes", "y", false,
+5
View File
@@ -7,6 +7,7 @@ import (
"github.com/docker/compose/v2/pkg/progress"
"github.com/psviderski/uncloud/internal/cli"
"github.com/psviderski/uncloud/internal/cli/completion"
"github.com/spf13/cobra"
)
@@ -30,6 +31,10 @@ Services can be specified by name or ID.`,
return start(cmd.Context(), uncli, opts)
},
GroupID: groupID,
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]cobra.Completion, cobra.ShellCompDirective) {
uncli := cmd.Context().Value("cli").(*cli.CLI)
return completion.Services(cmd.Context(), uncli, args, toComplete)
},
}
return cmd
}
+5
View File
@@ -8,6 +8,7 @@ import (
"github.com/docker/compose/v2/pkg/progress"
"github.com/docker/docker/api/types/container"
"github.com/psviderski/uncloud/internal/cli"
"github.com/psviderski/uncloud/internal/cli/completion"
"github.com/spf13/cobra"
)
@@ -33,6 +34,10 @@ Services can be specified by name or ID. Stopped services can be restarted with
return stop(cmd.Context(), uncli, opts)
},
GroupID: groupID,
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]cobra.Completion, cobra.ShellCompDirective) {
uncli := cmd.Context().Value("cli").(*cli.CLI)
return completion.Services(cmd.Context(), uncli, args, toComplete)
},
}
cmd.Flags().StringVarP(&opts.signal, "signal", "s", "",
"Signal to send to each container's main process.\n"+
+3
View File
@@ -9,6 +9,7 @@ import (
"charm.land/huh/v2"
"github.com/docker/docker/api/types/volume"
"github.com/psviderski/uncloud/internal/cli"
"github.com/psviderski/uncloud/internal/cli/completion"
"github.com/psviderski/uncloud/internal/machine/api/pb"
"github.com/psviderski/uncloud/pkg/api"
"github.com/spf13/cobra"
@@ -50,6 +51,8 @@ func NewCreateCommand() *cobra.Command {
cmd.Flags().StringVarP(&opts.machine, "machine", "m", "",
"Name or ID of the machine to create the volume on.")
completion.MachinesFlag(cmd)
return cmd
}
+10
View File
@@ -7,6 +7,7 @@ import (
"fmt"
"github.com/psviderski/uncloud/internal/cli"
"github.com/psviderski/uncloud/internal/cli/completion"
"github.com/psviderski/uncloud/pkg/api"
"github.com/spf13/cobra"
)
@@ -26,12 +27,21 @@ func NewInspectCommand() *cobra.Command {
uncli := cmd.Context().Value("cli").(*cli.CLI)
return inspect(cmd.Context(), uncli, args[0], opts)
},
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]cobra.Completion, cobra.ShellCompDirective) {
if len(args) > 0 {
return nil, cobra.ShellCompDirectiveNoFileComp
}
uncli := cmd.Context().Value("cli").(*cli.CLI)
return completion.Volumes(cmd.Context(), uncli, args, toComplete)
},
}
cmd.Flags().StringVarP(&opts.machine, "machine", "m", "",
"Name or ID of the machine where the volume is located. "+
"If not specified, the volume will be searched across all machines.")
completion.MachinesFlag(cmd)
return cmd
}
+3
View File
@@ -7,6 +7,7 @@ import (
"strings"
"github.com/psviderski/uncloud/internal/cli"
"github.com/psviderski/uncloud/internal/cli/completion"
"github.com/psviderski/uncloud/internal/cli/tui"
"github.com/psviderski/uncloud/pkg/api"
"github.com/spf13/cobra"
@@ -36,6 +37,8 @@ func NewListCommand() *cobra.Command {
cmd.Flags().BoolVarP(&opts.quiet, "quiet", "q", false,
"Only display volume names.")
completion.MachinesFlag(cmd)
return cmd
}
+7
View File
@@ -6,6 +6,7 @@ import (
"fmt"
"github.com/psviderski/uncloud/internal/cli"
"github.com/psviderski/uncloud/internal/cli/completion"
"github.com/psviderski/uncloud/internal/cli/tui"
"github.com/psviderski/uncloud/pkg/api"
"github.com/spf13/cobra"
@@ -30,6 +31,10 @@ func NewRemoveCommand() *cobra.Command {
uncli := cmd.Context().Value("cli").(*cli.CLI)
return remove(cmd.Context(), uncli, args, opts)
},
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]cobra.Completion, cobra.ShellCompDirective) {
uncli := cmd.Context().Value("cli").(*cli.CLI)
return completion.Volumes(cmd.Context(), uncli, args, toComplete)
},
}
cmd.Flags().BoolVarP(&opts.force, "force", "f", false,
@@ -41,6 +46,8 @@ func NewRemoveCommand() *cobra.Command {
cmd.Flags().BoolVarP(&opts.yes, "yes", "y", false,
"Do not prompt for confirmation before removing the volume(s).")
completion.MachinesFlag(cmd)
return cmd
}
+4
View File
@@ -8,6 +8,7 @@ import (
"github.com/docker/go-units"
"github.com/psviderski/uncloud/internal/cli"
"github.com/psviderski/uncloud/internal/cli/completion"
"github.com/psviderski/uncloud/internal/cli/tui"
"github.com/psviderski/uncloud/internal/machine/api/pb"
"github.com/spf13/cobra"
@@ -44,6 +45,9 @@ func newShowCommand() *cobra.Command {
}
cmd.Flags().StringVarP(&opts.machine, "machine", "m", "",
"Name or ID of the machine to show the configuration for. (default is connected machine)")
completion.MachinesFlag(cmd)
return cmd
}
+30
View File
@@ -0,0 +1,30 @@
package completion
import (
"context"
"slices"
"strings"
composecli "github.com/compose-spec/compose-go/v2/cli"
"github.com/psviderski/uncloud/pkg/client/compose"
"github.com/spf13/cobra"
)
func ComposeServices(ctx context.Context, args []string, toComplete string, files, profiles []string) ([]cobra.Completion, cobra.ShellCompDirective) {
project, err := compose.LoadProject(ctx, files, composecli.WithDefaultProfiles(profiles...))
if err != nil {
return nil, cobra.ShellCompDirectiveError
}
services := project.ServiceNames()
names := []cobra.Completion{}
for _, service := range services {
if slices.Contains(args, service) {
continue
}
if strings.HasPrefix(service, toComplete) {
names = append(names, service)
}
}
return names, cobra.ShellCompDirectiveNoFileComp
}
+28
View File
@@ -0,0 +1,28 @@
package completion
import (
"context"
"maps"
"slices"
"strings"
"github.com/psviderski/uncloud/internal/cli"
"github.com/spf13/cobra"
)
func Contexts(ctx context.Context, uncli *cli.CLI, args []string, toComplete string) ([]cobra.Completion, cobra.ShellCompDirective) {
contexts := slices.Sorted(maps.Keys(uncli.Config.Contexts))
names := []cobra.Completion{}
for _, context := range contexts {
if slices.Contains(args, context) {
continue
}
if strings.HasPrefix(context, toComplete) {
names = append(names, context)
}
names = append(names, context)
}
return names, cobra.ShellCompDirectiveNoFileComp
}
+41
View File
@@ -0,0 +1,41 @@
package completion
import (
"context"
"slices"
"strings"
"github.com/psviderski/uncloud/internal/cli"
"github.com/spf13/cobra"
)
func Machines(ctx context.Context, uncli *cli.CLI, args []string, toComplete string) ([]cobra.Completion, cobra.ShellCompDirective) {
client, err := uncli.ConnectCluster(ctx)
if err != nil {
return nil, cobra.ShellCompDirectiveError
}
defer client.Close()
machines, err := client.ListMachines(ctx, nil)
if err != nil {
return nil, cobra.ShellCompDirectiveError
}
names := []cobra.Completion{}
for _, machine := range machines {
if slices.Contains(args, machine.Machine.Name) {
continue
}
if strings.HasPrefix(machine.Machine.Name, toComplete) {
names = append(names, machine.Machine.Name)
}
}
return names, cobra.ShellCompDirectiveNoFileComp
}
func MachinesFlag(cmd *cobra.Command) {
cmd.RegisterFlagCompletionFunc("machine",
func(cmd *cobra.Command, args []string, toComplete string) ([]cobra.Completion, cobra.ShellCompDirective) {
uncli := cmd.Context().Value("cli").(*cli.CLI)
return Machines(cmd.Context(), uncli, args, toComplete)
})
}
+34
View File
@@ -0,0 +1,34 @@
// Package completion implements completion functions for the uc cli.
package completion
import (
"context"
"slices"
"strings"
"github.com/psviderski/uncloud/internal/cli"
"github.com/spf13/cobra"
)
func Services(ctx context.Context, uncli *cli.CLI, args []string, toComplete string) ([]cobra.Completion, cobra.ShellCompDirective) {
client, err := uncli.ConnectCluster(ctx)
if err != nil {
return nil, cobra.ShellCompDirectiveError
}
defer client.Close()
services, err := client.ListServices(ctx)
if err != nil {
return nil, cobra.ShellCompDirectiveError
}
names := []cobra.Completion{}
for _, service := range services {
if slices.Contains(args, service.Name) {
continue
}
if strings.HasPrefix(service.Name, toComplete) {
names = append(names, service.Name)
}
}
return names, cobra.ShellCompDirectiveNoFileComp
}
+34
View File
@@ -0,0 +1,34 @@
package completion
import (
"context"
"slices"
"strings"
"github.com/psviderski/uncloud/internal/cli"
"github.com/psviderski/uncloud/pkg/api"
"github.com/spf13/cobra"
)
func Volumes(ctx context.Context, uncli *cli.CLI, args []string, toComplete string) ([]cobra.Completion, cobra.ShellCompDirective) {
client, err := uncli.ConnectCluster(ctx)
if err != nil {
return nil, cobra.ShellCompDirectiveError
}
defer client.Close()
volumes, err := client.ListVolumes(ctx, &api.VolumeFilter{})
if err != nil {
return nil, cobra.ShellCompDirectiveError
}
names := []cobra.Completion{}
for _, volume := range volumes {
if slices.Contains(args, volume.Volume.Name) {
continue
}
if strings.HasPrefix(volume.Volume.Name, toComplete) {
names = append(names, volume.Volume.Name)
}
}
return names, cobra.ShellCompDirectiveNoFileComp
}