mirror of
https://github.com/grafana/grafana.git
synced 2025-08-02 18:02:15 +08:00
Plugins: Enable plugin runtime install/uninstall capabilities (#33836)
* add uninstall flow * add install flow * small cleanup * smaller-footprint solution * cleanup + make bp start auto * fix interface contract * improve naming * accept version arg * ensure use of shared logger * make installer a field * add plugin decommissioning * add basic error checking * fix api docs * making initialization idempotent * add mutex * fix comment * fix test * add test for decommission * improve existing test * add more test coverage * more tests * change test func to use read lock * refactoring + adding test asserts * improve purging old install flow * improve dupe checking * change log name * skip over dupe scanned * make test assertion more flexible * remove trailing line * fix pointer receiver name * update comment * add context to API * add config flag * add base http api test + fix update functionality * simplify existing check * clean up test * refactor tests based on feedback * add single quotes to errs * use gcmp in tests + fix logo issue * make plugin list testing more flexible * address feedback * fix API test * fix linter * undo preallocate * Update docs/sources/administration/configuration.md Co-authored-by: achatterjee-grafana <70489351+achatterjee-grafana@users.noreply.github.com> * Update docs/sources/administration/configuration.md Co-authored-by: achatterjee-grafana <70489351+achatterjee-grafana@users.noreply.github.com> * Update docs/sources/administration/configuration.md Co-authored-by: achatterjee-grafana <70489351+achatterjee-grafana@users.noreply.github.com> * fix linting issue in test * add docs placeholder * update install notes * Update docs/sources/plugins/marketplace.md Co-authored-by: Marcus Olsson <marcus.olsson@hey.com> * update access wording * add more placeholder docs * add link to more info * PR feedback - improved errors, refactor, lock fix * improve err details * propagate plugin version errors * don't autostart renderer * add H1 * fix imports Co-authored-by: achatterjee-grafana <70489351+achatterjee-grafana@users.noreply.github.com> Co-authored-by: Marcus Olsson <marcus.olsson@hey.com>
This commit is contained in:
@ -9,7 +9,6 @@ import (
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"gopkg.in/macaron.v1"
|
||||
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||
@ -19,6 +18,8 @@ import (
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/grafana/grafana/pkg/plugins/backendplugin"
|
||||
"github.com/grafana/grafana/pkg/plugins/manager/installer"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
func (hs *HTTPServer) GetPluginList(c *models.ReqContext) response.Response {
|
||||
@ -370,6 +371,56 @@ func (hs *HTTPServer) GetPluginErrorsList(_ *models.ReqContext) response.Respons
|
||||
return response.JSON(200, hs.PluginManager.ScanningErrors())
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) InstallPlugin(c *models.ReqContext, dto dtos.InstallPluginCommand) response.Response {
|
||||
pluginID := c.Params("pluginId")
|
||||
|
||||
err := hs.PluginManager.Install(c.Req.Context(), pluginID, dto.Version)
|
||||
if err != nil {
|
||||
var dupeErr plugins.DuplicatePluginError
|
||||
if errors.As(err, &dupeErr) {
|
||||
return response.Error(http.StatusConflict, "Plugin already installed", err)
|
||||
}
|
||||
var versionUnsupportedErr installer.ErrVersionUnsupported
|
||||
if errors.As(err, &versionUnsupportedErr) {
|
||||
return response.Error(http.StatusConflict, "Plugin version not supported", err)
|
||||
}
|
||||
var versionNotFoundErr installer.ErrVersionNotFound
|
||||
if errors.As(err, &versionNotFoundErr) {
|
||||
return response.Error(http.StatusNotFound, "Plugin version not found", err)
|
||||
}
|
||||
if errors.Is(err, installer.ErrPluginNotFound) {
|
||||
return response.Error(http.StatusNotFound, "Plugin not found", err)
|
||||
}
|
||||
if errors.Is(err, plugins.ErrInstallCorePlugin) {
|
||||
return response.Error(http.StatusForbidden, "Cannot install or change a Core plugin", err)
|
||||
}
|
||||
|
||||
return response.Error(http.StatusInternalServerError, "Failed to install plugin", err)
|
||||
}
|
||||
|
||||
return response.JSON(http.StatusOK, []byte{})
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) UninstallPlugin(c *models.ReqContext) response.Response {
|
||||
pluginID := c.Params("pluginId")
|
||||
|
||||
err := hs.PluginManager.Uninstall(c.Req.Context(), pluginID)
|
||||
if err != nil {
|
||||
if errors.Is(err, plugins.ErrPluginNotInstalled) {
|
||||
return response.Error(http.StatusNotFound, "Plugin not installed", err)
|
||||
}
|
||||
if errors.Is(err, plugins.ErrUninstallCorePlugin) {
|
||||
return response.Error(http.StatusForbidden, "Cannot uninstall a Core plugin", err)
|
||||
}
|
||||
if errors.Is(err, plugins.ErrUninstallOutsideOfPluginDir) {
|
||||
return response.Error(http.StatusForbidden, "Cannot uninstall a plugin outside of the plugins directory", err)
|
||||
}
|
||||
|
||||
return response.Error(http.StatusInternalServerError, "Failed to uninstall plugin", err)
|
||||
}
|
||||
return response.JSON(http.StatusOK, []byte{})
|
||||
}
|
||||
|
||||
func translatePluginRequestErrorToAPIError(err error) response.Response {
|
||||
if errors.Is(err, backendplugin.ErrPluginNotRegistered) {
|
||||
return response.Error(404, "Plugin not found", err)
|
||||
|
Reference in New Issue
Block a user