cli/command/container: unify completion funcs for create and run

Define completion funcs for create and run together with where
the flags are defined.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
Sebastiaan van Stijn 2024-10-29 13:06:51 +01:00
parent 32ff200fe6
commit 9454c560c1
No known key found for this signature in database
GPG Key ID: 76698F39D527CE8C
4 changed files with 29 additions and 29 deletions

View File

@ -75,19 +75,9 @@ func NewCreateCommand(dockerCli command.Cli) *cobra.Command {
flags.Bool("help", false, "Print usage") flags.Bool("help", false, "Print usage")
command.AddPlatformFlag(flags, &options.platform) command.AddPlatformFlag(flags, &options.platform)
command.AddTrustVerificationFlags(flags, &options.untrusted, dockerCli.ContentTrustEnabled())
copts = addFlags(flags)
_ = cmd.RegisterFlagCompletionFunc("cap-add", completeLinuxCapabilityNames)
_ = cmd.RegisterFlagCompletionFunc("cap-drop", completeLinuxCapabilityNames)
_ = cmd.RegisterFlagCompletionFunc("env", completion.EnvVarNames)
_ = cmd.RegisterFlagCompletionFunc("env-file", completion.FileNames)
_ = cmd.RegisterFlagCompletionFunc("network", completion.NetworkNames(dockerCli))
_ = cmd.RegisterFlagCompletionFunc("platform", completion.Platforms) _ = cmd.RegisterFlagCompletionFunc("platform", completion.Platforms)
_ = cmd.RegisterFlagCompletionFunc("pull", completion.FromList(PullImageAlways, PullImageMissing, PullImageNever)) command.AddTrustVerificationFlags(flags, &options.untrusted, dockerCli.ContentTrustEnabled())
_ = cmd.RegisterFlagCompletionFunc("restart", completeRestartPolicies) copts = addContainerCreateFlags(cmd, dockerCli)
_ = cmd.RegisterFlagCompletionFunc("stop-signal", completeSignals)
_ = cmd.RegisterFlagCompletionFunc("volumes-from", completion.ContainerNames(dockerCli, true))
return cmd return cmd
} }

View File

