-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: ctx cancellation on login prompt #5168
Conversation
Before this, when receiving a
However, now it's exiting with
I don't think this is necessarily wrong (on one hand, the user is cancelling the operation) but not sure. |
Error code 130 used to occur on the previous Prompt confirmations that were cancelled as well. I can't remember if this was an error that Go decides or that we did with os.Exit. But see here #4850 |
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #5168 +/- ##
==========================================
+ Coverage 61.43% 61.47% +0.04%
==========================================
Files 298 298
Lines 20799 20808 +9
==========================================
+ Hits 12777 12791 +14
+ Misses 7109 7105 -4
+ Partials 913 912 -1 |
Please see this PR which would also be required in the case of other commands/features not respecting context cancellation #5171 |
cli/command/utils.go
Outdated
// On Windows, force the use of the regular OS stdin stream. | ||
if runtime.GOOS == "windows" { | ||
ins = streams.NewIn(os.Stdin) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why we ignore the passed ins
on Windows?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not too sure tbh - might be a legacy bug which has been resolved. I can maybe check out if we still need to do this fallback on a windows install.
It's possible we don't need it, but I guess keep it for good measure for the time being? 🤷♂️
See this comment: https://github.com/docker/cli/blob/master/cli/command/registry.go#L94-L104
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lines 93 to 104 in b83cf58
func ConfigureAuth(cli Cli, flUser, flPassword string, authconfig *registrytypes.AuthConfig, isDefaultRegistry bool) error { | |
// On Windows, force the use of the regular OS stdin stream. | |
// | |
// See: | |
// - https://github.com/moby/moby/issues/14336 | |
// - https://github.com/moby/moby/issues/14210 | |
// - https://github.com/moby/moby/pull/17738 | |
// | |
// TODO(thaJeztah): we need to confirm if this special handling is still needed, as we may not be doing this in other places. | |
if runtime.GOOS == "windows" { | |
cli.SetIn(streams.NewIn(os.Stdin)) | |
} |
Hmm, so the code you linked is still there and already sets the in for the whole cli
so we don't need to do that again in PromptForInput
, because cli.In()
will already be the overriden stdin.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, although other places might call PromptForInput
which might not set this. We also set this in PromptForConfirmation
so keeping it consistent would be best I think.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It completely breaks the assumption that the input will be read from the provided ins
though.
If the ins
happens to be something different than stdin, it would still read from stdin on Windows.
This will also make the unit tests from this PR fail on Windows because they provide a io.Pipe
as an stdin.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alternative could be to pass a bare io.Reader
, and always handle wrapping it into a streams.In
internally; perhaps we don't even need the streams
considering that we already use moby/term
(which does most / all of the heavy-lifting in the streams
package.
I'm curious though; if we need the special handling here; did we do something wrong with setting up the CLI and/or elsewhere; we should definitely look at that, and check if this is still needed.
I did a quick search; this code was originally introduced in the Moby repo (before it was moved to docker/cli); in this commit; moby/moby@9c76504
That's this PR, and related tickets;
- Windows: [TP4] Fix docker login moby/moby#17738
- docker login: cannot input value for username on windows + powershell moby/moby#14336
- boot2docker Windows running
docker login
freezes moby/moby#14210
That PR was for Windows RS4, so ... really old, and if it was a Windows bug, that side may at least be obsolete (🤞) but we should check!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've removed the windows check in the last commit 668f874 - but still need to test a build on windows. I guess I'll need to install some older (supported) versions to ensure the majority of users won't be impacted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've tested on a recent version of windows 10 (19045.4529) and seems to work fine. I removed these lines
Lines 93 to 104 in b83cf58
func ConfigureAuth(cli Cli, flUser, flPassword string, authconfig *registrytypes.AuthConfig, isDefaultRegistry bool) error { | |
// On Windows, force the use of the regular OS stdin stream. | |
// | |
// See: | |
// - https://github.com/moby/moby/issues/14336 | |
// - https://github.com/moby/moby/issues/14210 | |
// - https://github.com/moby/moby/pull/17738 | |
// | |
// TODO(thaJeztah): we need to confirm if this special handling is still needed, as we may not be doing this in other places. | |
if runtime.GOOS == "windows" { | |
cli.SetIn(streams.NewIn(os.Stdin)) | |
} |
cli/command/utils.go
Outdated
// When the prompt returns an error, the caller should propagate the error up | ||
// the stack and close the io.Reader used for the prompt which will prevent the | ||
// background goroutine from blocking indefinitely. | ||
func PromptForInput(ctx context.Context, ins *streams.In, outs *streams.Out, message string, opts ...PromptOptions) (string, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Looks like
outs
could be bareio.Writer
(as we don't use any of the features provided bystreams.Out
- nit: perhaps use singular for the
ins
andouts
variables (in
andout
?); it's more common. - ☝️ I recalled we also had a
Streams
interface, which could be an alternative to use as argument, but it looks like that's in thecli/command
package, so a bit on the fence on that one (see comment further below) - Wondering though if this function should do a check if
outs
is a terminal, and return an error instead otherwise 🤔 ❓
Also wondering; is message
always required, or could we think of situations where the message itself is already printed, and we're only interested in input provided by a user?
In that case, this could be named WaitForInput()
and/or have a WithMessage()
option.
Finally; as this is a new function, and cli/command
is becoming a bit of a grab-bag of things; wondering if we should put this in a separate package; e.g. prompt.WaitForInput()
or userinput.Prompt()
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Even considering; if it's a separate package, we could have a separate WaitforPassword
(WaitforPassphrase
?) or RequestPassphrase
utility that would handle the disableEcho
. In that case, we could get rid of the PromptOptions
type (at least for now), or keep that one internal until we have new options that could warrant introducing more options.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if the message
parameter could have a default value since this is not a prompt like "confirm x" it's more like an open ended question "input x".
I've also gotten rid of the variadic parameter and instead opted for a utility function to disable input echo's in the terminal.
I guess one could also check inside this PromptForInput
function if it's a terminal or not - but thinking about the PromptForConfirmation
function we also don't check it there. I guess we would need think about a redesign of these two functions and move them into their own package.
@vvoland could we get this one merged? The windows specific code can be addressed in a follow-up. I'll be running some tests to verify if we need this on older (supported) versions of windows 10 Lines 93 to 104 in b83cf58
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM; needs a squash though
Signed-off-by: Alano Terblanche <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
- What I did
Implemented a new Prompt function to capture user input called
PromptForInput
. This function works virtually similar toPromptForConfirmation
and handles context cancellation.- How I did it
Replicate
PromptForConfirmation
.- How to verify it
Run
docker login
and cancel it midway with a SIGINT or SIGTERM or ctrl+c.PromptForInput
also allows for hiding user input - for example when the user enters their password.The original behavior of
docker login
should still be in-tact with trimming spaces and not showing user input on the password prompt.- Description for the changelog
- A picture of a cute animal (not mandatory but encouraged)