Uh oh!
There was an error while loading. Please reload this page.
fix: cli prompt termination exit code - #4888
Conversation
0bffacc to
c532931CompareCodecov 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 |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
7ddd3b8 to
e67927cCompareUh oh!
There was an error while loading. Please reload this page.
| @@ -1,36 +1,45 @@ | |||
| package command | |||
| package command_test | |||
There was a problem hiding this comment.
had cyclical import between the command package and test.
There was a problem hiding this comment.
Fine if we do this, but I wonder if the cyclical import was a smell that we should move something.
e67927c to
5e14416CompareUh oh!
There was an error while loading. Please reload this page.
de7081a to
e662a1eCompare| 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.
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.
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.
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.
Uh oh!
There was an error while loading. Please reload this page.
| @@ -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.
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
f4e617d to
77ad0c2Compare77ad0c2 to
d4d2552CompareUh oh!
There was an error while loading. Please reload this page.
ee32a21 to
ef1624cCompareUh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
| @@ -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.
Missing a newline at the end here? (The other new golden files have them 🤔)
There was a problem hiding this comment.
hmm, i'm not sure why this is. The file is generated by the -update command.
There was a problem hiding this comment.
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.
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?
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
4824d80 to
385e049CompareBenehiko
commented
Mar 4, 2024
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? |
laurazard
commented
Mar 4, 2024
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). |
Benehiko
commented
Mar 4, 2024
Seems like this test is quite flaky 56.34 === FAIL: cli-plugins/socket TestConnectAndWait/connect_goroutine_exits_after_EOF |
Signed-off-by: Alano Terblanche <18033717+Benehiko@users.noreply.github.com>
f21679e to
10bf91aCompare| // 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.
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.
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.
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)