MM-8622: Improved plugin error reporting (#8737)

* allow `Wait()`ing on the supervisor

In the event the plugin supervisor shuts down a plugin for crashing too
many times, the new `Wait()` interface allows the `ActivatePlugin` to
accept a callback function to trigger when `supervisor.Wait()` returns.
If the supervisor shuts down normally, this callback is invoked with
a nil error, otherwise any error reported by the supervisor is passed
along.

* improve plugin activation/deactivation logic

Avoid triggering activation of previously failed-to-start plugins just
becase something in the configuration changed. Now, intelligently
compare the global enable bit as well as the each individual plugin's
enabled bit.

* expose store to manipulate PluginStatuses

* expose API to fetch plugin statuses

* keep track of whether or not plugin sandboxing is supported

* transition plugin statuses

* restore error on plugin activation if already active

* don't initialize test plugins until successfully loaded

* emit websocket events when plugin statuses change

* skip pruning if already initialized

* MM-8622: maintain plugin statuses in memory

Switch away from persisting plugin statuses to the database, and
maintain in memory instead. This will be followed by a cluster interface
to query the in-memory status of plugin statuses from all cluster nodes.

At the same time, rename `cluster_discovery_id` on the `PluginStatus`
model object to `cluster_id`.

* MM-8622: aggregate plugin statuses across cluster

* fetch cluster plugin statuses when emitting websocket notification

* address unit test fixes after rebasing

* relax (poor) racey unit test re: supervisor.Wait()

* make store-mocks
Этот коммит содержится в:
Jesse Hallam
2018-05-23 14:26:35 -04:00
коммит произвёл GitHub
родитель 5c21bdc178
Коммит 847c181ec9
17 изменённых файлов: 519 добавлений и 96 удалений

Просмотреть файл

@@ -336,6 +336,10 @@ func (s *mockPluginSupervisor) Start(api plugin.API) error {
return s.hooks.OnActivate(api)
}
func (s *mockPluginSupervisor) Wait() error {
return nil
}
func (s *mockPluginSupervisor) Stop() error {
return nil
}
@@ -353,17 +357,6 @@ func (me *TestHelper) InstallPlugin(manifest *model.Manifest, hooks plugin.Hooks
me.tempWorkspace = dir
}
pluginDir := filepath.Join(me.tempWorkspace, "plugins")
webappDir := filepath.Join(me.tempWorkspace, "webapp")
me.App.InitPlugins(pluginDir, webappDir, func(bundle *model.BundleInfo) (plugin.Supervisor, error) {
if hooks, ok := me.pluginHooks[bundle.Manifest.Id]; ok {
return &mockPluginSupervisor{hooks}, nil
}
return pluginenv.DefaultSupervisorProvider(bundle)
})
me.pluginHooks[manifest.Id] = hooks
manifestCopy := *manifest
if manifestCopy.Backend == nil {
manifestCopy.Backend = &model.ManifestBackend{}
@@ -373,6 +366,9 @@ func (me *TestHelper) InstallPlugin(manifest *model.Manifest, hooks plugin.Hooks
panic(err)
}
pluginDir := filepath.Join(me.tempWorkspace, "plugins")
webappDir := filepath.Join(me.tempWorkspace, "webapp")
if err := os.MkdirAll(filepath.Join(pluginDir, manifest.Id), 0700); err != nil {
panic(err)
}
@@ -380,6 +376,15 @@ func (me *TestHelper) InstallPlugin(manifest *model.Manifest, hooks plugin.Hooks
if err := ioutil.WriteFile(filepath.Join(pluginDir, manifest.Id, "plugin.json"), manifestBytes, 0600); err != nil {
panic(err)
}
me.App.InitPlugins(pluginDir, webappDir, func(bundle *model.BundleInfo) (plugin.Supervisor, error) {
if hooks, ok := me.pluginHooks[bundle.Manifest.Id]; ok {
return &mockPluginSupervisor{hooks}, nil
}
return pluginenv.DefaultSupervisorProvider(bundle)
})
me.pluginHooks[manifest.Id] = hooks
}
func (me *TestHelper) ResetRoleMigration() {
@@ -415,6 +420,9 @@ func (me *FakeClusterInterface) GetClusterStats() ([]*model.ClusterStats, *model
func (me *FakeClusterInterface) GetLogs(page, perPage int) ([]string, *model.AppError) {
return []string{}, nil
}
func (me *FakeClusterInterface) GetPluginStatuses() (model.PluginStatuses, *model.AppError) {
return nil, nil
}
func (me *FakeClusterInterface) ConfigChanged(previousConfig *model.Config, newConfig *model.Config, sendToOtherServer bool) *model.AppError {
return nil
}