@ -14,6 +14,7 @@ import (
"time" "time"
"github.com/docker/cli/cli/command" "github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/command/completion"
"github.com/docker/cli/cli/compose/loader" "github.com/docker/cli/cli/compose/loader"
"github.com/docker/cli/opts" "github.com/docker/cli/opts"
"github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/container"
@ -24,6 +25,7 @@ import (
"github.com/docker/go-connections/nat" "github.com/docker/go-connections/nat"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/spf13/pflag" "github.com/spf13/pflag"
cdi "tags.cncf.io/container-device-interface/pkg/parser" cdi "tags.cncf.io/container-device-interface/pkg/parser"
) )
@ -145,8 +147,9 @@ type containerOptions struct {
Args []string Args []string
} }
// addFlags adds all command line flags that will be used by parse to the FlagSet // addContainerCreateFlags adds all command line flags that will be used by parse to the FlagSet
func addFlags(flags *pflag.FlagSet) *containerOptions { func addContainerCreateFlags(cmd *cobra.Command, dockerCLI completion.APIClientProvider) *containerOptions {
flags := cmd.Flags()
copts := &containerOptions{ copts := &containerOptions{
aliases: opts.NewListOpts(nil), aliases: opts.NewListOpts(nil),
attach: opts.NewListOpts(validateAttach), attach: opts.NewListOpts(validateAttach),
@ -190,7 +193,9 @@ func addFlags(flags *pflag.FlagSet) *containerOptions {
flags.Var(&copts.gpus, "gpus", "GPU devices to add to the container ('all' to pass all GPUs)") flags.Var(&copts.gpus, "gpus", "GPU devices to add to the container ('all' to pass all GPUs)")
flags.SetAnnotation("gpus", "version", []string{"1.40"}) flags.SetAnnotation("gpus", "version", []string{"1.40"})
flags.VarP(&copts.env, "env", "e", "Set environment variables") flags.VarP(&copts.env, "env", "e", "Set environment variables")
_ = cmd.RegisterFlagCompletionFunc("env", completion.EnvVarNames)
flags.Var(&copts.envFile, "env-file", "Read in a file of environment variables") flags.Var(&copts.envFile, "env-file", "Read in a file of environment variables")
_ = cmd.RegisterFlagCompletionFunc("env-file", completion.FileNames)
flags.StringVar(&copts.entrypoint, "entrypoint", "", "Overwrite the default ENTRYPOINT of the image") flags.StringVar(&copts.entrypoint, "entrypoint", "", "Overwrite the default ENTRYPOINT of the image")
flags.Var(&copts.groupAdd, "group-add", "Add additional groups to join") flags.Var(&copts.groupAdd, "group-add", "Add additional groups to join")
flags.StringVarP(&copts.hostname, "hostname", "h", "", "Container host name") flags.StringVarP(&copts.hostname, "hostname", "h", "", "Container host name")
@ -200,7 +205,9 @@ func addFlags(flags *pflag.FlagSet) *containerOptions {
flags.Var(&copts.labelsFile, "label-file", "Read in a line delimited file of labels") flags.Var(&copts.labelsFile, "label-file", "Read in a line delimited file of labels")
flags.BoolVar(&copts.readonlyRootfs, "read-only", false, "Mount the container's root filesystem as read only") flags.BoolVar(&copts.readonlyRootfs, "read-only", false, "Mount the container's root filesystem as read only")
flags.StringVar(&copts.restartPolicy, "restart", string(container.RestartPolicyDisabled), "Restart policy to apply when a container exits") flags.StringVar(&copts.restartPolicy, "restart", string(container.RestartPolicyDisabled), "Restart policy to apply when a container exits")
_ = cmd.RegisterFlagCompletionFunc("restart", completeRestartPolicies)
flags.StringVar(&copts.stopSignal, "stop-signal", "", "Signal to stop the container") flags.StringVar(&copts.stopSignal, "stop-signal", "", "Signal to stop the container")
_ = cmd.RegisterFlagCompletionFunc("stop-signal", completeSignals)
flags.IntVar(&copts.stopTimeout, "stop-timeout", 0, "Timeout (in seconds) to stop a container") flags.IntVar(&copts.stopTimeout, "stop-timeout", 0, "Timeout (in seconds) to stop a container")
flags.SetAnnotation("stop-timeout", "version", []string{"1.25"}) flags.SetAnnotation("stop-timeout", "version", []string{"1.25"})
flags.Var(copts.sysctls, "sysctl", "Sysctl options") flags.Var(copts.sysctls, "sysctl", "Sysctl options")
@ -212,7 +219,9 @@ func addFlags(flags *pflag.FlagSet) *containerOptions {
// Security // Security
flags.Var(&copts.capAdd, "cap-add", "Add Linux capabilities") flags.Var(&copts.capAdd, "cap-add", "Add Linux capabilities")
_ = cmd.RegisterFlagCompletionFunc("cap-add", completeLinuxCapabilityNames)
flags.Var(&copts.capDrop, "cap-drop", "Drop Linux capabilities") flags.Var(&copts.capDrop, "cap-drop", "Drop Linux capabilities")
_ = cmd.RegisterFlagCompletionFunc("cap-drop", completeLinuxCapabilityNames)
flags.BoolVar(&copts.privileged, "privileged", false, "Give extended privileges to this container") flags.BoolVar(&copts.privileged, "privileged", false, "Give extended privileges to this container")
flags.Var(&copts.securityOpt, "security-opt", "Security Options") flags.Var(&copts.securityOpt, "security-opt", "Security Options")
flags.StringVar(&copts.usernsMode, "userns", "", "User namespace to use") flags.StringVar(&copts.usernsMode, "userns", "", "User namespace to use")
@ -242,8 +251,9 @@ func addFlags(flags *pflag.FlagSet) *containerOptions {
flags.BoolVarP(&copts.publishAll, "publish-all", "P", false, "Publish all exposed ports to random ports") flags.BoolVarP(&copts.publishAll, "publish-all", "P", false, "Publish all exposed ports to random ports")
// We allow for both "--net" and "--network", although the latter is the recommended way. // We allow for both "--net" and "--network", although the latter is the recommended way.
flags.Var(&copts.netMode, "net", "Connect a container to a network") flags.Var(&copts.netMode, "net", "Connect a container to a network")
_ = flags.MarkHidden("net")
flags.Var(&copts.netMode, "network", "Connect a container to a network") flags.Var(&copts.netMode, "network", "Connect a container to a network")
flags.MarkHidden("net") _ = cmd.RegisterFlagCompletionFunc("network", completion.NetworkNames(dockerCLI))
// We allow for both "--net-alias" and "--network-alias", although the latter is the recommended way. // We allow for both "--net-alias" and "--network-alias", although the latter is the recommended way.
flags.Var(&copts.aliases, "net-alias", "Add network-scoped alias for the container") flags.Var(&copts.aliases, "net-alias", "Add network-scoped alias for the container")
flags.Var(&copts.aliases, "network-alias", "Add network-scoped alias for the container") flags.Var(&copts.aliases, "network-alias", "Add network-scoped alias for the container")
@ -256,6 +266,7 @@ func addFlags(flags *pflag.FlagSet) *containerOptions {
flags.Var(&copts.storageOpt, "storage-opt", "Storage driver options for the container") flags.Var(&copts.storageOpt, "storage-opt", "Storage driver options for the container")
flags.Var(&copts.tmpfs, "tmpfs", "Mount a tmpfs directory") flags.Var(&copts.tmpfs, "tmpfs", "Mount a tmpfs directory")
flags.Var(&copts.volumesFrom, "volumes-from", "Mount volumes from the specified container(s)") flags.Var(&copts.volumesFrom, "volumes-from", "Mount volumes from the specified container(s)")
_ = cmd.RegisterFlagCompletionFunc("volumes-from", completion.ContainerNames(dockerCLI, true))
flags.VarP(&copts.volumes, "volume", "v", "Bind mount a volume") flags.VarP(&copts.volumes, "volume", "v", "Bind mount a volume")
flags.Var(&copts.mounts, "mount", "Attach a filesystem mount to the container") flags.Var(&copts.mounts, "mount", "Attach a filesystem mount to the container")

View File

@ -9,10 +9,12 @@ import (
"testing" "testing"
"time" "time"
"github.com/docker/cli/cli/command/completion"
"github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/container"
networktypes "github.com/docker/docker/api/types/network" networktypes "github.com/docker/docker/api/types/network"
"github.com/docker/go-connections/nat" "github.com/docker/go-connections/nat"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/spf13/cobra"
"github.com/spf13/pflag" "github.com/spf13/pflag"
"gotest.tools/v3/assert" "gotest.tools/v3/assert"
is "gotest.tools/v3/assert/cmp" is "gotest.tools/v3/assert/cmp"
@ -57,10 +59,16 @@ func parseRun(args []string) (*container.Config, *container.HostConfig, *network
} }
func setupRunFlags() (*pflag.FlagSet, *containerOptions) { func setupRunFlags() (*pflag.FlagSet, *containerOptions) {
flags := pflag.NewFlagSet("run", pflag.ContinueOnError) dummyCmd := &cobra.Command{Use: "dummy"}
// This will panic when called, but never called in tests
type dummyCLI struct {
completion.APIClientProvider
}
flags := dummyCmd.Flags()
flags.SetOutput(io.Discard) flags.SetOutput(io.Discard)
flags.Usage = nil flags.Usage = nil
copts := addFlags(flags) copts := addContainerCreateFlags(dummyCmd, dummyCLI{})
return flags, copts return flags, copts
} }

View File

@ -59,6 +59,7 @@ func NewRunCommand(dockerCli command.Cli) *cobra.Command {
flags.StringVar(&options.name, "name", "", "Assign a name to the container") flags.StringVar(&options.name, "name", "", "Assign a name to the container")
flags.StringVar(&options.detachKeys, "detach-keys", "", "Override the key sequence for detaching a container") flags.StringVar(&options.detachKeys, "detach-keys", "", "Override the key sequence for detaching a container")
flags.StringVar(&options.pull, "pull", PullImageMissing, `Pull image before running ("`+PullImageAlways+`", "`+PullImageMissing+`", "`+PullImageNever+`")`) flags.StringVar(&options.pull, "pull", PullImageMissing, `Pull image before running ("`+PullImageAlways+`", "`+PullImageMissing+`", "`+PullImageNever+`")`)
_ = cmd.RegisterFlagCompletionFunc("pull", completion.FromList(PullImageAlways, PullImageMissing, PullImageNever))
flags.BoolVarP(&options.quiet, "quiet", "q", false, "Suppress the pull output") flags.BoolVarP(&options.quiet, "quiet", "q", false, "Suppress the pull output")
// Add an explicit help that doesn't have a `-h` to prevent the conflict // Add an explicit help that doesn't have a `-h` to prevent the conflict
@ -66,19 +67,9 @@ func NewRunCommand(dockerCli command.Cli) *cobra.Command {
flags.Bool("help", false, "Print usage") flags.Bool("help", false, "Print usage")
command.AddPlatformFlag(flags, &options.platform) command.AddPlatformFlag(flags, &options.platform)
command.AddTrustVerificationFlags(flags, &options.untrusted, dockerCli.ContentTrustEnabled())
copts = addFlags(flags)
_ = cmd.RegisterFlagCompletionFunc("cap-add", completeLinuxCapabilityNames)
_ = cmd.RegisterFlagCompletionFunc("cap-drop", completeLinuxCapabilityNames)
_ = cmd.RegisterFlagCompletionFunc("env", completion.EnvVarNames)
_ = cmd.RegisterFlagCompletionFunc("env-file", completion.FileNames)
_ = cmd.RegisterFlagCompletionFunc("network", completion.NetworkNames(dockerCli))
_ = cmd.RegisterFlagCompletionFunc("platform", completion.Platforms) _ = cmd.RegisterFlagCompletionFunc("platform", completion.Platforms)
_ = cmd.RegisterFlagCompletionFunc("pull", completion.FromList(PullImageAlways, PullImageMissing, PullImageNever)) command.AddTrustVerificationFlags(flags, &options.untrusted, dockerCli.ContentTrustEnabled())
_ = cmd.RegisterFlagCompletionFunc("restart", completeRestartPolicies) copts = addContainerCreateFlags(cmd, dockerCli)
_ = cmd.RegisterFlagCompletionFunc("stop-signal", completeSignals)
_ = cmd.RegisterFlagCompletionFunc("volumes-from", completion.ContainerNames(dockerCli, true))
return cmd return cmd
} }