Skip to content

Commit

Permalink
Plugins: Add file store abstraction for handling plugin files (grafan…
Browse files Browse the repository at this point in the history
…a#65432)

* add file store

* fix markdown fetch bug

* add markdown tests

* fix var name
  • Loading branch information
wbrowne authored Mar 29, 2023
1 parent 562d8db commit 7bbe255
Show file tree
Hide file tree
Showing 13 changed files with 212 additions and 189 deletions.
4 changes: 3 additions & 1 deletion pkg/api/http_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ type HTTPServer struct {
pluginClient plugins.Client
pluginStore plugins.Store
pluginInstaller plugins.Installer
pluginFileStore plugins.FileStore
pluginDashboardService plugindashboards.Service
pluginStaticRouteResolver plugins.StaticRouteResolver
pluginErrorResolver plugins.ErrorResolver
Expand Down Expand Up @@ -230,7 +231,7 @@ func ProvideHTTPServer(opts ServerOptions, cfg *setting.Cfg, routeRegister routi
quotaService quota.Service, socialService social.Service, tracer tracing.Tracer,
encryptionService encryption.Internal, grafanaUpdateChecker *updatechecker.GrafanaService,
pluginsUpdateChecker *updatechecker.PluginsService, searchUsersService searchusers.Service,
dataSourcesService datasources.DataSourceService, queryDataService query.Service,
dataSourcesService datasources.DataSourceService, queryDataService query.Service, pluginFileStore plugins.FileStore,
teamGuardian teamguardian.TeamGuardian, serviceaccountsService serviceaccounts.Service,
authInfoService login.AuthInfoService, storageService store.StorageService, httpEntityStore httpentitystore.HTTPEntityStore,
notificationService *notifications.NotificationService, dashboardService dashboards.DashboardService,
Expand Down Expand Up @@ -271,6 +272,7 @@ func ProvideHTTPServer(opts ServerOptions, cfg *setting.Cfg, routeRegister routi
pluginStaticRouteResolver: pluginStaticRouteResolver,
pluginDashboardService: pluginDashboardService,
pluginErrorResolver: pluginErrorResolver,
pluginFileStore: pluginFileStore,
grafanaUpdateChecker: grafanaUpdateChecker,
pluginsUpdateChecker: pluginsUpdateChecker,
SettingsProvider: settingsProvider,
Expand Down
52 changes: 10 additions & 42 deletions pkg/api/plugins.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
"path"
"path/filepath"
Expand Down Expand Up @@ -350,7 +349,7 @@ func (hs *HTTPServer) getPluginAssets(c *contextmodel.ReqContext) {

// serveLocalPluginAsset returns the content of a plugin asset file from the local filesystem to the http client.
func (hs *HTTPServer) serveLocalPluginAsset(c *contextmodel.ReqContext, plugin plugins.PluginDTO, assetPath string) {
f, err := plugin.File(assetPath)
f, err := hs.pluginFileStore.File(c.Req.Context(), plugin.ID, assetPath)
if err != nil {
if errors.Is(err, plugins.ErrFileNotExist) {
c.JsonApiErr(404, "Plugin file not found", nil)
Expand All @@ -359,35 +358,14 @@ func (hs *HTTPServer) serveLocalPluginAsset(c *contextmodel.ReqContext, plugin p
c.JsonApiErr(500, "Could not open plugin file", err)
return
}
defer func() {
if err = f.Close(); err != nil {
hs.log.Error("Failed to close plugin file", "err", err)
}
}()

fi, err := f.Stat()
if err != nil {
c.JsonApiErr(500, "Plugin file exists but could not open", err)
return
}

if hs.Cfg.Env == setting.Dev {
c.Resp.Header().Set("Cache-Control", "max-age=0, must-revalidate, no-cache")
} else {
c.Resp.Header().Set("Cache-Control", "public, max-age=3600")
}

if rs, ok := f.(io.ReadSeeker); ok {
http.ServeContent(c.Resp, c.Req, assetPath, fi.ModTime(), rs)
return
}

b, err := io.ReadAll(f)
if err != nil {
c.JsonApiErr(500, "Plugin file exists but could not read", err)
return
}
http.ServeContent(c.Resp, c.Req, assetPath, fi.ModTime(), bytes.NewReader(b))
http.ServeContent(c.Resp, c.Req, assetPath, f.ModTime, bytes.NewReader(f.Content))
}

// redirectCDNPluginAsset redirects the http request to specified asset path on the configured plugins CDN.
Expand Down Expand Up @@ -538,34 +516,24 @@ func translatePluginRequestErrorToAPIError(err error) response.Response {
return response.Error(500, "Plugin request failed", err)
}

func (hs *HTTPServer) pluginMarkdown(ctx context.Context, pluginId string, name string) ([]byte, error) {
plugin, exists := hs.pluginStore.Plugin(ctx, pluginId)
if !exists {
return make([]byte, 0), plugins.NotFoundError{PluginID: pluginId}
}

func (hs *HTTPServer) pluginMarkdown(ctx context.Context, pluginID string, name string) ([]byte, error) {
file, err := mdFilepath(strings.ToUpper(name))
if err != nil {
return make([]byte, 0), err
}

md, err := plugin.File(file)
md, err := hs.pluginFileStore.File(ctx, pluginID, file)
if err != nil {
md, err = plugin.File(strings.ToLower(file))
if errors.Is(err, plugins.ErrPluginNotInstalled) {
return make([]byte, 0), plugins.NotFoundError{PluginID: pluginID}
}

md, err = hs.pluginFileStore.File(ctx, pluginID, strings.ToLower(file))
if err != nil {
return make([]byte, 0), nil
}
}
defer func() {
if err = md.Close(); err != nil {
hs.log.Error("Failed to close plugin markdown file", "err", err)
}
}()
d, err := io.ReadAll(md)
if err != nil {
return make([]byte, 0), nil
}
return d, nil
return md.Content, nil
}

func mdFilepath(mdFilename string) (string, error) {
Expand Down
Loading

0 comments on commit 7bbe255

Please sign in to comment.