@@ -44,6 +44,65 @@ var allLinuxCapabilities = sync.OnceValue(func() []string {
4444 return out
4545})
4646
47+ // logDriverOptions provides the options for each built-in logging driver.
48+ var logDriverOptions = map [string ][]string {
49+ "awslogs" : {
50+ "max-buffer-size" , "mode" , "awslogs-create-group" , "awslogs-credentials-endpoint" , "awslogs-datetime-format" ,
51+ "awslogs-group" , "awslogs-multiline-pattern" , "awslogs-region" , "awslogs-stream" , "tag" ,
52+ },
53+ "fluentd" : {
54+ "max-buffer-size" , "mode" , "env" , "env-regex" , "labels" , "fluentd-address" , "fluentd-async" ,
55+ "fluentd-buffer-limit" , "fluentd-request-ack" , "fluentd-retry-wait" , "fluentd-max-retries" ,
56+ "fluentd-sub-second-precision" , "tag" ,
57+ },
58+ "gcplogs" : {
59+ "max-buffer-size" , "mode" , "env" , "env-regex" , "labels" , "gcp-log-cmd" , "gcp-meta-id" , "gcp-meta-name" ,
60+ "gcp-meta-zone" , "gcp-project" ,
61+ },
62+ "gelf" : {
63+ "max-buffer-size" , "mode" , "env" , "env-regex" , "labels" , "gelf-address" , "gelf-compression-level" ,
64+ "gelf-compression-type" , "gelf-tcp-max-reconnect" , "gelf-tcp-reconnect-delay" , "tag" ,
65+ },
66+ "journald" : {"max-buffer-size" , "mode" , "env" , "env-regex" , "labels" , "tag" },
67+ "json-file" : {"max-buffer-size" , "mode" , "env" , "env-regex" , "labels" , "compress" , "max-file" , "max-size" },
68+ "local" : {"max-buffer-size" , "mode" , "compress" , "max-file" , "max-size" },
69+ "none" : {},
70+ "splunk" : {
71+ "max-buffer-size" , "mode" , "env" , "env-regex" , "labels" , "splunk-caname" , "splunk-capath" , "splunk-format" ,
72+ "splunk-gzip" , "splunk-gzip-level" , "splunk-index" , "splunk-insecureskipverify" , "splunk-source" ,
73+ "splunk-sourcetype" , "splunk-token" , "splunk-url" , "splunk-verify-connection" , "tag" ,
74+ },
75+ "syslog" : {
76+ "max-buffer-size" , "mode" , "env" , "env-regex" , "labels" , "syslog-address" , "syslog-facility" , "syslog-format" ,
77+ "syslog-tls-ca-cert" , "syslog-tls-cert" , "syslog-tls-key" , "syslog-tls-skip-verify" , "tag" ,
78+ },
79+ }
80+
81+ // builtInLogDrivers provides a list of the built-in logging drivers.
82+ var builtInLogDrivers = sync .OnceValue (func () []string {
83+ drivers := make ([]string , 0 , len (logDriverOptions ))
84+ for driver := range logDriverOptions {
85+ drivers = append (drivers , driver )
86+ }
87+ return drivers
88+ })
89+
90+ // allLogDriverOptions provides all options of the built-in logging drivers.
91+ // The list does not contain duplicates.
92+ var allLogDriverOptions = sync .OnceValue (func () []string {
93+ var result []string
94+ seen := make (map [string ]bool )
95+ for driver := range logDriverOptions {
96+ for _ , opt := range logDriverOptions [driver ] {
97+ if ! seen [opt ] {
98+ seen [opt ] = true
99+ result = append (result , opt )
100+ }
101+ }
102+ }
103+ return result
104+ })
105+
47106// restartPolicies is a list of all valid restart-policies..
48107//
49108// TODO(thaJeztah): add descriptions, and enable descriptions for our completion scripts (cobra.CompletionOptions.DisableDescriptions is currently set to "true")
@@ -54,6 +113,207 @@ var restartPolicies = []string{
54113 string (container .RestartPolicyUnlessStopped ),
55114}
56115
116+ // addCompletions adds the completions that `run` and `create` have in common.
117+ func addCompletions (cmd * cobra.Command , dockerCLI completion.APIClientProvider ) {
118+ _ = cmd .RegisterFlagCompletionFunc ("attach" , completion .FromList ("stderr" , "stdin" , "stdout" ))
119+ _ = cmd .RegisterFlagCompletionFunc ("cap-add" , completeLinuxCapabilityNames )
120+ _ = cmd .RegisterFlagCompletionFunc ("cap-drop" , completeLinuxCapabilityNames )
121+ _ = cmd .RegisterFlagCompletionFunc ("cgroupns" , completeCgroupns ())
122+ _ = cmd .RegisterFlagCompletionFunc ("env" , completion .EnvVarNames )
123+ _ = cmd .RegisterFlagCompletionFunc ("env-file" , completion .FileNames )
124+ _ = cmd .RegisterFlagCompletionFunc ("ipc" , completeIpc (dockerCLI ))
125+ _ = cmd .RegisterFlagCompletionFunc ("link" , completeLink (dockerCLI ))
126+ _ = cmd .RegisterFlagCompletionFunc ("log-driver" , completeLogDriver (dockerCLI ))
127+ _ = cmd .RegisterFlagCompletionFunc ("log-opt" , completeLogOpt )
128+ _ = cmd .RegisterFlagCompletionFunc ("network" , completion .NetworkNames (dockerCLI ))
129+ _ = cmd .RegisterFlagCompletionFunc ("pid" , completePid (dockerCLI ))
130+ _ = cmd .RegisterFlagCompletionFunc ("platform" , completion .Platforms )
131+ _ = cmd .RegisterFlagCompletionFunc ("pull" , completion .FromList (PullImageAlways , PullImageMissing , PullImageNever ))
132+ _ = cmd .RegisterFlagCompletionFunc ("restart" , completeRestartPolicies )
133+ _ = cmd .RegisterFlagCompletionFunc ("security-opt" , completeSecurityOpt )
134+ _ = cmd .RegisterFlagCompletionFunc ("stop-signal" , completeSignals )
135+ _ = cmd .RegisterFlagCompletionFunc ("storage-opt" , completeStorageOpt )
136+ _ = cmd .RegisterFlagCompletionFunc ("ulimit" , completeUlimit )
137+ _ = cmd .RegisterFlagCompletionFunc ("userns" , completion .FromList ("host" ))
138+ _ = cmd .RegisterFlagCompletionFunc ("uts" , completion .FromList ("host" ))
139+ _ = cmd .RegisterFlagCompletionFunc ("volume-driver" , completeVolumeDriver (dockerCLI ))
140+ _ = cmd .RegisterFlagCompletionFunc ("volumes-from" , completion .ContainerNames (dockerCLI , true ))
141+ }
142+
143+ // completeCgroupns implements shell completion for the `--cgroupns` option of `run` and `create`.
144+ func completeCgroupns () completion.ValidArgsFn {
145+ return completion .FromList (string (container .CgroupnsModeHost ), string (container .CgroupnsModePrivate ))
146+ }
147+
148+ // completeDetachKeys implements shell completion for the `--detach-keys` option of `run` and `create`.
149+ func completeDetachKeys (_ * cobra.Command , _ []string , _ string ) ([]string , cobra.ShellCompDirective ) {
150+ return []string {"ctrl-" }, cobra .ShellCompDirectiveNoSpace
151+ }
152+
153+ // completeIpc implements shell completion for the `--ipc` option of `run` and `create`.
154+ // The completion is partly composite.
155+ func completeIpc (dockerCLI completion.APIClientProvider ) func (cmd * cobra.Command , args []string , toComplete string ) ([]string , cobra.ShellCompDirective ) {
156+ return func (cmd * cobra.Command , args []string , toComplete string ) ([]string , cobra.ShellCompDirective ) {
157+ if len (toComplete ) > 0 && strings .HasPrefix ("container" , toComplete ) { //nolint:gocritic // not swapped, matches partly typed "container"
158+ return []string {"container:" }, cobra .ShellCompDirectiveNoSpace
159+ }
160+ if strings .HasPrefix (toComplete , "container:" ) {
161+ names , _ := completion .ContainerNames (dockerCLI , true )(cmd , args , toComplete )
162+ return prefixWith ("container:" , names ), cobra .ShellCompDirectiveNoFileComp
163+ }
164+ return []string {
165+ string (container .IPCModeContainer + ":" ),
166+ string (container .IPCModeHost ),
167+ string (container .IPCModeNone ),
168+ string (container .IPCModePrivate ),
169+ string (container .IPCModeShareable ),
170+ }, cobra .ShellCompDirectiveNoFileComp
171+ }
172+ }
173+
174+ // completeLink implements shell completion for the `--link` option of `run` and `create`.
175+ func completeLink (dockerCLI completion.APIClientProvider ) func (cmd * cobra.Command , args []string , toComplete string ) ([]string , cobra.ShellCompDirective ) {
176+ return func (cmd * cobra.Command , args []string , toComplete string ) ([]string , cobra.ShellCompDirective ) {
177+ return postfixWith (":" , containerNames (dockerCLI , cmd , args , toComplete )), cobra .ShellCompDirectiveNoSpace
178+ }
179+ }
180+
181+ // completeLogDriver implements shell completion for the `--log-driver` option of `run` and `create`.
182+ // The log drivers are collected from a call to the Info endpoint with a fallback to a hard-coded list
183+ // of the build-in log drivers.
184+ func completeLogDriver (dockerCLI completion.APIClientProvider ) completion.ValidArgsFn {
185+ return func (cmd * cobra.Command , args []string , toComplete string ) ([]string , cobra.ShellCompDirective ) {
186+ info , err := dockerCLI .Client ().Info (cmd .Context ())
187+ if err != nil {
188+ return builtInLogDrivers (), cobra .ShellCompDirectiveNoFileComp
189+ }
190+ drivers := info .Plugins .Log
191+ return drivers , cobra .ShellCompDirectiveNoFileComp
192+ }
193+ }
194+
195+ // completeLogOpt implements shell completion for the `--log-opt` option of `run` and `create`.
196+ // If the user supplied a log-driver, only options for that driver are returned.
197+ func completeLogOpt (cmd * cobra.Command , _ []string , _ string ) ([]string , cobra.ShellCompDirective ) {
198+ driver , _ := cmd .Flags ().GetString ("log-driver" )
199+ if options , exists := logDriverOptions [driver ]; exists {
200+ return postfixWith ("=" , options ), cobra .ShellCompDirectiveNoSpace | cobra .ShellCompDirectiveNoFileComp
201+ }
202+ return postfixWith ("=" , allLogDriverOptions ()), cobra .ShellCompDirectiveNoSpace
203+ }
204+
205+ // completePid implements shell completion for the `--pid` option of `run` and `create`.
206+ func completePid (dockerCLI completion.APIClientProvider ) func (cmd * cobra.Command , args []string , toComplete string ) ([]string , cobra.ShellCompDirective ) {
207+ return func (cmd * cobra.Command , args []string , toComplete string ) ([]string , cobra.ShellCompDirective ) {
208+ if len (toComplete ) > 0 && strings .HasPrefix ("container" , toComplete ) { //nolint:gocritic // not swapped, matches partly typed "container"
209+ return []string {"container:" }, cobra .ShellCompDirectiveNoSpace
210+ }
211+ if strings .HasPrefix (toComplete , "container:" ) {
212+ names , _ := completion .ContainerNames (dockerCLI , true )(cmd , args , toComplete )
213+ return prefixWith ("container:" , names ), cobra .ShellCompDirectiveNoFileComp
214+ }
215+ return []string {"container:" , "host" }, cobra .ShellCompDirectiveNoFileComp
216+ }
217+ }
218+
219+ // completeSecurityOpt implements shell completion for the `--security-opt` option of `run` and `create`.
220+ // The completion is partly composite.
221+ func completeSecurityOpt (_ * cobra.Command , _ []string , toComplete string ) ([]string , cobra.ShellCompDirective ) {
222+ if len (toComplete ) > 0 && strings .HasPrefix ("apparmor=" , toComplete ) { //nolint:gocritic // not swapped, matches partly typed "apparmor="
223+ return []string {"apparmor=" }, cobra .ShellCompDirectiveNoSpace
224+ }
225+ if len (toComplete ) > 0 && strings .HasPrefix ("label" , toComplete ) { //nolint:gocritic // not swapped, matches partly typed "label"
226+ return []string {"label=" }, cobra .ShellCompDirectiveNoSpace
227+ }
228+ if strings .HasPrefix (toComplete , "label=" ) {
229+ if strings .HasPrefix (toComplete , "label=d" ) {
230+ return []string {"label=disable" }, cobra .ShellCompDirectiveNoFileComp
231+ }
232+ labels := []string {"disable" , "level:" , "role:" , "type:" , "user:" }
233+ return prefixWith ("label=" , labels ), cobra .ShellCompDirectiveNoSpace | cobra .ShellCompDirectiveNoFileComp
234+ }
235+ // length must be > 1 here so that completion of "s" falls through.
236+ if len (toComplete ) > 1 && strings .HasPrefix ("seccomp" , toComplete ) { //nolint:gocritic // not swapped, matches partly typed "seccomp"
237+ return []string {"seccomp=" }, cobra .ShellCompDirectiveNoSpace
238+ }
239+ if strings .HasPrefix (toComplete , "seccomp=" ) {
240+ return []string {"seccomp=unconfined" }, cobra .ShellCompDirectiveNoFileComp
241+ }
242+ return []string {"apparmor=" , "label=" , "no-new-privileges" , "seccomp=" , "systempaths=unconfined" }, cobra .ShellCompDirectiveNoFileComp
243+ }
244+
245+ // completeStorageOpt implements shell completion for the `--storage-opt` option of `run` and `create`.
246+ func completeStorageOpt (_ * cobra.Command , _ []string , _ string ) ([]string , cobra.ShellCompDirective ) {
247+ return []string {"size=" }, cobra .ShellCompDirectiveNoSpace
248+ }
249+
250+ // completeUlimit implements shell completion for the `--ulimit` option of `run` and `create`.
251+ func completeUlimit (_ * cobra.Command , _ []string , _ string ) ([]string , cobra.ShellCompDirective ) {
252+ limits := []string {
253+ "as" ,
254+ "chroot" ,
255+ "core" ,
256+ "cpu" ,
257+ "data" ,
258+ "fsize" ,
259+ "locks" ,
260+ "maxlogins" ,
261+ "maxsyslogins" ,
262+ "memlock" ,
263+ "msgqueue" ,
264+ "nice" ,
265+ "nofile" ,
266+ "nproc" ,
267+ "priority" ,
268+ "rss" ,
269+ "rtprio" ,
270+ "sigpending" ,
271+ "stack" ,
272+ }
273+ return postfixWith ("=" , limits ), cobra .ShellCompDirectiveNoSpace
274+ }
275+
276+ // completeVolumeDriver contacts the API to get the built-in and installed volume drivers.
277+ func completeVolumeDriver (dockerCLI completion.APIClientProvider ) completion.ValidArgsFn {
278+ return func (cmd * cobra.Command , _ []string , _ string ) ([]string , cobra.ShellCompDirective ) {
279+ info , err := dockerCLI .Client ().Info (cmd .Context ())
280+ if err != nil {
281+ // fallback: the built-in drivers
282+ return []string {"local" }, cobra .ShellCompDirectiveNoFileComp
283+ }
284+ drivers := info .Plugins .Volume
285+ return drivers , cobra .ShellCompDirectiveNoFileComp
286+ }
287+ }
288+
289+ // containerNames contacts the API to get names and optionally IDs of containers.
290+ // In case of an error, an empty list is returned.
291+ func containerNames (dockerCLI completion.APIClientProvider , cmd * cobra.Command , args []string , toComplete string ) []string {
292+ names , _ := completion .ContainerNames (dockerCLI , true )(cmd , args , toComplete )
293+ if names == nil {
294+ return []string {}
295+ }
296+ return names
297+ }
298+
299+ // prefixWith prefixes every element in the slice with the given prefix.
300+ func prefixWith (prefix string , values []string ) []string {
301+ result := make ([]string , len (values ))
302+ for i , v := range values {
303+ result [i ] = prefix + v
304+ }
305+ return result
306+ }
307+
308+ // postfixWith appends postfix to every element in the slice.
309+ func postfixWith (postfix string , values []string ) []string {
310+ result := make ([]string , len (values ))
311+ for i , v := range values {
312+ result [i ] = v + postfix
313+ }
314+ return result
315+ }
316+
57317func completeLinuxCapabilityNames (cmd * cobra.Command , args []string , toComplete string ) (names []string , _ cobra.ShellCompDirective ) {
58318 return completion .FromList (allLinuxCapabilities ()... )(cmd , args , toComplete )
59319}
0 commit comments