-
Notifications
You must be signed in to change notification settings - Fork 2.1k
fix: cli prompt termination exit code #4888
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
Conversation
0bffacc to
c532931
Compare
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #4888 +/- ##
==========================================
+ Coverage 61.13% 61.45% +0.31%
==========================================
Files 287 289 +2
Lines 20136 20229 +93
==========================================
+ Hits 12310 12431 +121
+ Misses 6933 6896 -37
- Partials 893 902 +9 |
7ddd3b8 to
e67927c
Compare
| @@ -1,36 +1,45 @@ | |||
| package command | |||
| package command_test | |||
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.
had cyclical import between the command package and test.
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.
Fine if we do this, but I wonder if the cyclical import was a smell that we should move something.
e67927c to
5e14416
Compare
de7081a to
e662a1e
Compare
| fmt.Fprintf(dockerCli.Out(), " - %s: %v\n", privilege.Name, privilege.Value) | ||
| } | ||
| return command.PromptForConfirmation(dockerCli.In(), dockerCli.Out(), "Do you grant the above permissions?"), nil | ||
| ctx := context.TODO() |
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.
here the context isn't apparent. Either we use the top level dockerCli context or create a new context within the function. The moby project does not support passing context on this function call https://github.com/moby/moby/blob/d19d98b136f6a7e80029b65c5ae8886eacdf43d7/api/types/client.go#L292
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.
FWIW; if we would benefit from passing contexts, we should consider updating the moby code. For a lot of code in moby, context didn't exist yet when it was written, and we started passing through contexts more, but there's still many areas where we didn't.
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'll take a look at also adding context in the moby api client. It will help greatly with otel and just task cleanup in general.
| @@ -0,0 +1,2 @@ | |||
| Please confirm you would like to delete all signature data for example/trust-demo? [y/N] | |||
| Aborting action. | |||
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.
aah i guess this could be another confirmation prompt to "fix" by standardizing the output (aka not printing "Aborting action" and making it behave more like everything else). For another moment of course
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.
ah yeah true
f4e617d to
77ad0c2
Compare
77ad0c2 to
d4d2552
Compare
ee32a21 to
ef1624c
Compare
| @@ -0,0 +1,2 @@ | |||
| Upgrading plugin foo/bar from localhost:5000/foo/bar:v0.1.0 to localhost:5000/foo/bar:v1.0.0 | |||
| Plugin images do not match, are you sure? [y/N] No newline at end of file | |||
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.
Missing a newline at the end here? (The other new golden files have them 🤔)
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.
@Benehiko could we fix this?
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.
hmm, i'm not sure why this is. The file is generated by the -update command.
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.
Right, this is likely due to us missing a newline when printing things somewhere
laurazard
left a comment
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.
Really nice, thank you! Left a few comments (mostly nits), but overall a good change.
Not sure if I missed it, but are we explicitly testing the exit code anywhere?
4824d80 to
385e049
Compare
Hmm, I suppose we could check the status code, but the status code seems to be added to a specific error type. It seems the main package handles some exit codes based on the error type here https://github.com/docker/cli/blob/master/cmd/docker/docker.go#L35-L50 Since we gracefully propagate the error up we check for it inside the test, which I think should be enough. Wdyt? |
|
imo those tests are useful, but if we want to preserve the "exit code is 0 when user CTRL-C's a confirmation prompt" in the future, we could add this check in particular for the e2e tests for these commands. (But fine if you'd prefer to do it in another PR). |
|
Seems like this test is quite flaky 56.34 === FAIL: cli-plugins/socket TestConnectAndWait/connect_goroutine_exits_after_EOF |
Signed-off-by: Alano Terblanche <[email protected]>
f21679e to
10bf91a
Compare
| // NewWriterWithHook returns a new WriterWithHook that still writes to the actualWriter | ||
| // but also calls the hook function after every write. | ||
| // The hook function is useful for testing, or waiting for a write to complete. | ||
| func NewWriterWithHook(actualWriter io.Writer, hook func([]byte)) *WriterWithHook { |
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.
Just noticed we're only using this in internal/test and one other usage, I wonder if this needs to be public at all (thinking about this because otherwise we can relax a bit with the docstrings.
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.
Anyway, can address this (and e2e tests) in a follow-up (cc @Benehiko)
|
|
||
| // Catch the termination signal and exit the prompt gracefully. | ||
| // The caller is responsible for properly handling the termination. | ||
| notifyCtx, notifyCancel := signal.NotifyContext(ctx, syscall.SIGINT, syscall.SIGTERM) |
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 a utility function should set up signal handlers for the process as a side effect. I think this should just use the passed in context for cancellation, and if that context is tied to the os signals is up to the caller. Normally, a process already has a signal handler and this will conflict with it.
Fixes #4850
- What I did
The docker
command/utils.goprovides a function for prompting the user for a confirmation[Y/n]. To fix the termination of the CLI while the prompt is active, the reader is blocked inside a gouroutine instead allowing for checks on context cancellation from the parent or from a SIGINT/SIGTERM. An error is then propagated up the stack when the prompt is terminated instead of an immediate program termination. The caller should respect the error and either close the reader or exit the CLI to prevent goroutine leaks and unexpected behavior on re-prompting.- How I did it
Catch the termination signal on prompt.
- How to verify it
Manually and with tests.
- Description for the changelog
CLI confirmation prompts will now safely cancel the operation on termination (SIGINT/SIGTERM) producing an exit code of 0.
These are the affected CLI commands:
docker system prunedocker volume prunedocker plugin upgradedocker image prunedocker network prunedocker container prunedocker network rmdocker builder prunedocker trust revokeSome commands above are replaced by plugins, which will not be affected.
- A picture of a cute animal (not mandatory but encouraged)

(https://www.rawpixel.com/image/6041428/photo-image-background-public-domain-cat)