Make daemon events listen for plugin lifecycle events.
Signed-off-by: Anusha Ragunathan <anusha@docker.com>
(cherry picked from commit 42abccb841
)
Signed-off-by: Tibor Vass <tibor@docker.com>
This commit is contained in:
parent
49d9a425d5
commit
4d529895f0
13 changed files with 167 additions and 106 deletions
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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)
|
||||
}
|
|
@ -606,6 +606,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
|
||||
}
|
||||
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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() {
|
||||
}
|
||||
|
|
|
@ -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{
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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=<name or id>`)
|
||||
* event (`event=<event action>`)
|
||||
* image (`image=<tag or id>`)
|
||||
* plugin (experimental) (`plugin=<name or id>`)
|
||||
* label (`label=<key>` or `label=<key>=<value>`)
|
||||
* type (`type=<container or image or volume or network or daemon>`)
|
||||
* volume (`volume=<name or id>`)
|
||||
|
@ -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)
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue