Currently the metrics plugin uses a really hackish host mount with
propagated mounts to get the metrics socket into a plugin after the
plugin is alreay running.
This approach ends up leaking mounts which requires setting the plugin
manager root to private, which causes some other issues.
With this change, plugin subsystems can register a set of modifiers to
apply to the plugin's runtime spec before the plugin is ever started.
This will help to generalize some of the customization work that needs
to happen for various plugin subsystems (and future ones).
Specifically it lets the metrics plugin subsystem append a mount to the
runtime spec to mount the metrics socket in the plugin's mount namespace
rather than the host's and prevetns any leaking due to this mount.
Signed-off-by: Brian Goff <cpuguy83@gmail.com>
During a plugin remove, docker performs an `os.Rename` to move the
plugin data dir to a new location before removing to acheive an atomic
removal.
`os.Rename` can return either a `NotExist` error if the source path
doesn't exist, or an `Exist` error if the target path already exists.
Both these cases can happen when there is an error on the final
`os.Remove` call, which is common on older kernels (`device or resource
busy`).
When calling rename, we can safely ignore these error types and proceed
to try and remove the plugin.
Signed-off-by: Brian Goff <cpuguy83@gmail.com>
Signed-off-by: John Howard <jhoward@microsoft.com>
The re-coalesces the daemon stores which were split as part of the
original LCOW implementation.
This is part of the work discussed in https://github.com/moby/moby/issues/34617,
in particular see the document linked to in that issue.
Instead of having to create a bunch of custom error types that are doing
nothing but wrapping another error in sub-packages, use a common helper
to create errors of the requested type.
e.g. instead of re-implementing this over and over:
```go
type notFoundError struct {
cause error
}
func(e notFoundError) Error() string {
return e.cause.Error()
}
func(e notFoundError) NotFound() {}
func(e notFoundError) Cause() error {
return e.cause
}
```
Packages can instead just do:
```
errdefs.NotFound(err)
```
Signed-off-by: Brian Goff <cpuguy83@gmail.com>
Files that are suffixed with `_linux.go` or `_windows.go` are
already only built on Linux / Windows, so these build-tags
were redundant.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Follow the conventions for namespace naming set out by other projects,
such as linuxkit and cri-containerd. Typically, they are some sort of
host name, with a subdomain describing functionality of the namespace.
In the case of linuxkit, services are launched in `services.linuxkit`.
In cri-containerd, pods are launched in `k8s.io`, making it clear that
these are from kubernetes.
Signed-off-by: Stephen J Day <stephen.day@docker.com>
Ensures that when a plugin is removed that it doesn't interfere with
other plugins mounts and also ensures its own mounts are cleaned up.
Signed-off-by: Brian Goff <cpuguy83@gmail.com>
Plugin config can have Mounts without a 'Source' field. In such cases,
performing a 'plugin set' on the mount source will panic the daemon. Its
the same case for device paths as well. This detects the case and
returns error.
Signed-off-by: Anusha Ragunathan <anusha.ragunathan@docker.com>
Instead of duplicating the same if condition per plugin manager directory,
use one if condition and a for-loop.
Signed-off-by: Boaz Shuster <ripcurld.github@gmail.com>
In some circumstances we were not properly releasing plugin references,
leading to failures in removing a plugin with no way to recover other
than restarting the daemon.
1. If volume create fails (in the driver)
2. If a driver validation fails (should be rare)
3. If trying to get a plugin that does not match the passed in capability
Ideally the test for 1 and 2 would just be a unit test, however the
plugin interfaces are too complicated as `plugingetter` relies on
github.com/pkg/plugin/Client (a concrete type), which will require
spinning up services from within the unit test... it just wouldn't be a
unit test at this point.
I attempted to refactor this a bit, but since both libnetwork and
swarmkit are reliant on `plugingetter` as well, this would not work.
This really requires a re-write of the lower-level plugin management to
decouple these pieces.
Signed-off-by: Brian Goff <cpuguy83@gmail.com>
Signed-off-by: John Howard <jhoward@microsoft.com>
This PR has the API changes described in https://github.com/moby/moby/issues/34617.
Specifically, it adds an HTTP header "X-Requested-Platform" which is a JSON-encoded
OCI Image-spec `Platform` structure.
In addition, it renames (almost all) uses of a string variable platform (and associated)
methods/functions to os. This makes it much clearer to disambiguate with the swarm
"platform" which is really os/arch. This is a stepping stone to getting the daemon towards
fully multi-platform/arch-aware, and makes it clear when "operating system" is being
referred to rather than "platform" which is misleadingly used - sometimes in the swarm
meaning, but more often as just the operating system.
The `filters.Include()` method was deprecated in favor of `filters.Contains()`
in 065118390a, but still used in various
locations.
This patch replaces uses of `filters.Include()` with `filters.Contains()`.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
libcontainerd has a bunch of platform dependent code and huge interfaces
that are a pain implement.
To make the plugin manager a bit easier to work with, extract the plugin
executor into an interface and move the containerd implementation to a
separate package.
Signed-off-by: Brian Goff <cpuguy83@gmail.com>
This enables docker cp and ADD/COPY docker build support for LCOW.
Originally, the graphdriver.Get() interface returned a local path
to the container root filesystem. This does not work for LCOW, so
the Get() method now returns an interface that LCOW implements to
support copying to and from the container.
Signed-off-by: Akash Gupta <akagup@microsoft.com>
This also update:
- runc to 3f2f8b84a77f73d38244dd690525642a72156c64
- runtime-specs to v1.0.0
Signed-off-by: Kenfe-Mickael Laventure <mickael.laventure@gmail.com>
Use strongly typed errors to set HTTP status codes.
Error interfaces are defined in the api/errors package and errors
returned from controllers are checked against these interfaces.
Errors can be wraeped in a pkg/errors.Causer, as long as somewhere in the
line of causes one of the interfaces is implemented. The special error
interfaces take precedence over Causer, meaning if both Causer and one
of the new error interfaces are implemented, the Causer is not
traversed.
Signed-off-by: Brian Goff <cpuguy83@gmail.com>
This prevents mounts in the plugins dir from leaking into other
namespaces which can prevent removal (`device or resource busy`),
particularly on older kernels.
Signed-off-by: Brian Goff <cpuguy83@gmail.com>
Changes most references of syscall to golang.org/x/sys/
Ones aren't changes include, Errno, Signal and SysProcAttr
as they haven't been implemented in /x/sys/.
Signed-off-by: Christopher Jones <tophj@linux.vnet.ibm.com>
[s390x] switch utsname from unsigned to signed
per 33267e036f
char in s390x in the /x/sys/unix package is now signed, so
change the buildtags
Signed-off-by: Christopher Jones <tophj@linux.vnet.ibm.com>
Enables other subsystems to watch actions for a plugin(s).
This will be used specifically for implementing plugins on swarm where a
swarm controller needs to watch the state of a plugin.
Signed-off-by: Brian Goff <cpuguy83@gmail.com>
Before this patch, if the plugin's `config.json` is successfully removed
but the main plugin state dir could not be removed for some reason (e.g.
leaked mount), it will prevent the daemon from being able to be
restarted.
This patches changes this to atomically remove the plugin such that on
daemon restart we can detect that there was an error and re-try. It also
changes the logic so that it only logs errors on restore rather than
erroring out the daemon.
This also removes some code which is now duplicated elsewhere.
Signed-off-by: Brian Goff <cpuguy83@gmail.com>
Also, this removes the use of a questionable golang range feature which
corrects for mutation of a slice during iteration over that slice. This
makes the filter operation easier to read and reason about.
Signed-off-by: David Sheets <dsheets@docker.com>
Previously, a 'plugin not found' error would be returned if a plugin to be
retrieved was found but disabled. This was misleading and incorrect. Now,
a new error plugin.ErrDisabled is returned in this case. This makes the
error message when trying to statically start plugins (from daemon.json or
dockerd command line) accurate.
Signed-off-by: David Sheets <dsheets@docker.com>
Increases the test coverage of pkg/plugins.
Changed signature of function NewClientWithTimeout in pkg/plugin/client, to
take time.Duration instead of integers.
Signed-off-by: Raja Sami <raja.sami@tenpearl.com>
This was mistakenly unmounting everything under `plugins/*` instead of
just `plugins/<id>/*` anytime a plugin is removed.
Signed-off-by: Brian Goff <cpuguy83@gmail.com>
In some cases, if a user specifies `-f` when disabling a plugin mounts
can still exist on the plugin rootfs.
This can cause problems during upgrade where the rootfs is removed and
may cause data loss.
To resolve this, ensure the rootfs is unmounted
before performing an upgrade.
Signed-off-by: Brian Goff <cpuguy83@gmail.com>
While restoring plugins during daemon restart, some plugins can fail to
respond to net.Dial. These plugins should be explicitly set to disabled,
else they will retain their original state of enabled, which is
incorrect.
Tested with a plugin that fails to restart and observed that the state
was set to disabled.
Signed-off-by: Anusha Ragunathan <anusha.ragunathan@docker.com>
When the daemon is configured to run with an authorization-plugin and if
the plugin is disabled, the daemon continues to send API requests to the
plugin and expect it to respond. But the plugin has been disabled. As a
result, all API requests are blocked. Fix this behavior by removing the
disabled plugin from the authz middleware chain.
Tested using riyaz/authz-no-volume-plugin and observed that after
disabling the plugin, API request/response is functional.
Fixes#31836
Signed-off-by: Anusha Ragunathan <anusha.ragunathan@docker.com>
Embedding DockerVersion in plugin config when the plugin is created,
enables users to do a docker plugin inspect and know which version
the plugin was built on. This is helpful in cases where users are
running a new plugin on older docker releases and confused at
unexpected behavior.
By embedding DockerVersion in the config, we claim that there's no
guarantee that if the plugin config's DockerVersion is greater that
the version of the docker engine the plugin is executed against, the
plugin will work as expected.
For example, lets say:
- in 17.03, a plugin was released as johndoe/foo:v1
- in 17.05, the plugin uses the new ipchost config setting and author
publishes johndoe/foo:v2
In this case, johndoe/foo:v2 was built on 17.05 using ipchost, but is
running on docker-engine version 17.03. Since 17.05 > 17.03, there's
no guarantee that the plugin will work as expected. Ofcourse, if the
plugin did not use newly added config settings (ipchost in this case)
in 17.05, it would work fine in 17.03.
Signed-off-by: Anusha Ragunathan <anusha.ragunathan@docker.com>
Tested using global-net-plugin-ipc which sets PidHost in config.json.
Plugins might need access to host pid namespace. Add support for that.
Tested using aragunathan/global-net-plugin-ipc which sets "pidhost" in
config.json. Observed using `readlink /proc/self/ns/pid` that plugin and
host have the same ns.
Signed-off-by: Anusha Ragunathan <anusha.ragunathan@docker.com>
Plugins might need access to host ipc namespace. A good usecase is
a volume plugin running iscsi multipath commands that need access to
host kernel locks.
Tested with a custom plugin (aragunathan/global-net-plugin-full) that's
built with `"ipchost" : true` in config.json. Observed using
`readlink /proc/self/ns/ipc` that plugin and host have the same ns.
Signed-off-by: Anusha Ragunathan <anusha.ragunathan@docker.com>
TestPluginTrustedInstall revealed a race in the plugin shutdown logic,
where the exit channel signal was sent even before the propagated mounts
were unmounted. If the same plugin was enabled, it would try to setup
propagated mounts *before* it was unmounted resulting in errors.
This change fixes the behavior by waiting until the unmount completes on
disable before marking the plugin as disabled.
Signed-off-by: Anusha Ragunathan <anusha.ragunathan@docker.com>
When a plugin fails to start, we still incorrectly mark it as enabled.
This change verifies that we can dial to the plugin socket to confirm that
the plugin is functional and only then mark the plugin as enabled. Also,
dont delete the plugin on install, if only the enable fails.
Signed-off-by: Anusha Ragunathan <anusha.ragunathan@docker.com>
Remove forked reference package. Use normalized named values
everywhere and familiar functions to convert back to familiar
strings for UX and storage compatibility.
Enforce that the source repository in the distribution metadata
is always a normalized string, ignore invalid values which are not.
Update distribution tests to use normalized values.
Signed-off-by: Derek McGowan <derek@mcgstyle.net> (github: dmcgowan)
This persists the "propagated mount" for plugins outside the main
rootfs. This enables `docker plugin upgrade` to not remove potentially
important data during upgrade rather than forcing plugin authors to hard
code a host path to persist data to.
Also migrates old plugins that have a propagated mount which is in the
rootfs on daemon startup.
Signed-off-by: Brian Goff <cpuguy83@gmail.com>
This allows a plugin to be upgraded without requiring to
uninstall/reinstall a plugin.
Since plugin resources (e.g. volumes) are tied to a plugin ID, this is
important to ensure resources aren't lost.
The plugin must be disabled while upgrading (errors out if enabled).
This does not add any convenience flags for automatically
disabling/re-enabling the plugin during before/after upgrade.
Since an upgrade may change requested permissions, the user is required
to accept permissions just like `docker plugin install`.
Signed-off-by: Brian Goff <cpuguy83@gmail.com>
This fix adds `--filter capability=[volumedriver|authz]` to `docker plugin ls`.
The related docs has been updated.
An integration test has been added.
Signed-off-by: Yong Tang <yong.tang.github@outlook.com>
This fix adds `--filter enabled=true` to `docker plugin ls`,
as was specified in 28624.
The related API and docs has been updated.
An integration test has been added.
This fix fixes 28624.
Signed-off-by: Yong Tang <yong.tang.github@outlook.com>
Use resolving to repo info as the split point between the
legitimate reference package and forked reference package.
Signed-off-by: Derek McGowan <derek@mcgstyle.net> (github: dmcgowan)
The `digest` data type, used throughout docker for image verification
and identity, has been broken out into `opencontainers/go-digest`. This
PR updates the dependencies and moves uses over to the new type.
Signed-off-by: Stephen J Day <stephen.day@docker.com>
Go style calls for mixed caps instead of all caps:
https://golang.org/doc/effective_go.html#mixed-caps
Change LOOKUP, ACQUIRE, and RELEASE to Lookup, Acquire, and Release.
This vendors a fork of libnetwork for now, to deal with a cyclic
dependency issue. The change will be upstream to libnetwork once this is
merged.
Signed-off-by: Aaron Lehmann <aaron.lehmann@docker.com>
Move plugins to shared distribution stack with images.
Create immutable plugin config that matches schema2 requirements.
Ensure data being pushed is same as pulled/created.
Store distribution artifacts in a blobstore.
Run init layer setup for every plugin start.
Fix breakouts from unsafe file accesses.
Add support for `docker plugin install --alias`
Uses normalized references for default names to avoid collisions when using default hosts/tags.
Some refactoring of the plugin manager to support the change, like removing the singleton manager and adding manager config struct.
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
Signed-off-by: Derek McGowan <derek@mcgstyle.net>
When plugins have a positive refcount, they were not allowed to be
removed. However, plugins could still be disabled when volumes
referenced it and containers using them were running.
This change fixes that by enforcing plugin refcount during disable.
A "force" disable option is also added to ignore reference refcounting.
Signed-off-by: Anusha Ragunathan <anusha@docker.com>
The current GetAll handles both V2 and legacy plugins. Also due to the
nature of V1 plugins, it also loads them. This causes problems when
loading is not required. Hence adding an independent API that will
return only the plugins that are loaded using v2 mangaed plugins.
Signed-off-by: Madhu Venugopal <madhu@docker.com>
This fix is a follow up for comment:
https://github.com/docker/docker/pull/29186/files#r91277345
While #29186 addresses the issue of `docker inspect <unknown object>`
on Windows, it actually makes `docker plugin inspect <unknown object>`
out `object not found` on Windows as well. This is actually misleading
as plugin is not supported on Windows.
This fix reverted the change in #29186 while at the same time,
checks `not supported` in `docker inspect <unknown object>` so that
- `docker plugin inspect <unknown object>` returns `not supported` on Windows
- `docker inspect <unknown object>` returns `not found` on Windows
This fix is related to #29186 and #29185.
Signed-off-by: Yong Tang <yong.tang.github@outlook.com>
Fixes a case where removing the plugin from disk would
fail silently. Also moves pluginStore remove after we
remove from disk, so 'docker plugin ls' doesn't isn't
empty in case it errors out.
Signed-off-by: Christopher Jones <tophj@linux.vnet.ibm.com>
Fixes an issue when starting the daemon with live-restore
where previously it was not set, plugins are not running.
Fixes an issue when starting the daemon with live-restore, the plugin
client (for interacting with the plugins HTTP interface) is not set,
causing a panic when the plugin is called.
Signed-off-by: Brian Goff <cpuguy83@gmail.com>
Adds 2 new methods to v2 plugin `Acquire` and `Release` which allow
refcounting directly at the plugin level instead of just the store.
Since a graphdriver is initialized exactly once, and is really managed
by a separate object, it didn't really seem right to call
`getter.Get()` to refcount graphdriver plugins.
On shutdown it was particularly weird where we'd either need to keep a
driver reference in daemon, or keep a reference to the pluggin getter in
the layer store, and even then still store extra details on if the
graphdriver is a plugin or not.
Instead the plugin proxy itself will handle calling the neccessary
refcounting methods directly on the plugin object.
Also adds a new interface in `plugingetter` to account for these new
functions which are not going to be implemented by v1 plugins.
Changes terms `plugingetter.CREATE` and `plugingetter.REMOVE` to
`ACQUIRE` and `RELEASE` respectively, which seems to be better
adjectives for what we're doing.
Signed-off-by: Brian Goff <cpuguy83@gmail.com>
Legacy plugins expect host-relative paths (such as for Volume.Mount).
However, a containerized plugin cannot respond with a host-relative
path. Therefore, this commit modifies new volume plugins' paths in Mount
and List to prepend the container's rootfs path.
This introduces a new PropagatedMount field in the Plugin Config.
When it is set for volume plugins, RootfsPropagation is set to rshared
and the path specified by PropagatedMount is bind-mounted with rshared
prior to launching the container. This is so that the daemon code can
access the paths returned by the plugin from the host mount namespace.
Signed-off-by: Tibor Vass <tibor@docker.com>
v2/Plugin struct had fields that were
- purely used by the manager.
- unsafely exposed without proper locking.
This change fixes this, by moving relevant fields to the manager as well
as making remaining fields as private and providing proper accessors for
them.
Signed-off-by: Anusha Ragunathan <anusha@docker.com>
This fix tries to address the issue raised on 29185 where
`docker inspect <unknown object>` on Windows will return:
```
Error response from daemon: plugins are not supported on this platform
```
The reason was that in case `--type` is not specified, `docker inspect`
will iterate through different types `container`, `image`, `network`,
`plugin` etc. The `plugin` object is the last type to check.
However, as `plugin` is not supported on Windows yet, the error message
is not very informative for `plugins are not supported on this platform`.
This fix tries to fix the issue by return a `not found` error on unsupported
platforms as well.
An integration test has been added to cover the changes for Windows/Linux.
This fix fixes 29185.
Signed-off-by: Yong Tang <yong.tang.github@outlook.com>
This fix tries to address the proposal raised in 28946
to support plugins in `docker inspect`.
The command `docker inspect` already supports
"container", "image", "node", "network", "service", "volume", "task".
However, `--type plugin` is not supported yet at the moment.
This fix address this issue by adding the support of `--type plugin`
for `docker inspect`.
An additional integration test has been added to cover the changes.
This fix fixes 28946.
Signed-off-by: Yong Tang <yong.tang.github@outlook.com>
This fix tries to address the issue raised in discussion of
PR 28735 where it was not possible to manage plugin based on
plugin ID. Previously it was not possible to invoke
`docker plugin inspect` with a plugin ID (or ID prefix).
This fix updates the implementation of `docker plugin inspect`
so that it is possbile to search based on a plugin name, or a
plugin ID. A short format of plugin ID (prefix) is also possible,
as long as there is no ambiguity.
Previously the check of `docker plugin inspect` was mostly done
on the client side. This could potentially cause inconsistency
between API and CMD. This fix move all the checks to daemon side
so that API and CMD will be consistent.
An integration test has been added to cover the changes.
Signed-off-by: Yong Tang <yong.tang.github@outlook.com>
This fix is a follow up to the comment:
https://github.com/docker/docker/pull/28717#discussion_r90040589
Currently, the collision checking is done at the last step `Add()` of
plugin creation. However, at this stage the context such as plugin
directories have already been creation. In case of name collision,
rollback is needed which could be expensive.
This fix performs the check at the beginning of CreateFromContext using
GetByName. In this way, collision fails fast and no context creation
or rollback is needed.
Signed-off-by: Yong Tang <yong.tang.github@outlook.com>
A plugin has an `ExitChan` channel which is used to signal the exit of
the plugin process. In a recent change, the initialization was
incorrectly moved to the daemon Shutdown path.
Fix this by initializing the channel during plugin enable.
Signed-off-by: Anusha Ragunathan <anusha@docker.com>
This fix tries to fix the issue raised in 28684:
1. Duplicate plugin create with the same name will override the old plugin reference
2. In case an error happens in the middle of the plugin creation, plugin directories
in `/var/lib/docker/plugins` are not cleaned up.
This fix update the plugin store so that `Add()` will return an error if a plugin
with the same name already exist.
This fix also will clean up the directory in `/var/lib/docker/plugins` in case
an error happens in the middle of the plugin creation.
This fix fixes 28684.
Signed-off-by: Yong Tang <yong.tang.github@outlook.com>
In the plugin manifest, Capabilities has been moved to
Linux.Capabilities to avoid confusion with Interface.Types[i].Capability
A DeviceCreation boolean has also been added to the manifest. This could
be changed in the future to be specific to a major number.
Signed-off-by: Tibor Vass <tibor@docker.com>
During error cases, we dont cleanup correctly. This commit takes care
of removing the plugin, if there are errors after the pull passed. It
also shuts down the plugin, if there are errors after the plugin in the
enable path.
Signed-off-by: Anusha Ragunathan <anusha@docker.com>