From bc7f961d75809d899b6d1ab9733df7ba6258a80c Mon Sep 17 00:00:00 2001 From: Michael Kochell <6913320+mickmister@users.noreply.github.com> Date: Thu, 21 Jul 2022 10:55:57 -0400 Subject: [PATCH] Store plugin OnActivate errors and include them in PluginStatus response (#20430) * store plugin OnActivate errors, and include in PluginStatus * write test Co-authored-by: Mattermod --- app/plugin_test.go | 38 ++++++++++++++++++++++++++++++++++++++ model/plugin_status.go | 1 + plugin/environment.go | 26 ++++++++++++++++++++++++++ 3 files changed, 65 insertions(+) diff --git a/app/plugin_test.go b/app/plugin_test.go index 3342f12a5b..a5346e270f 100644 --- a/app/plugin_test.go +++ b/app/plugin_test.go @@ -770,6 +770,44 @@ func TestPluginPanicLogs(t *testing.T) { }) } +func TestPluginStatusActivateError(t *testing.T) { + t.Run("should return error from OnActivate in plugin statuses", func(t *testing.T) { + th := Setup(t).InitBasic() + defer th.TearDown() + + pluginSource := ` + package main + + import ( + "errors" + + "github.com/mattermost/mattermost-server/v6/plugin" + ) + + type MyPlugin struct { + plugin.MattermostPlugin + } + + func (p *MyPlugin) OnActivate() error { + return errors.New("sample error") + } + + func main() { + plugin.ClientMain(&MyPlugin{}) + } + ` + + tearDown, _, _ := SetAppEnvironmentWithPlugins(t, []string{pluginSource}, th.App, th.NewPluginAPI) + defer tearDown() + + env := th.App.GetPluginsEnvironment() + pluginStatus, err := env.Statuses() + require.NoError(t, err) + require.Len(t, pluginStatus, 1) + require.Equal(t, "sample error", pluginStatus[0].Error) + }) +} + func TestProcessPrepackagedPlugins(t *testing.T) { th := Setup(t) defer th.TearDown() diff --git a/model/plugin_status.go b/model/plugin_status.go index c206505be3..63e94c1624 100644 --- a/model/plugin_status.go +++ b/model/plugin_status.go @@ -18,6 +18,7 @@ type PluginStatus struct { ClusterId string `json:"cluster_id"` PluginPath string `json:"plugin_path"` State int `json:"state"` + Error string `json:"error"` Name string `json:"name"` Description string `json:"description"` Version string `json:"version"` diff --git a/plugin/environment.go b/plugin/environment.go index a24f1573ed..6469c9352b 100644 --- a/plugin/environment.go +++ b/plugin/environment.go @@ -32,6 +32,7 @@ type apiImplCreatorFunc func(*model.Manifest) API type registeredPlugin struct { BundleInfo *model.BundleInfo State int + Error string supervisor *supervisor } @@ -137,6 +138,22 @@ func (env *Environment) IsActive(id string) bool { return env.GetPluginState(id) == model.PluginStateRunning } +func (env *Environment) setPluginError(id string, err string) { + if rp, ok := env.registeredPlugins.Load(id); ok { + p := rp.(registeredPlugin) + p.Error = err + env.registeredPlugins.Store(id, p) + } +} + +func (env *Environment) getPluginError(id string) string { + if rp, ok := env.registeredPlugins.Load(id); ok { + return rp.(registeredPlugin).Error + } + + return "" +} + // GetPluginState returns the current state of a plugin (disabled, running, or error) func (env *Environment) GetPluginState(id string) int { rp, ok := env.registeredPlugins.Load(id) @@ -185,6 +202,7 @@ func (env *Environment) Statuses() (model.PluginStatuses, error) { PluginId: plugin.Manifest.Id, PluginPath: filepath.Dir(plugin.ManifestPath), State: pluginState, + Error: env.getPluginError(plugin.Manifest.Id), Name: plugin.Manifest.Name, Description: plugin.Manifest.Description, Version: plugin.Manifest.Version, @@ -214,6 +232,14 @@ func (env *Environment) GetManifest(pluginId string) (*model.Manifest, error) { } func (env *Environment) Activate(id string) (manifest *model.Manifest, activated bool, reterr error) { + defer func() { + if reterr != nil { + env.setPluginError(id, reterr.Error()) + } else { + env.setPluginError(id, "") + } + }() + // Check if we are already active if env.IsActive(id) { return nil, false, nil