2018-12-11 09:50:04 -05:00
|
|
|
package cliplugins
|
|
|
|
|
|
|
|
import (
|
|
|
|
"regexp"
|
|
|
|
"testing"
|
|
|
|
|
2020-02-22 12:12:14 -05:00
|
|
|
"gotest.tools/v3/assert"
|
|
|
|
is "gotest.tools/v3/assert/cmp"
|
|
|
|
"gotest.tools/v3/icmd"
|
2018-12-11 09:50:04 -05:00
|
|
|
)
|
|
|
|
|
|
|
|
// TestGlobalHelp ensures correct behaviour when running `docker help`
|
|
|
|
func TestGlobalHelp(t *testing.T) {
|
2019-02-18 06:49:41 -05:00
|
|
|
run, _, cleanup := prepare(t)
|
2018-12-11 09:50:04 -05:00
|
|
|
defer cleanup()
|
|
|
|
|
|
|
|
res := icmd.RunCmd(run("help"))
|
|
|
|
res.Assert(t, icmd.Expected{
|
|
|
|
ExitCode: 0,
|
|
|
|
})
|
|
|
|
assert.Assert(t, is.Equal(res.Stderr(), ""))
|
2022-03-26 12:54:40 -04:00
|
|
|
output := res.Stdout()
|
2018-12-11 09:50:04 -05:00
|
|
|
|
|
|
|
// Instead of baking in the full current output of `docker
|
|
|
|
// help`, which can be expected to change regularly, bake in
|
|
|
|
// some checkpoints. Key things we are looking for:
|
|
|
|
//
|
|
|
|
// - The top-level description
|
|
|
|
// - Each of the main headings
|
|
|
|
// - Some builtin commands under the main headings
|
|
|
|
// - The `helloworld` plugin in the appropriate place
|
2018-12-19 06:29:01 -05:00
|
|
|
// - The `badmeta` plugin under the "Invalid Plugins" heading.
|
2018-12-11 09:50:04 -05:00
|
|
|
//
|
|
|
|
// Regexps are needed because the width depends on `unix.TIOCGWINSZ` or similar.
|
2022-03-26 12:54:40 -04:00
|
|
|
for _, s := range []string{
|
|
|
|
`Management Commands:`,
|
|
|
|
`\s+container\s+Manage containers`,
|
2024-02-26 09:31:25 -05:00
|
|
|
`\s+helloworld\*\s+A basic Hello World plugin for tests`,
|
2022-03-26 12:54:40 -04:00
|
|
|
`\s+image\s+Manage images`,
|
|
|
|
`Commands:`,
|
|
|
|
`\s+create\s+Create a new container`,
|
|
|
|
`Invalid Plugins:`,
|
|
|
|
`\s+badmeta\s+invalid metadata: invalid character 'i' looking for beginning of object key string`,
|
2018-12-11 09:50:04 -05:00
|
|
|
} {
|
2022-03-26 12:54:40 -04:00
|
|
|
expected := regexp.MustCompile(`(?m)^` + s + `$`)
|
|
|
|
matches := expected.FindAllString(output, -1)
|
|
|
|
assert.Equal(t, len(matches), 1, "Did not find expected number of matches for %q in `docker help` output", expected)
|
2018-12-11 09:50:04 -05:00
|
|
|
}
|
2019-01-30 05:46:31 -05:00
|
|
|
|
|
|
|
// Running with `--help` should produce the same.
|
2019-04-26 05:37:26 -04:00
|
|
|
t.Run("help_flag", func(t *testing.T) {
|
|
|
|
res2 := icmd.RunCmd(run("--help"))
|
|
|
|
res2.Assert(t, icmd.Expected{
|
|
|
|
ExitCode: 0,
|
|
|
|
})
|
2022-03-26 12:54:40 -04:00
|
|
|
assert.Assert(t, is.Equal(res2.Stdout(), output))
|
2019-04-26 05:37:26 -04:00
|
|
|
assert.Assert(t, is.Equal(res2.Stderr(), ""))
|
2019-01-30 05:46:31 -05:00
|
|
|
})
|
2019-01-22 08:44:39 -05:00
|
|
|
|
2019-01-30 05:46:31 -05:00
|
|
|
// Running just `docker` (without `help` nor `--help`) should produce the same thing, except on Stderr.
|
2019-04-26 05:37:26 -04:00
|
|
|
t.Run("bare", func(t *testing.T) {
|
|
|
|
res2 := icmd.RunCmd(run())
|
|
|
|
res2.Assert(t, icmd.Expected{
|
|
|
|
ExitCode: 0,
|
|
|
|
})
|
|
|
|
assert.Assert(t, is.Equal(res2.Stdout(), ""))
|
2022-03-26 12:54:40 -04:00
|
|
|
assert.Assert(t, is.Equal(res2.Stderr(), output))
|
2019-01-22 08:44:39 -05:00
|
|
|
})
|
2019-04-26 10:08:22 -04:00
|
|
|
|
|
|
|
t.Run("badopt", func(t *testing.T) {
|
|
|
|
// Running `docker --badopt` should also produce the
|
|
|
|
// same thing, give or take the leading error message
|
|
|
|
// and a trailing carriage return (due to main() using
|
|
|
|
// Println in the error case).
|
|
|
|
res2 := icmd.RunCmd(run("--badopt"))
|
|
|
|
res2.Assert(t, icmd.Expected{
|
|
|
|
ExitCode: 125,
|
|
|
|
})
|
|
|
|
assert.Assert(t, is.Equal(res2.Stdout(), ""))
|
2022-03-26 12:54:40 -04:00
|
|
|
assert.Assert(t, is.Contains(res2.Stderr(), "unknown flag: --badopt"))
|
cli: FlagErrorFunc: don't print long usage output for invalid flags
When trying to use an invalid flag, the CLI currently prints the a short
error message, instructions to use the `--help` flag to learn about the
correct usage, followed by the command's usage output.
While this is a common convention, and may have been a nice gesture when
docker was still young and only had a few commands and options ("you did
something wrong, but here's an overview of what you can use"), that's no
longer the case, and many commands have a _very_ long output.
The result of this is that the error message, which is the relevant
information in this case - "You mis-typed something" - is lost in the
output, and hard to find (sometimes even requiring scrolling back).
The output is also confusing, because it _looks_ like something ran
successfully (most of the output is not about the error!).
Even further; the suggested resolution (try `--help` to see the correct
options) is rather redundant, because running teh command with `--help`
produces _exactly_ the same output as was just showh, baring the error
message. As a fun fact, due to the usage output being printed, the
output even contains not one, but _two_ "call to actions";
- `See 'docker volume --help'.` (under the erro message)
- `Run 'docker volume COMMAND --help' for more information on a command.`
(under the usage output)
In short; the output is too verbose, confusing, and doesn't provide
a good UX. Let's reduce the output produced so that the focus is on the
important information.
This patch:
- Changes the usage to the short-usage.
- Prefixes the error message with the binary / root-command name
(usually `docker:`) to be consistent with `unknon command`, and helps
to distinguish where the message originated from (the `docker` CLI in
this case).
- Adds an empty line between the error-message and the "call to action"
(`Run 'docker volume --help' ...` in the example below). This helps
separating the error message ("unkown flag") from the call-to-action.
Before this patch:
docker volume --no-such-flag
unknown flag: --no-such-flag
See 'docker volume --help'.
Usage: docker volume COMMAND
Manage volumes
Commands:
create Create a volume
inspect Display detailed information on one or more volumes
ls List volumes
prune Remove unused local volumes
rm Remove one or more volumes
update Update a volume (cluster volumes only)
Run 'docker volume COMMAND --help' for more information on a command.
With this patch:
docker volume --no-such-flag
docker: unknown flag: --no-such-flag
Usage: docker volume COMMAND
Run 'docker volume --help' for more information
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-07-04 17:45:30 -04:00
|
|
|
assert.Assert(t, is.Contains(res2.Stderr(), "Run 'docker --help' for more information"))
|
2019-04-26 10:08:22 -04:00
|
|
|
})
|
2018-12-11 09:50:04 -05:00
|
|
|
}
|