The issue with plugin options clashing with globals is that when cobra is
parsing the command line and it comes across an argument which doesn't start
with a `-` it (in the absence of plugins) distinguishes between "argument to
current command" and "new subcommand" based on the list of registered sub
commands.
Plugins breaks that model. When presented with `docker -D plugin -c foo` cobra
parses up to the `plugin`, sees it isn't a registered sub-command of the
top-level docker (because it isn't, it's a plugin) so it accumulates it as an
argument to the top-level `docker` command. Then it sees the `-c`, and thinks
it is the global `-c` (for AKA `--context`) option and tries to treat it as
that, which fails.
In the specific case of the top-level `docker` subcommand we know that it has
no arguments which aren't `--flags` (or `-f` short flags) and so anything which
doesn't start with a `-` must either be a (known) subcommand or an attempt to
execute a plugin.
We could simply scan for and register all installed plugins at start of day, so
that cobra can do the right thing, but we want to avoid that since it would
involve executing each plugin to fetch the metadata, even if the command wasn't
going to end up hitting a plugin.
Instead we can parse the initial set of global arguments separately before
hitting the main cobra `Execute` path, which works here exactly because we know
that the top-level has no non-flag arguments.
One slight wrinkle is that the top-level `PersistentPreRunE` is no longer
called on the plugins path (since it no longer goes via `Execute`), so we
arrange for the initialisation done there (which has to be done after global
flags are parsed to handle e.g. `--config`) to happen explictly after the
global flags are parsed. Rather than make `newDockerCommand` return the
complicated set of results needed to make this happen, instead return a closure
which achieves this.
The new functionality is introduced via a common `TopLevelCommand` abstraction
which lets us adjust the plugin entrypoint to use the same strategy for parsing
the global arguments. This isn't strictly required (in this case the stuff in
cobra's `Execute` works fine) but doing it this way avoids the possibility of
subtle differences in behaviour.
Fixes#1699, and also, as a side-effect, the first item in #1661.
Signed-off-by: Ian Campbell <ijc@docker.com>
These won't pass right now due to https://github.com/docker/cli/issues/1699
("Plugins can't re-use the same flags as cli global flags") and the change in
935d47bbe9 ("Ignore unknown arguments on the top-level command."), but the
intention is to fix them now.
Signed-off-by: Ian Campbell <ijc@docker.com>
... in preference to `chsh`, since in recent alpine 3.9.2 images that can fail
with:
Password: chsh: PAM: Authentication token manipulation error
Which seems to relate to the use of `!` as the password for `root` in `/etc/shadow`gq
Signed-off-by: Ian Campbell <ijc@docker.com>
By default, exec uses the environment of the current process, however,
if `exec.Env` is not `nil`, the environment is discarded:
e73f489494/src/os/exec/exec.go (L57-L60)
> If Env is nil, the new process uses the current process's environment.
When adding a new environment variable, prepend the current environment,
to make sure it is not discarded.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Plugins are expected to be management commands ("docker <object> <verb>").
This patch modified the usage output to shown plugins in the "Management commands"
section.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
- The placement of the vendor is now in the end of the line.
- A '*' is now added as suffix of plugins' top level commands.
Signed-off-by: Ulysses Souza <ulysses.souza@docker.com>
This means that plugins can use whatever methods the monolithic CLI supports,
which is good for consistency.
This relies on `os.Args[0]` being something which can be executed again to
reach the same binary, since it is propagated (via an envvar) to the plugin for
this purpose. This essentially requires that the current working directory and
path are not modified by the monolithic CLI before it launches the plugin nor
by the plugin before it initializes the client. This should be the case.
Previously the fake apiclient used by `TestExperimentalCLI` was not being used,
since `cli.Initialize` was unconditionally overwriting it with a real one
(talking to a real daemon during unit testing, it seems). This wasn't expected
nor desirable and no longer happens with the new arrangements, exposing the
fact that no `pingFunc` is provided, leading to a panic. Add a `pingFunc` to
the fake client to avoid this.
Signed-off-by: Ian Campbell <ijc@docker.com>
They were listed twice in `docker --help` (but not `docker help`), since the
stubs were added in both `tryRunPluginHelp` and the `setHelpFunc` closure.
Calling `AddPluginStubCommands` earlier in `setHelpFunc` before the call to
`tryRunPluginHelp` is sufficient. Also it is no longer necessary to add just
valid plugins (`tryRunPluginHelp` handles invalid plugins correctly) so remove
that logic (which was in any case broken for e.g. `docker --help`).
Update the e2e test to check for duplicate entries and also to test `docker
--help` which was previously missed.
Signed-off-by: Ian Campbell <ijc@docker.com>
This allows passing argument to plugins, otherwise they are caught by the parse
loop, since cobra does not know about each plugin at this stage (to avoid
having to always scan for all plugins) this means that e.g. `docker plugin
--foo` would accumulate `plugin` as an arg to the `docker` command, then choke
on the unknown `--foo`.
This allows unknown global args only, unknown arguments on subcommands (e.g.
`docker ps --foo`) are still correctly caught.
Add an e2e test covering this case.
Signed-off-by: Ian Campbell <ijc@docker.com>
Previously a plugin which used these hooks would overwrite the top-level plugin
command's use of this hook, resulting in the dockerCli object not being fully
initialised.
Provide a function which plugins can use to chain to the required behaviour.
This required some fairly ugly arrangements to preserve state (which was
previously in-scope in `newPluginCOmmand`) to be used by the new function.
Signed-off-by: Ian Campbell <ijc@docker.com>
To achieve this we hook in at the beginning of our custom `HelpFunc` and detect
the plugin case by adding stub commands.
Signed-off-by: Ian Campbell <ijc@docker.com>
To do this we add a stub `cobra.Command` for each installed plugin (only when
invoking `help`, not for normal running).
This requires a function to list all available plugins so that is added here.
Signed-off-by: Ian Campbell <ijc@docker.com>
To help with this add a bad plugin which produces invalid metadata and arrange
for it to be built in the e2e container.
Signed-off-by: Ian Campbell <ijc@docker.com>
Add `--quiet` to the `docker image pull` subcommand that will not pull
the image quietly.
```
$ docker pull -q golang
Using default tag: latest
```
Signed-off-by: Vincent Demeester <vincent@sbr.pm>
PersistentPreRunE needs to be called within the help function to initialize all the flags (notably the orchestrator flag)
Add an e2e test as regression test
Signed-off-by: Silvin Lubecki <silvin.lubecki@docker.com>
- `make test-e2e` runs the e2e tests twice : once against on
non-experimental daemon (as before), once against an experimental
daemon.
- adds `test-e2e-experimental` and `test-e2e-non-experimental` target
to run tests for the specified cases
Signed-off-by: Vincent Demeester <vincent@sbr.pm>
* Renaming DOCKER_ORCHESTRATOR to DOCKER_STACK_ORCHESTRATOR
* Renaming config file option "orchestrator" to "stackOrchestrator"
* "--orchestrator" flag is no more global but local to stack command and subcommands
* Cleaning all global orchestrator code
* Replicating Hidden flags in help and Supported flags from root command to stack command
Signed-off-by: Silvin Lubecki <silvin.lubecki@docker.com>
- Build image that contains everything needed to run e2e tests
- Add ability to run e2e tests against an endpoint
Signed-off-by: Christopher Crone <christopher.crone@docker.com>
- More strict on orchestrator flag
- Make orchestrator flag more explicit as experimental
- Add experimentalCLI annotation on kubernetes flags
- Better kubeconfig error message
- Prefix service name with stackname in ps and services stack subcommands
- Fix yaml documentation
- Fix code coverage ignoring generated code
Signed-off-by: Silvin Lubecki <silvin.lubecki@docker.com>
- Add support for kubernetes for docker stack command
- Update to go 1.9
- Add kubernetes to vendors
- Print orchestrator in docker version command
Signed-off-by: Vincent Demeester <vincent@sbr.pm>
Signed-off-by: Silvin Lubecki <silvin.lubecki@docker.com>
Allow to mark some commands and flags experimental on cli (i.e. not
depending to the state of the daemon). This will allow more flexibility
on experimentation with the cli.
Marking `docker trust` as cli experimental as it is documented so.
Signed-off-by: Vincent Demeester <vincent@sbr.pm>
Also add TEST_DEBUG env variable for debugging E2E tests.
And change icmd environment helpers to fit the CmdOp interface os they
can be passed to 'icmd.RunCmd()'
Signed-off-by: Daniel Nephin <dnephin@docker.com>
Signed-off-by: French Ben <frenchben@docker.com>
Update for the test to capture the proper removal
Signed-off-by: French Ben <frenchben@docker.com>
Satisfy lint length limit
Signed-off-by: French Ben <frenchben@docker.com>
Updated e2e test
Signed-off-by: French Ben <frenchben@docker.com>