Skip to content

Improve Cobra completions for run and create - #5580

Merged
thaJeztah merged 15 commits into
docker:masterfrom
albers:container-completions
Nov 14, 2024
Merged

Improve Cobra completions for run and create#5580
thaJeztah merged 15 commits into
docker:masterfrom
albers:container-completions

Conversation

@albers

@albersalbers commented Oct 28, 2024

Copy link
Copy Markdown
Collaborator

- What I did
Added Cobra completion for all options of docker run and docker create.

- How I did it
Provided FlagCompletionFuncs for all options except for

  • boolean flags (default completion works)
  • flags with file completions (default completion works)
  • flags that already had a completion function.

The reference for my work was the legacy bash completion.
Features that I did not recreate:

  • completion for --user
  • completion for the individual log driver options
  • completion of non-built-in drivers

- How to verify it

  1. In a dev container, issue make completion, then try completions of various docker run and docker create commands.
  2. In another terminal, exec into the container, install the legacy completion with . ./contrib/completion/bash/docker. then execute the same completions for reference.

- Description for the changelog
Improved completions for docker run and docker create.

Ported some completions from the bash completion to the new cobra based completion.

@albers
albers marked this pull request as ready for review October 28, 2024 22:55
@albers
albers requested a review from thaJeztahOctober 28, 2024 22:55
@codecov-commenter

codecov-commenter commented Oct 28, 2024

Copy link
Copy Markdown

Codecov Report

Attention: Patch coverage is 43.50282% with 100 lines in your changes missing coverage. Please review.

Project coverage is 59.50%. Comparing base (61baf2a) to head (06260e6).
Report is 82 commits behind head on master.

Additional details and impacted files
@@ Coverage Diff @@## master #5580 +/- ##
==========================================
+ Coverage 59.21% 59.50% +0.28% 
==========================================
Files 342 346 +4 Lines 29083 29365 +282 ==========================================
+ Hits 17222 17474 +252 - Misses 10889 10916 +27 - Partials 972 975 +3 

@thaJeztahthaJeztah left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is amazing work, thank you!! I left quite some comments, but welcome your feedback/thoughts.

