2024-07-05 09:54:09 -04:00
package container
import (
2024-09-26 07:35:46 -04:00
"strings"
"sync"
2024-10-22 15:40:31 -04:00
"github.com/docker/cli/cli/command"
2024-07-05 09:54:09 -04:00
"github.com/docker/cli/cli/command/completion"
2024-07-05 18:48:51 -04:00
"github.com/docker/docker/api/types/container"
2024-09-26 07:35:46 -04:00
"github.com/moby/sys/capability"
2024-07-05 19:46:47 -04:00
"github.com/moby/sys/signal"
2024-07-05 09:54:09 -04:00
"github.com/spf13/cobra"
)
2024-09-26 07:35:46 -04:00
// allCaps is the magic value for "all capabilities".
const allCaps = "ALL"
2024-07-05 09:54:09 -04:00
// allLinuxCapabilities is a list of all known Linux capabilities.
//
// TODO(thaJeztah): add descriptions, and enable descriptions for our completion scripts (cobra.CompletionOptions.DisableDescriptions is currently set to "true")
2024-09-26 07:35:46 -04:00
// TODO(thaJeztah): consider what casing we want to use for completion (see below);
//
// We need to consider what format is most convenient; currently we use the
// canonical name (uppercase and "CAP_" prefix), however, tab-completion is
// case-sensitive by default, so requires the user to type uppercase letters
// to filter the list of options.
//
// Bash completion provides a `completion-ignore-case on` option to make completion
// case-insensitive (https://askubuntu.com/a/87066), but it looks to be a global
// option; the current cobra.CompletionOptions also don't provide this as an option
// to be used in the generated completion-script.
//
// Fish completion has `smartcase` (by default?) which matches any case if
// all of the input is lowercase.
//
// Zsh does not appear have a dedicated option, but allows setting matching-rules
// (see https://superuser.com/a/1092328).
var allLinuxCapabilities = sync . OnceValue ( func ( ) [ ] string {
caps := capability . ListKnown ( )
out := make ( [ ] string , 0 , len ( caps ) + 1 )
out = append ( out , allCaps )
for _ , c := range caps {
out = append ( out , "CAP_" + strings . ToUpper ( c . String ( ) ) )
}
return out
} )
2024-07-05 09:54:09 -04:00
2024-07-05 18:48:51 -04:00
// restartPolicies is a list of all valid restart-policies..
//
// TODO(thaJeztah): add descriptions, and enable descriptions for our completion scripts (cobra.CompletionOptions.DisableDescriptions is currently set to "true")
var restartPolicies = [ ] string {
string ( container . RestartPolicyDisabled ) ,
string ( container . RestartPolicyAlways ) ,
string ( container . RestartPolicyOnFailure ) ,
string ( container . RestartPolicyUnlessStopped ) ,
}
2024-10-22 15:40:31 -04:00
// addCompletions adds the completions that `run` and `create` have in common.
func addCompletions ( cmd * cobra . Command , dockerCli command . Cli ) {
2024-10-23 09:04:58 -04:00
_ = cmd . RegisterFlagCompletionFunc ( "add-host" , completion . NoComplete )
2024-10-23 09:05:09 -04:00
_ = cmd . RegisterFlagCompletionFunc ( "annotation" , completion . NoComplete )
2024-10-23 09:09:13 -04:00
_ = cmd . RegisterFlagCompletionFunc ( "attach" , completion . FromList ( "stderr" , "stdin" , "stdout" ) )
2024-10-23 09:14:07 -04:00
_ = cmd . RegisterFlagCompletionFunc ( "blkio-weight" , completion . NoComplete )
_ = cmd . RegisterFlagCompletionFunc ( "blkio-weight-device" , completion . NoComplete )
2024-10-22 15:40:31 -04:00
_ = cmd . RegisterFlagCompletionFunc ( "cap-add" , completeLinuxCapabilityNames )
_ = cmd . RegisterFlagCompletionFunc ( "cap-drop" , completeLinuxCapabilityNames )
2024-10-23 09:16:12 -04:00
_ = cmd . RegisterFlagCompletionFunc ( "cgroup-parent" , completion . NoComplete )
2024-10-23 09:18:13 -04:00
_ = cmd . RegisterFlagCompletionFunc ( "cgroupns" , completion . FromList ( "host" , "private" ) )
2024-10-23 09:39:28 -04:00
_ = cmd . RegisterFlagCompletionFunc ( "cpu-period" , completion . NoComplete )
_ = cmd . RegisterFlagCompletionFunc ( "cpu-quota" , completion . NoComplete )
_ = cmd . RegisterFlagCompletionFunc ( "cpu-rt-period" , completion . NoComplete )
_ = cmd . RegisterFlagCompletionFunc ( "cpu-rt-runtime" , completion . NoComplete )
_ = cmd . RegisterFlagCompletionFunc ( "cpu-shares" , completion . NoComplete )
_ = cmd . RegisterFlagCompletionFunc ( "cpus" , completion . NoComplete )
_ = cmd . RegisterFlagCompletionFunc ( "cpuset-cpus" , completion . NoComplete )
_ = cmd . RegisterFlagCompletionFunc ( "cpuset-mems" , completion . NoComplete )
2024-10-23 13:17:13 -04:00
_ = cmd . RegisterFlagCompletionFunc ( "device-cgroup-rule" , completion . NoComplete )
_ = cmd . RegisterFlagCompletionFunc ( "device-read-bps" , completion . NoComplete )
_ = cmd . RegisterFlagCompletionFunc ( "device-read-iops" , completion . NoComplete )
_ = cmd . RegisterFlagCompletionFunc ( "device-write-bps" , completion . NoComplete )
_ = cmd . RegisterFlagCompletionFunc ( "device-write-iops" , completion . NoComplete )
2024-10-24 14:34:31 -04:00
_ = cmd . RegisterFlagCompletionFunc ( "dns" , completion . NoComplete )
_ = cmd . RegisterFlagCompletionFunc ( "dns-option" , completion . NoComplete )
_ = cmd . RegisterFlagCompletionFunc ( "dns-search" , completion . NoComplete )
2024-10-24 14:38:18 -04:00
_ = cmd . RegisterFlagCompletionFunc ( "domainname" , completion . NoComplete )
2024-10-23 13:19:47 -04:00
_ = cmd . RegisterFlagCompletionFunc ( "entrypoint" , completion . NoComplete )
2024-10-24 14:23:09 -04:00
_ = cmd . RegisterFlagCompletionFunc ( "expose" , completion . NoComplete )
2024-10-22 15:40:31 -04:00
_ = cmd . RegisterFlagCompletionFunc ( "env" , completion . EnvVarNames )
_ = cmd . RegisterFlagCompletionFunc ( "env-file" , completion . FileNames )
2024-10-24 14:23:22 -04:00
_ = cmd . RegisterFlagCompletionFunc ( "gpus" , completion . NoComplete )
2024-10-23 13:24:14 -04:00
_ = cmd . RegisterFlagCompletionFunc ( "group-add" , completion . NoComplete )
2024-10-23 13:26:56 -04:00
_ = cmd . RegisterFlagCompletionFunc ( "health-cmd" , completion . NoComplete )
_ = cmd . RegisterFlagCompletionFunc ( "health-interval" , completion . NoComplete )
_ = cmd . RegisterFlagCompletionFunc ( "health-retries" , completion . NoComplete )
_ = cmd . RegisterFlagCompletionFunc ( "health-start-interval" , completion . NoComplete )
_ = cmd . RegisterFlagCompletionFunc ( "health-start-period" , completion . NoComplete )
_ = cmd . RegisterFlagCompletionFunc ( "health-timeout" , completion . NoComplete )
2024-10-23 13:27:22 -04:00
_ = cmd . RegisterFlagCompletionFunc ( "hostname" , completion . NoComplete )
2024-10-23 13:32:13 -04:00
_ = cmd . RegisterFlagCompletionFunc ( "ip" , completion . NoComplete )
_ = cmd . RegisterFlagCompletionFunc ( "ip6" , completion . NoComplete )
2024-10-24 07:08:41 -04:00
_ = cmd . RegisterFlagCompletionFunc ( "ipc" , completeIpc ( dockerCli ) )
2024-10-24 14:47:14 -04:00
_ = cmd . RegisterFlagCompletionFunc ( "isolation" , completion . NoComplete )
2024-10-24 07:12:45 -04:00
_ = cmd . RegisterFlagCompletionFunc ( "kernel-memory" , completion . NoComplete )
2024-10-24 07:14:11 -04:00
_ = cmd . RegisterFlagCompletionFunc ( "label" , completion . NoComplete )
2024-10-24 07:31:25 -04:00
_ = cmd . RegisterFlagCompletionFunc ( "link" , completeLink ( dockerCli ) )
2024-10-24 07:36:15 -04:00
_ = cmd . RegisterFlagCompletionFunc ( "link-local-ip" , completion . NoComplete )
2024-10-24 08:28:07 -04:00
_ = cmd . RegisterFlagCompletionFunc ( "log-driver" , completion . NoComplete ) // TODO complete drivers
_ = cmd . RegisterFlagCompletionFunc ( "log-opt" , completion . NoComplete ) // TODO complete driver options
2024-10-24 08:30:07 -04:00
_ = cmd . RegisterFlagCompletionFunc ( "mac-address" , completion . NoComplete )
2024-10-24 08:32:46 -04:00
_ = cmd . RegisterFlagCompletionFunc ( "memory" , completion . NoComplete )
_ = cmd . RegisterFlagCompletionFunc ( "memory-reservation" , completion . NoComplete )
_ = cmd . RegisterFlagCompletionFunc ( "memory-swap" , completion . NoComplete )
_ = cmd . RegisterFlagCompletionFunc ( "memory-swappiness" , completion . NoComplete )
2024-10-24 08:33:37 -04:00
_ = cmd . RegisterFlagCompletionFunc ( "mount" , completion . NoComplete )
2024-10-24 09:01:11 -04:00
_ = cmd . RegisterFlagCompletionFunc ( "name" , completion . NoComplete )
2024-10-22 15:40:31 -04:00
_ = cmd . RegisterFlagCompletionFunc ( "network" , completion . NetworkNames ( dockerCli ) )
2024-10-24 09:02:11 -04:00
_ = cmd . RegisterFlagCompletionFunc ( "network-alias" , completion . NoComplete )
2024-10-22 15:40:31 -04:00
_ = cmd . RegisterFlagCompletionFunc ( "platform" , completion . Platforms )
_ = cmd . RegisterFlagCompletionFunc ( "pull" , completion . FromList ( PullImageAlways , PullImageMissing , PullImageNever ) )
_ = cmd . RegisterFlagCompletionFunc ( "restart" , completeRestartPolicies )
_ = cmd . RegisterFlagCompletionFunc ( "stop-signal" , completeSignals )
_ = cmd . RegisterFlagCompletionFunc ( "volumes-from" , completion . ContainerNames ( dockerCli , true ) )
}
2024-10-24 07:08:41 -04:00
// completeIpc implements shell completion for the `--ipc` option of `run` and `create`.
// The completion is partly composite.
func completeIpc ( cli command . Cli ) func ( cmd * cobra . Command , args [ ] string , toComplete string ) ( [ ] string , cobra . ShellCompDirective ) {
return func ( cmd * cobra . Command , args [ ] string , toComplete string ) ( [ ] string , cobra . ShellCompDirective ) {
if len ( toComplete ) > 0 && strings . HasPrefix ( "container" , toComplete ) { //nolint:gocritic
return [ ] string { "container:" } , cobra . ShellCompDirectiveNoSpace
}
if strings . HasPrefix ( toComplete , "container:" ) {
names , _ := completion . ContainerNames ( cli , true ) ( cmd , args , toComplete )
return prefixWith ( "container:" , names ) , cobra . ShellCompDirectiveNoFileComp
}
return [ ] string { "container:" , "host" , "none" , "private" , "shareable" } , cobra . ShellCompDirectiveNoFileComp
}
}
2024-10-24 07:31:25 -04:00
// completeLink implements shell completion for the `--link` option of `run` and `create`.
func completeLink ( cli command . Cli ) func ( cmd * cobra . Command , args [ ] string , toComplete string ) ( [ ] string , cobra . ShellCompDirective ) {
return func ( cmd * cobra . Command , args [ ] string , toComplete string ) ( [ ] string , cobra . ShellCompDirective ) {
return postfixWith ( ":" , containerNames ( cli , cmd , args , toComplete ) ) , cobra . ShellCompDirectiveNoSpace
}
}
// containerNames contacts the API to get names and optionally IDs of containers.
// In case of an error, an empty list is returned.
func containerNames ( dockerCLI completion . APIClientProvider , cmd * cobra . Command , args [ ] string , toComplete string ) [ ] string {
names , _ := completion . ContainerNames ( dockerCLI , true ) ( cmd , args , toComplete )
if names == nil {
return [ ] string { }
}
return names
}
2024-10-24 07:08:41 -04:00
// prefixWith prefixes every element in the slice with the given prefix.
func prefixWith ( prefix string , values [ ] string ) [ ] string {
result := make ( [ ] string , len ( values ) )
for i , v := range values {
result [ i ] = prefix + v
}
return result
}
2024-10-24 07:31:25 -04:00
// postfixWith appends postfix to every element in the slice.
func postfixWith ( postfix string , values [ ] string ) [ ] string {
result := make ( [ ] string , len ( values ) )
for i , v := range values {
result [ i ] = v + postfix
}
return result
}
2024-07-05 09:54:09 -04:00
func completeLinuxCapabilityNames ( cmd * cobra . Command , args [ ] string , toComplete string ) ( names [ ] string , _ cobra . ShellCompDirective ) {
2024-09-26 07:35:46 -04:00
return completion . FromList ( allLinuxCapabilities ( ) ... ) ( cmd , args , toComplete )
2024-07-05 09:54:09 -04:00
}
2024-07-05 18:48:51 -04:00
func completeRestartPolicies ( cmd * cobra . Command , args [ ] string , toComplete string ) ( names [ ] string , _ cobra . ShellCompDirective ) {
return completion . FromList ( restartPolicies ... ) ( cmd , args , toComplete )
}
2024-07-05 19:46:47 -04:00
func completeSignals ( cmd * cobra . Command , args [ ] string , toComplete string ) ( names [ ] string , _ cobra . ShellCompDirective ) {
// TODO(thaJeztah): do we want to provide the full list here, or a subset?
signalNames := make ( [ ] string , 0 , len ( signal . SignalMap ) )
for k := range signal . SignalMap {
signalNames = append ( signalNames , k )
}
return completion . FromList ( signalNames ... ) ( cmd , args , toComplete )
}