diff --git a/cmd/dockerd/daemon.go b/cmd/dockerd/daemon.go index e7f24ed976..0d3cace22a 100644 --- a/cmd/dockerd/daemon.go +++ b/cmd/dockerd/daemon.go @@ -262,10 +262,6 @@ func (cli *DaemonCli) start() (err error) { <-stopc // wait for daemonCli.start() to return }) - if err := pluginInit(cli.Config, containerdRemote, registryService); err != nil { - return err - } - d, err := daemon.NewDaemon(cli.Config, registryService, containerdRemote) if err != nil { return fmt.Errorf("Error starting daemon: %v", err) diff --git a/cmd/dockerd/daemon_no_plugin_support.go b/cmd/dockerd/daemon_no_plugin_support.go deleted file mode 100644 index 17f249190d..0000000000 --- a/cmd/dockerd/daemon_no_plugin_support.go +++ /dev/null @@ -1,13 +0,0 @@ -// +build !experimental !linux - -package main - -import ( - "github.com/docker/docker/daemon" - "github.com/docker/docker/libcontainerd" - "github.com/docker/docker/registry" -) - -func pluginInit(config *daemon.Config, remote libcontainerd.Remote, rs registry.Service) error { - return nil -} diff --git a/cmd/dockerd/daemon_plugin_support.go b/cmd/dockerd/daemon_plugin_support.go deleted file mode 100644 index de1bf1263d..0000000000 --- a/cmd/dockerd/daemon_plugin_support.go +++ /dev/null @@ -1,14 +0,0 @@ -// +build linux,experimental - -package main - -import ( - "github.com/docker/docker/daemon" - "github.com/docker/docker/libcontainerd" - "github.com/docker/docker/plugin" - "github.com/docker/docker/registry" -) - -func pluginInit(config *daemon.Config, remote libcontainerd.Remote, rs registry.Service) error { - return plugin.Init(config.Root, remote, rs, config.LiveRestore) -} diff --git a/daemon/daemon.go b/daemon/daemon.go index ab7ed96d23..e44d985cf1 100644 --- a/daemon/daemon.go +++ b/daemon/daemon.go @@ -604,6 +604,10 @@ func NewDaemon(config *Config, registryService registry.Service, containerdRemot return nil, err } + if err := pluginInit(d, config, containerdRemote); err != nil { + return nil, err + } + return d, nil } diff --git a/daemon/daemon_experimental.go b/daemon/daemon_experimental.go index 5244f1df2f..cad706eb86 100644 --- a/daemon/daemon_experimental.go +++ b/daemon/daemon_experimental.go @@ -3,6 +3,7 @@ package daemon import ( + "github.com/docker/docker/libcontainerd" "github.com/docker/docker/plugin" "github.com/docker/engine-api/types/container" ) @@ -11,6 +12,15 @@ func (daemon *Daemon) verifyExperimentalContainerSettings(hostConfig *container. return nil, nil } -func pluginShutdown() { - plugin.GetManager().Shutdown() +func pluginInit(d *Daemon, cfg *Config, remote libcontainerd.Remote) error { + return plugin.Init(cfg.Root, remote, d.RegistryService, cfg.LiveRestore, d.LogPluginEvent) +} + +func pluginShutdown() { + manager := plugin.GetManager() + // Check for a valid manager object. In error conditions, daemon init can fail + // and shutdown called, before plugin manager is initialized. + if manager != nil { + manager.Shutdown() + } } diff --git a/daemon/daemon_stub.go b/daemon/daemon_stub.go index dd1fb09f1f..a5f534964d 100644 --- a/daemon/daemon_stub.go +++ b/daemon/daemon_stub.go @@ -2,11 +2,18 @@ package daemon -import "github.com/docker/engine-api/types/container" +import ( + "github.com/docker/docker/libcontainerd" + "github.com/docker/engine-api/types/container" +) func (daemon *Daemon) verifyExperimentalContainerSettings(hostConfig *container.HostConfig, config *container.Config) ([]string, error) { return nil, nil } +func pluginInit(d *Daemon, config *Config, remote libcontainerd.Remote) error { + return nil +} + func pluginShutdown() { } diff --git a/daemon/events.go b/daemon/events.go index 7fb8cd29ca..e01015777e 100644 --- a/daemon/events.go +++ b/daemon/events.go @@ -55,6 +55,21 @@ func (daemon *Daemon) LogImageEventWithAttributes(imageID, refName, action strin daemon.EventsService.Log(action, events.ImageEventType, actor) } +// LogPluginEvent generates an event related to a plugin with only the default attributes. +func (daemon *Daemon) LogPluginEvent(pluginID, refName, action string) { + daemon.LogPluginEventWithAttributes(pluginID, refName, action, map[string]string{}) +} + +// LogPluginEventWithAttributes generates an event related to a plugin with specific given attributes. +func (daemon *Daemon) LogPluginEventWithAttributes(pluginID, refName, action string, attributes map[string]string) { + attributes["name"] = refName + actor := events.Actor{ + ID: pluginID, + Attributes: attributes, + } + daemon.EventsService.Log(action, events.PluginEventType, actor) +} + // LogVolumeEvent generates an event related to a volume. func (daemon *Daemon) LogVolumeEvent(volumeID, action string, attributes map[string]string) { actor := events.Actor{ diff --git a/daemon/events/filter.go b/daemon/events/filter.go index b38c034c9f..525431c915 100644 --- a/daemon/events/filter.go +++ b/daemon/events/filter.go @@ -22,6 +22,7 @@ func (ef *Filter) Include(ev events.Message) bool { ef.filter.ExactMatch("type", ev.Type) && ef.matchDaemon(ev) && ef.matchContainer(ev) && + ef.matchPlugin(ev) && ef.matchVolume(ev) && ef.matchNetwork(ev) && ef.matchImage(ev) && @@ -43,6 +44,10 @@ func (ef *Filter) matchContainer(ev events.Message) bool { return ef.fuzzyMatchName(ev, events.ContainerEventType) } +func (ef *Filter) matchPlugin(ev events.Message) bool { + return ef.fuzzyMatchName(ev, events.PluginEventType) +} + func (ef *Filter) matchVolume(ev events.Message) bool { return ef.fuzzyMatchName(ev, events.VolumeEventType) } diff --git a/docs/reference/commandline/events.md b/docs/reference/commandline/events.md index c966289d59..18b92fccb4 100644 --- a/docs/reference/commandline/events.md +++ b/docs/reference/commandline/events.md @@ -30,6 +30,10 @@ Docker images report the following events: delete, import, load, pull, push, save, tag, untag +Docker plugins(experimental) report the following events: + + install, enable, disable, remove + Docker volumes report the following events: create, mount, unmount, destroy @@ -74,6 +78,7 @@ The currently supported filters are: * container (`container=`) * event (`event=`) * image (`image=`) +* plugin (experimental) (`plugin=`) * label (`label=` or `label==`) * type (`type=`) * volume (`volume=`) @@ -171,3 +176,7 @@ relative to the current time on the client machine: $ docker events --filter 'type=network' 2015-12-23T21:38:24.705709133Z network create 8b111217944ba0ba844a65b13efcd57dc494932ee2527577758f939315ba2c5b (name=test-event-network-local, type=bridge) 2015-12-23T21:38:25.119625123Z network connect 8b111217944ba0ba844a65b13efcd57dc494932ee2527577758f939315ba2c5b (name=test-event-network-local, container=b4be644031a3d90b400f88ab3d4bdf4dc23adb250e696b6328b85441abe2c54e, type=bridge) + + $ docker events --filter 'type=plugin' (experimental) + 2016-07-25T17:30:14.825557616Z plugin pull ec7b87f2ce84330fe076e666f17dfc049d2d7ae0b8190763de94e1f2d105993f (name=tiborvass/no-remove:latest) + 2016-07-25T17:30:14.888127370Z plugin enable ec7b87f2ce84330fe076e666f17dfc049d2d7ae0b8190763de94e1f2d105993f (name=tiborvass/no-remove:latest) diff --git a/integration-cli/docker_cli_events_test.go b/integration-cli/docker_cli_events_test.go index 801e2d01b6..260228f2cc 100644 --- a/integration-cli/docker_cli_events_test.go +++ b/integration-cli/docker_cli_events_test.go @@ -297,6 +297,32 @@ func (s *DockerSuite) TestEventsImageLoad(c *check.C) { c.Assert(matches["action"], checker.Equals, "save", check.Commentf("matches: %v\nout:\n%s\n", matches, out)) } +func (s *DockerSuite) TestEventsPluginOps(c *check.C) { + testRequires(c, DaemonIsLinux, ExperimentalDaemon) + + pluginName := "tiborvass/no-remove:latest" + since := daemonUnixTime(c) + + dockerCmd(c, "plugin", "install", pluginName, "--grant-all-permissions") + dockerCmd(c, "plugin", "disable", pluginName) + dockerCmd(c, "plugin", "remove", pluginName) + + out, _ := dockerCmd(c, "events", "--since", since, "--until", daemonUnixTime(c)) + events := strings.Split(out, "\n") + events = events[:len(events)-1] + + nEvents := len(events) + c.Assert(nEvents, checker.GreaterOrEqualThan, 4) + + pluginEvents := eventActionsByIDAndType(c, events, pluginName, "plugin") + c.Assert(pluginEvents, checker.HasLen, 4, check.Commentf("events: %v", events)) + + c.Assert(pluginEvents[0], checker.Equals, "pull", check.Commentf(out)) + c.Assert(pluginEvents[1], checker.Equals, "enable", check.Commentf(out)) + c.Assert(pluginEvents[2], checker.Equals, "disable", check.Commentf(out)) + c.Assert(pluginEvents[3], checker.Equals, "remove", check.Commentf(out)) +} + func (s *DockerSuite) TestEventsFilters(c *check.C) { since := daemonUnixTime(c) dockerCmd(c, "run", "--rm", "busybox", "true") diff --git a/plugin/backend.go b/plugin/backend.go index ada623950b..ca31620602 100644 --- a/plugin/backend.go +++ b/plugin/backend.go @@ -22,7 +22,11 @@ func (pm *Manager) Disable(name string) error { if err != nil { return err } - return pm.disable(p) + if err := pm.disable(p); err != nil { + return err + } + pm.pluginEventLogger(p.PluginObj.ID, name, "disable") + return nil } // Enable activates a plugin, which implies that they are ready to be used by containers. @@ -31,7 +35,11 @@ func (pm *Manager) Enable(name string) error { if err != nil { return err } - return pm.enable(p) + if err := pm.enable(p); err != nil { + return err + } + pm.pluginEventLogger(p.PluginObj.ID, name, "enable") + return nil } // Inspect examines a plugin manifest @@ -40,10 +48,10 @@ func (pm *Manager) Inspect(name string) (tp types.Plugin, err error) { if err != nil { return tp, err } - return p.P, nil + return p.PluginObj, nil } -// Pull pulls a plugin and enables it. +// Pull pulls a plugin and computes the privileges required to install it. func (pm *Manager) Pull(name string, metaHeader http.Header, authConfig *types.AuthConfig) (types.PluginPrivileges, error) { ref, err := reference.ParseNamed(name) if err != nil { @@ -86,14 +94,15 @@ func (pm *Manager) Pull(name string, metaHeader http.Header, authConfig *types.A pm.save() pm.Unlock() - return computePrivileges(&p.P.Manifest), nil + pm.pluginEventLogger(pluginID, name, "pull") + return computePrivileges(&p.PluginObj.Manifest), nil } // List displays the list of plugins and associated metadata. func (pm *Manager) List() ([]types.Plugin, error) { out := make([]types.Plugin, 0, len(pm.plugins)) for _, p := range pm.plugins { - out = append(out, p.P) + out = append(out, p.PluginObj) } return out, nil } @@ -104,7 +113,7 @@ func (pm *Manager) Push(name string, metaHeader http.Header, authConfig *types.A if err != nil { return err } - dest := filepath.Join(pm.libRoot, p.P.ID) + dest := filepath.Join(pm.libRoot, p.PluginObj.ID) config, err := os.Open(filepath.Join(dest, "manifest.json")) if err != nil { return err @@ -127,7 +136,11 @@ func (pm *Manager) Remove(name string) error { if err != nil { return err } - return pm.remove(p) + if err := pm.remove(p); err != nil { + return err + } + pm.pluginEventLogger(p.PluginObj.ID, name, "remove") + return nil } // Set sets plugin args diff --git a/plugin/manager.go b/plugin/manager.go index faed7185e7..6f0bf57788 100644 --- a/plugin/manager.go +++ b/plugin/manager.go @@ -43,7 +43,7 @@ func (e ErrInadequateCapability) Error() string { type plugin struct { //sync.RWMutex TODO - P types.Plugin `json:"plugin"` + PluginObj types.Plugin `json:"plugin"` client *plugins.Client restartManager restartmanager.RestartManager runtimeSourcePath string @@ -60,51 +60,53 @@ func (p *plugin) IsLegacy() bool { } func (p *plugin) Name() string { - name := p.P.Name - if len(p.P.Tag) > 0 { + name := p.PluginObj.Name + if len(p.PluginObj.Tag) > 0 { // TODO: this feels hacky, maybe we should be storing the distribution reference rather than splitting these - name += ":" + p.P.Tag + name += ":" + p.PluginObj.Tag } return name } func (pm *Manager) newPlugin(ref reference.Named, id string) *plugin { p := &plugin{ - P: types.Plugin{ + PluginObj: types.Plugin{ Name: ref.Name(), ID: id, }, runtimeSourcePath: filepath.Join(pm.runRoot, id), } if ref, ok := ref.(reference.NamedTagged); ok { - p.P.Tag = ref.Tag() + p.PluginObj.Tag = ref.Tag() } return p } func (pm *Manager) restorePlugin(p *plugin) error { - p.runtimeSourcePath = filepath.Join(pm.runRoot, p.P.ID) - if p.P.Active { + p.runtimeSourcePath = filepath.Join(pm.runRoot, p.PluginObj.ID) + if p.PluginObj.Active { return pm.restore(p) } return nil } type pluginMap map[string]*plugin +type eventLogger func(id, name, action string) // Manager controls the plugin subsystem. type Manager struct { sync.RWMutex - libRoot string - runRoot string - plugins pluginMap // TODO: figure out why save() doesn't json encode *plugin object - nameToID map[string]string - handlers map[string]func(string, *plugins.Client) - containerdClient libcontainerd.Client - registryService registry.Service - handleLegacy bool - liveRestore bool - shutdown bool + libRoot string + runRoot string + plugins pluginMap // TODO: figure out why save() doesn't json encode *plugin object + nameToID map[string]string + handlers map[string]func(string, *plugins.Client) + containerdClient libcontainerd.Client + registryService registry.Service + handleLegacy bool + liveRestore bool + shutdown bool + pluginEventLogger eventLogger } // GetManager returns the singleton plugin Manager @@ -114,21 +116,22 @@ func GetManager() *Manager { // Init (was NewManager) instantiates the singleton Manager. // TODO: revert this to NewManager once we get rid of all the singletons. -func Init(root string, remote libcontainerd.Remote, rs registry.Service, liveRestore bool) (err error) { +func Init(root string, remote libcontainerd.Remote, rs registry.Service, liveRestore bool, evL eventLogger) (err error) { if manager != nil { return nil } root = filepath.Join(root, "plugins") manager = &Manager{ - libRoot: root, - runRoot: "/run/docker", - plugins: make(map[string]*plugin), - nameToID: make(map[string]string), - handlers: make(map[string]func(string, *plugins.Client)), - registryService: rs, - handleLegacy: true, - liveRestore: liveRestore, + libRoot: root, + runRoot: "/run/docker", + plugins: make(map[string]*plugin), + nameToID: make(map[string]string), + handlers: make(map[string]func(string, *plugins.Client)), + registryService: rs, + handleLegacy: true, + liveRestore: liveRestore, + pluginEventLogger: evL, } if err := os.MkdirAll(manager.runRoot, 0700); err != nil { return err @@ -180,7 +183,7 @@ func FindWithCapability(capability string) ([]Plugin, error) { defer manager.RUnlock() pluginLoop: for _, p := range manager.plugins { - for _, typ := range p.P.Manifest.Interface.Types { + for _, typ := range p.PluginObj.Manifest.Interface.Types { if typ.Capability != capability || typ.Prefix != "docker" { continue pluginLoop } @@ -242,7 +245,7 @@ func LookupWithCapability(name, capability string) (Plugin, error) { } capability = strings.ToLower(capability) - for _, typ := range p.P.Manifest.Interface.Types { + for _, typ := range p.PluginObj.Manifest.Interface.Types { if typ.Capability == capability && typ.Prefix == "docker" { return p, nil } @@ -312,8 +315,8 @@ func (pm *Manager) init() error { } pm.Lock() - pm.nameToID[p.Name()] = p.P.ID - requiresManualRestore := !pm.liveRestore && p.P.Active + pm.nameToID[p.Name()] = p.PluginObj.ID + requiresManualRestore := !pm.liveRestore && p.PluginObj.Active pm.Unlock() if requiresManualRestore { @@ -329,44 +332,44 @@ func (pm *Manager) init() error { } func (pm *Manager) initPlugin(p *plugin) error { - dt, err := os.Open(filepath.Join(pm.libRoot, p.P.ID, "manifest.json")) + dt, err := os.Open(filepath.Join(pm.libRoot, p.PluginObj.ID, "manifest.json")) if err != nil { return err } - err = json.NewDecoder(dt).Decode(&p.P.Manifest) + err = json.NewDecoder(dt).Decode(&p.PluginObj.Manifest) dt.Close() if err != nil { return err } - p.P.Config.Mounts = make([]types.PluginMount, len(p.P.Manifest.Mounts)) - for i, mount := range p.P.Manifest.Mounts { - p.P.Config.Mounts[i] = mount + p.PluginObj.Config.Mounts = make([]types.PluginMount, len(p.PluginObj.Manifest.Mounts)) + for i, mount := range p.PluginObj.Manifest.Mounts { + p.PluginObj.Config.Mounts[i] = mount } - p.P.Config.Env = make([]string, 0, len(p.P.Manifest.Env)) - for _, env := range p.P.Manifest.Env { + p.PluginObj.Config.Env = make([]string, 0, len(p.PluginObj.Manifest.Env)) + for _, env := range p.PluginObj.Manifest.Env { if env.Value != nil { - p.P.Config.Env = append(p.P.Config.Env, fmt.Sprintf("%s=%s", env.Name, *env.Value)) + p.PluginObj.Config.Env = append(p.PluginObj.Config.Env, fmt.Sprintf("%s=%s", env.Name, *env.Value)) } } - copy(p.P.Config.Args, p.P.Manifest.Args.Value) + copy(p.PluginObj.Config.Args, p.PluginObj.Manifest.Args.Value) - f, err := os.Create(filepath.Join(pm.libRoot, p.P.ID, "plugin-config.json")) + f, err := os.Create(filepath.Join(pm.libRoot, p.PluginObj.ID, "plugin-config.json")) if err != nil { return err } - err = json.NewEncoder(f).Encode(&p.P.Config) + err = json.NewEncoder(f).Encode(&p.PluginObj.Config) f.Close() return err } func (pm *Manager) remove(p *plugin) error { - if p.P.Active { + if p.PluginObj.Active { return fmt.Errorf("plugin %s is active", p.Name()) } pm.Lock() // fixme: lock single record defer pm.Unlock() - delete(pm.plugins, p.P.ID) + delete(pm.plugins, p.PluginObj.ID) delete(pm.nameToID, p.Name()) pm.save() return nil diff --git a/plugin/manager_linux.go b/plugin/manager_linux.go index b50415b124..b247aae912 100644 --- a/plugin/manager_linux.go +++ b/plugin/manager_linux.go @@ -21,7 +21,7 @@ import ( ) func (pm *Manager) enable(p *plugin) error { - if p.P.Active { + if p.PluginObj.Active { return fmt.Errorf("plugin %s is already enabled", p.Name()) } spec, err := pm.initSpec(p) @@ -30,14 +30,14 @@ func (pm *Manager) enable(p *plugin) error { } p.restartManager = restartmanager.New(container.RestartPolicy{Name: "always"}, 0) - if err := pm.containerdClient.Create(p.P.ID, libcontainerd.Spec(*spec), libcontainerd.WithRestartManager(p.restartManager)); err != nil { // POC-only + if err := pm.containerdClient.Create(p.PluginObj.ID, libcontainerd.Spec(*spec), libcontainerd.WithRestartManager(p.restartManager)); err != nil { // POC-only if err := p.restartManager.Cancel(); err != nil { logrus.Errorf("enable: restartManager.Cancel failed due to %v", err) } return err } - socket := p.P.Manifest.Interface.Socket + socket := p.PluginObj.Manifest.Interface.Socket p.client, err = plugins.NewClient("unix://"+filepath.Join(p.runtimeSourcePath, socket), nil) if err != nil { if err := p.restartManager.Cancel(); err != nil { @@ -47,11 +47,11 @@ func (pm *Manager) enable(p *plugin) error { } pm.Lock() // fixme: lock single record - p.P.Active = true + p.PluginObj.Active = true pm.save() pm.Unlock() - for _, typ := range p.P.Manifest.Interface.Types { + for _, typ := range p.PluginObj.Manifest.Interface.Types { if handler := pm.handlers[typ.String()]; handler != nil { handler(p.Name(), p.Client()) } @@ -62,19 +62,19 @@ func (pm *Manager) enable(p *plugin) error { func (pm *Manager) restore(p *plugin) error { p.restartManager = restartmanager.New(container.RestartPolicy{Name: "always"}, 0) - return pm.containerdClient.Restore(p.P.ID, libcontainerd.WithRestartManager(p.restartManager)) + return pm.containerdClient.Restore(p.PluginObj.ID, libcontainerd.WithRestartManager(p.restartManager)) } func (pm *Manager) initSpec(p *plugin) (*specs.Spec, error) { s := oci.DefaultSpec() - rootfs := filepath.Join(pm.libRoot, p.P.ID, "rootfs") + rootfs := filepath.Join(pm.libRoot, p.PluginObj.ID, "rootfs") s.Root = specs.Root{ Path: rootfs, Readonly: false, // TODO: all plugins should be readonly? settable in manifest? } - mounts := append(p.P.Config.Mounts, types.PluginMount{ + mounts := append(p.PluginObj.Config.Mounts, types.PluginMount{ Source: &p.runtimeSourcePath, Destination: defaultPluginRuntimeDestination, Type: "bind", @@ -104,12 +104,12 @@ func (pm *Manager) initSpec(p *plugin) (*specs.Spec, error) { s.Mounts = append(s.Mounts, m) } - envs := make([]string, 1, len(p.P.Config.Env)+1) + envs := make([]string, 1, len(p.PluginObj.Config.Env)+1) envs[0] = "PATH=" + system.DefaultPathEnv - envs = append(envs, p.P.Config.Env...) + envs = append(envs, p.PluginObj.Config.Env...) - args := append(p.P.Manifest.Entrypoint, p.P.Config.Args...) - cwd := p.P.Manifest.Workdir + args := append(p.PluginObj.Manifest.Entrypoint, p.PluginObj.Config.Args...) + cwd := p.PluginObj.Manifest.Workdir if len(cwd) == 0 { cwd = "/" } @@ -124,19 +124,19 @@ func (pm *Manager) initSpec(p *plugin) (*specs.Spec, error) { } func (pm *Manager) disable(p *plugin) error { - if !p.P.Active { + if !p.PluginObj.Active { return fmt.Errorf("plugin %s is already disabled", p.Name()) } if err := p.restartManager.Cancel(); err != nil { logrus.Error(err) } - if err := pm.containerdClient.Signal(p.P.ID, int(syscall.SIGKILL)); err != nil { + if err := pm.containerdClient.Signal(p.PluginObj.ID, int(syscall.SIGKILL)); err != nil { logrus.Error(err) } os.RemoveAll(p.runtimeSourcePath) pm.Lock() // fixme: lock single record defer pm.Unlock() - p.P.Active = false + p.PluginObj.Active = false pm.save() return nil } @@ -148,7 +148,7 @@ func (pm *Manager) Shutdown() { pm.shutdown = true for _, p := range pm.plugins { - if pm.liveRestore && p.P.Active { + if pm.liveRestore && p.PluginObj.Active { logrus.Debug("Plugin active when liveRestore is set, skipping shutdown") continue } @@ -157,9 +157,9 @@ func (pm *Manager) Shutdown() { logrus.Error(err) } } - if pm.containerdClient != nil && p.P.Active { + if pm.containerdClient != nil && p.PluginObj.Active { p.exitChan = make(chan bool) - err := pm.containerdClient.Signal(p.P.ID, int(syscall.SIGTERM)) + err := pm.containerdClient.Signal(p.PluginObj.ID, int(syscall.SIGTERM)) if err != nil { logrus.Errorf("Sending SIGTERM to plugin failed with error: %v", err) } else { @@ -168,14 +168,14 @@ func (pm *Manager) Shutdown() { logrus.Debug("Clean shutdown of plugin") case <-time.After(time.Second * 10): logrus.Debug("Force shutdown plugin") - if err := pm.containerdClient.Signal(p.P.ID, int(syscall.SIGKILL)); err != nil { + if err := pm.containerdClient.Signal(p.PluginObj.ID, int(syscall.SIGKILL)); err != nil { logrus.Errorf("Sending SIGKILL to plugin failed with error: %v", err) } } } close(p.exitChan) pm.Lock() - p.P.Active = false + p.PluginObj.Active = false pm.save() pm.Unlock() }