I think the most notable one that could reduce a lot of boiler plating, is the comment on (perhaps could be a utility) setting a "default" NoComplete on all flags; that way we wouldn't have to set the NoComplete for all flags that don't have one. (Although maybe there's something to be said for explicitly setting "no completions here)

Comment threadcli/command/container/completion.go Outdated

// addCompletions adds the completions that `run` and `create` have in common.
func addCompletions(cmd *cobra.Command, dockerCli command.Cli) {
_ = cmd.RegisterFlagCompletionFunc("add-host", completion.NoComplete)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ugh, yes, this is something I was looking at as well. I was considering if we could set a default, then optionally override, but Cobra currently doesn't allow for a completion to be replaced once set;

if_, exists:=flagCompletionFunctions[flag]; exists {
returnfmt.Errorf("RegisterFlagCompletionFunc: flag '%s' already registered", flagName)
}
flagCompletionFunctions[flag] =f

In that case, if the flag has no completion, it returns here;

if!finalCmd.DisableFlagParsing {
// If DisableFlagParsing==false, we have completed the flags as known by Cobra;
// we can return what we found.
// If DisableFlagParsing==true, Cobra may not be aware of all flags, so we
// let the logic continue to see if ValidArgsFunction needs to be called.
returnfinalCmd, completions, directive, nil
}

Which returns with ShellCompDirectiveNoFileComp

directive=ShellCompDirectiveNoFileComp

I think ideally Cobra would allow setting a custom default for flags, but perhaps a somewhat dirty, but functional one would be to do it ourselves, and set a default at the very end of functions that constructed a command, e.g. at;

flags.VisitAll(func(flag*pflag.Flag) {
// Set a default completion function if none was set. We don't look// up if it does already have one set, because Cobra does this for// us, and returns an error (which we ignore for this reason)._=cmd.RegisterFlagCompletionFunc(flag.Name, completion.NoComplete)
})
returncmd

I was a bit on the fence on using VisitAll, but it looks like there's many places where Cobra already does, so maybe not too bad, WDYT?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could not find a way to set a default ShellCompDirective for silencing the numerouns flags with inapproptiate file completions.

IMHO this should be handled in Cobra. I'll open a feature request for this.

Your workaround looks very promising, I'll give it a try.

Comment threadcli/command/container/completion.go Outdated
func addCompletions(cmd *cobra.Command, dockerCli command.Cli) {
_ = cmd.RegisterFlagCompletionFunc("add-host", completion.NoComplete)
_ = cmd.RegisterFlagCompletionFunc("annotation", completion.NoComplete)
_ = cmd.RegisterFlagCompletionFunc("attach", completion.FromList("stderr", "stdin", "stdout"))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Heh; I was working on this one, when I discovered completion doesn't work for specifying --attach multiple times.

I started looking "why???" because it does work for some other flags we define multiple times, which is when I discovered the reason; Cobra has some "magic" values for flag "types"; if the flag-type ends with Slice or Array it considers that it can be used multiple times. If not, it considers that the flag can only be set once and it removes it from the suggestions;

if!flag.Changed||
strings.Contains(flag.Value.Type(), "Slice") ||
strings.Contains(flag.Value.Type(), "Array") {
// If the flag is not already present, or if it can be specified multiple times (Array or Slice)
// we suggest it as a completion
completions=append(completions, getFlagNameCompletions(flag, toComplete)...)
}

In our case, some types use list as name, which isn't matched. I'm considering contributing a patch to Cobra to make it somewhat smarter;

  • make the matching case-insensitive
  • possibly add list to the magic strings

But also to have it match SliceValue, which is an interface defined by the pflag module used by Cobra for flags. I think it's an omission that it doesn't consider that interface;

typeSliceValueinterface {
// Append adds the specified value to the end of the flag value list.
Append(string) error
// Replace will fully overwrite any data currently in the flag value list.
Replace([]string) error
// GetSlice returns the flag value list as an array of strings.
GetSlice() []string
}

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, now I understand.
I was also wondering why the events --filter completion only works once.

Comment threadcli/command/container/completion.go Outdated
Comment threadcli/command/container/completion.go Outdated
Comment on lines +82 to +84
_ = cmd.RegisterFlagCompletionFunc("dns", completion.NoComplete)
_ = cmd.RegisterFlagCompletionFunc("dns-option", completion.NoComplete)
_ = cmd.RegisterFlagCompletionFunc("dns-search", completion.NoComplete)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly "note to self" - I think it's fine to disable completion for these for now.

  • For dns-option we could at some point consider adding the list from https://man7.org/linux/man-pages/man5/resolv.conf.5.html
  • For dns-search I wonder how much sense it would make to complete based on the current host's settings. That would not make sense for a remote daemon, but wondering if it's still useful for situations where the daemon runs locally.
  • (same for dns)

Comment threadcli/command/container/completion.go Outdated
Comment threadcli/command/container/completion.go Outdated

// completeDetachKeys implements shell completion for the `--detach-keys` option of `run` and `create`.
func completeDetachKeys(_ *cobra.Command, _ []string, _ string) ([]string, cobra.ShellCompDirective) {
return []string{"ctrl-"}, cobra.ShellCompDirectiveNoSpace

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note to self; I need to lookup if there's other special ones we define (meta-, alt-, possibly others)

Comment threadcli/command/container/completion_test.go
Comment threadcli/command/container/completion.go Outdated
@thaJeztahthaJeztah added this to the 28.0.0 milestone Oct 29, 2024
@albers
albersforce-pushed the container-completions branch from 110bb3d to ef6cca9CompareOctober 30, 2024 19:45
@albersalbers changed the title Improve cobra completions for run and createImprove Cobra completions for run and createOct 30, 2024
@albers

Copy link
Copy Markdown
CollaboratorAuthor

@thaJeztah Thanks very much for your mentoring. It's very much appreciated.

I think I'm through with your review comments, please take another look.

@albers
albers requested a review from thaJeztahOctober 30, 2024 20:23

@BenehikoBenehiko left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@albers

Copy link
Copy Markdown
CollaboratorAuthor

Let me know when I can squash the commits into a more relevant set of commits.

@laurazard

laurazard commented Nov 7, 2024

Copy link
Copy Markdown
Member

Thank you so much for this @albers!

I'm thinking we could squash 4378ab4 (#5580) together with all the "disable file completions for X" commit, and also take care of 33d3246 (#5580) – and whatever else there is – but overall looks good!

Signed-off-by: Harald Albers <github@albersweb.de>
Signed-off-by: Harald Albers <github@albersweb.de>
Signed-off-by: Harald Albers <github@albersweb.de>
Signed-off-by: Harald Albers <github@albersweb.de>
@albers
albersforce-pushed the container-completions branch from 4378ab4 to 32957b3CompareNovember 8, 2024 15:47
Signed-off-by: Harald Albers <github@albersweb.de>
Signed-off-by: Harald Albers <github@albersweb.de>
Signed-off-by: Harald Albers <github@albersweb.de>
Signed-off-by: Harald Albers <github@albersweb.de>
Signed-off-by: Harald Albers <github@albersweb.de>
Signed-off-by: Harald Albers <github@albersweb.de>
Signed-off-by: Harald Albers <github@albersweb.de>
Signed-off-by: Harald Albers <github@albersweb.de>
Signed-off-by: Harald Albers <github@albersweb.de>
Signed-off-by: Harald Albers <github@albersweb.de>
Credits to thaJeztah
Signed-off-by: Harald Albers <github@albersweb.de>
@albers
albersforce-pushed the container-completions branch from 32957b3 to 06260e6CompareNovember 8, 2024 15:57
@albers

Copy link
Copy Markdown
CollaboratorAuthor

@laurazard The commits are now squashed to a sequence of meaningful, self-contained commits.

@thaJeztah would you like to take another look at this PR?

@laurazardlaurazard left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-LGTM. Thanks!

@thaJeztahthaJeztah left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

Sorry thought I already did 🙈 🙈 🙈

@thaJeztah
thaJeztah merged commit 4adbb18 into docker:masterNov 14, 2024
@albers
albers deleted the container-completions branch November 14, 2024 20:11
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@albers@codecov-commenter@laurazard@thaJeztah@Benehiko