Plugins: Tidy up CLI code (#67813)

* more tidying

* move some things around

* more tidying

* fix linter
This commit is contained in:
Will Browne 2023-05-08 10:58:47 +02:00 committed by GitHub
parent 0fc9a47779
commit e0e2535c96
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 307 additions and 298 deletions

View File

@ -127,7 +127,7 @@ func osAndArchString() string {
return osString + "-" + arch
}
func supportsCurrentArch(version *models.Version) bool {
func supportsCurrentArch(version models.Version) bool {
if version.Arch == nil {
return true
}
@ -139,10 +139,10 @@ func supportsCurrentArch(version *models.Version) bool {
return false
}
func latestSupportedVersion(plugin *models.Plugin) *models.Version {
func latestSupportedVersion(plugin models.Plugin) *models.Version {
for _, v := range plugin.Versions {
ver := v
if supportsCurrentArch(&ver) {
if supportsCurrentArch(ver) {
return &ver
}
}

View File

@ -15,11 +15,10 @@ func listRemoteCommand(c utils.CommandLine) error {
}
for _, p := range plugin.Plugins {
plugin := p
if len(plugin.Versions) > 0 {
ver := latestSupportedVersion(&plugin)
if len(p.Versions) > 0 {
ver := latestSupportedVersion(p)
if ver != nil {
logger.Infof("id: %v version: %s\n", plugin.ID, ver.Version)
logger.Infof("id: %v version: %s\n", p.ID, ver.Version)
}
}
}

View File

@ -24,7 +24,7 @@ func listVersionsCommand(c utils.CommandLine) error {
pluginToList := c.Args().First()
plugin, err := services.GetPlugin(pluginToList, c.String("repo"))
plugin, err := services.GetPluginInfoFromRepo(pluginToList, c.String("repo"))
if err != nil {
return err
}

View File

@ -6,13 +6,10 @@ import (
"github.com/fatih/color"
"github.com/grafana/grafana/pkg/cmd/grafana-cli/logger"
"github.com/grafana/grafana/pkg/cmd/grafana-cli/models"
"github.com/grafana/grafana/pkg/cmd/grafana-cli/services"
"github.com/grafana/grafana/pkg/cmd/grafana-cli/utils"
)
var ls_getPlugins func(path string) []models.InstalledPlugin = services.GetLocalPlugins
var (
errMissingPathFlag = errors.New("missing path flag")
errNotDirectory = errors.New("plugin path is not a directory")
@ -41,7 +38,7 @@ func lsCommand(c utils.CommandLine) error {
return err
}
plugins := ls_getPlugins(pluginDir)
plugins := services.GetLocalPlugins(pluginDir)
if len(plugins) > 0 {
logger.Info("installed plugins:\n")
@ -50,7 +47,8 @@ func lsCommand(c utils.CommandLine) error {
}
for _, plugin := range plugins {
logger.Infof("%s %s %s\n", plugin.ID, color.YellowString("@"), plugin.Info.Version)
logger.Infof("%s %s %s\n", plugin.Primary.JSONData.ID,
color.YellowString("@"), plugin.Primary.JSONData.Info.Version)
}
return nil

View File

@ -9,10 +9,15 @@ import (
"github.com/grafana/grafana/pkg/cmd/grafana-cli/models"
"github.com/grafana/grafana/pkg/cmd/grafana-cli/services"
"github.com/grafana/grafana/pkg/cmd/grafana-cli/utils"
"github.com/grafana/grafana/pkg/plugins"
)
func shouldUpgrade(installed string, remote *models.Plugin) bool {
installedVersion, err := version.NewVersion(installed)
func shouldUpgrade(installed plugins.FoundPlugin, remote models.Plugin) bool {
installedVer := installed.JSONData.Info.Version
if installedVer == "" {
installedVer = "0.0.0"
}
installedVersion, err := version.NewVersion(installedVer)
if err != nil {
return false
}
@ -35,30 +40,30 @@ func upgradeAllCommand(c utils.CommandLine) error {
return err
}
pluginsToUpgrade := make([]models.InstalledPlugin, 0)
pluginsToUpgrade := make([]plugins.FoundPlugin, 0)
for _, localPlugin := range localPlugins {
for _, p := range remotePlugins.Plugins {
remotePlugin := p
if localPlugin.ID != remotePlugin.ID {
if localPlugin.Primary.JSONData.ID != remotePlugin.ID {
continue
}
if shouldUpgrade(localPlugin.Info.Version, &remotePlugin) {
pluginsToUpgrade = append(pluginsToUpgrade, localPlugin)
if shouldUpgrade(localPlugin.Primary, remotePlugin) {
pluginsToUpgrade = append(pluginsToUpgrade, localPlugin.Primary)
}
}
}
ctx := context.Background()
for _, p := range pluginsToUpgrade {
logger.Infof("Updating %v \n", p.ID)
logger.Infof("Updating %v \n", p.JSONData.ID)
err = uninstallPlugin(ctx, p.ID, c)
err = uninstallPlugin(ctx, p.JSONData.ID, c)
if err != nil {
return err
}
err = installPlugin(ctx, p.ID, "", c)
err = installPlugin(ctx, p.JSONData.ID, "", c)
if err != nil {
return err
}

View File

@ -4,9 +4,10 @@ import (
"fmt"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/cmd/grafana-cli/models"
"github.com/grafana/grafana/pkg/plugins"
)
func TestVersionComparison(t *testing.T) {
@ -16,15 +17,23 @@ func TestVersionComparison(t *testing.T) {
{Version: "2.0.0"},
}
upgradeablePlugins := map[string]models.Plugin{
"0.0.0": {Versions: versions},
"1.0.0": {Versions: versions},
upgradeablePlugins := []struct {
have plugins.FoundPlugin
requested models.Plugin
}{
{
have: plugins.FoundPlugin{JSONData: plugins.JSONData{Info: plugins.Info{Version: "0.0.0"}}},
requested: models.Plugin{Versions: versions},
},
{
have: plugins.FoundPlugin{JSONData: plugins.JSONData{Info: plugins.Info{Version: "1.0.0"}}},
requested: models.Plugin{Versions: versions},
},
}
for k, v := range upgradeablePlugins {
val := v
t.Run(fmt.Sprintf("for %s should be true", k), func(t *testing.T) {
assert.True(t, shouldUpgrade(k, &val))
for _, v := range upgradeablePlugins {
t.Run(fmt.Sprintf("for %s should be true", v.have.JSONData.Info.Version), func(t *testing.T) {
require.True(t, shouldUpgrade(v.have, v.requested))
})
}
})
@ -35,15 +44,23 @@ func TestVersionComparison(t *testing.T) {
{Version: "2.0.0"},
}
shouldNotUpgrade := map[string]models.Plugin{
"2.0.0": {Versions: versions},
"6.0.0": {Versions: versions},
shouldNotUpgrade := []struct {
have plugins.FoundPlugin
requested models.Plugin
}{
{
have: plugins.FoundPlugin{JSONData: plugins.JSONData{Info: plugins.Info{Version: "2.0.0"}}},
requested: models.Plugin{Versions: versions},
},
{
have: plugins.FoundPlugin{JSONData: plugins.JSONData{Info: plugins.Info{Version: "6.0.0"}}},
requested: models.Plugin{Versions: versions},
},
}
for k, v := range shouldNotUpgrade {
val := v
t.Run(fmt.Sprintf("for %s should be false", k), func(t *testing.T) {
assert.False(t, shouldUpgrade(k, &val))
for _, v := range shouldNotUpgrade {
t.Run(fmt.Sprintf("for %s should be false", v.have.JSONData.Info.Version), func(t *testing.T) {
require.False(t, shouldUpgrade(v.have, v.requested))
})
}
})

View File

@ -16,17 +16,17 @@ func upgradeCommand(c utils.CommandLine) error {
pluginsDir := c.PluginDirectory()
pluginID := c.Args().First()
localPlugin, err := services.ReadPlugin(pluginsDir, pluginID)
localPlugin, err := services.GetLocalPlugin(pluginsDir, pluginID)
if err != nil {
return err
}
plugin, err := services.GetPlugin(pluginID, c.PluginRepoURL())
plugin, err := services.GetPluginInfoFromRepo(pluginID, c.PluginRepoURL())
if err != nil {
return err
}
if shouldUpgrade(localPlugin.Info.Version, &plugin) {
if shouldUpgrade(localPlugin, plugin) {
if err = uninstallPlugin(ctx, pluginID, c); err != nil {
return fmt.Errorf("failed to remove plugin '%s': %w", pluginID, err)
}

View File

@ -14,7 +14,7 @@ import (
"github.com/grafana/grafana/pkg/cmd/grafana-cli/models"
)
func GetPlugin(pluginId, repoUrl string) (models.Plugin, error) {
func GetPluginInfoFromRepo(pluginId, repoUrl string) (models.Plugin, error) {
logger.Debugf("getting plugin metadata from: %v pluginId: %v \n", repoUrl, pluginId)
body, err := sendRequestGetBytes(HttpClient, repoUrl, "repo", pluginId)
if err != nil {

View File

@ -1,8 +1,8 @@
package services
import (
"context"
"crypto/tls"
"encoding/json"
"errors"
"fmt"
"net"
@ -12,6 +12,10 @@ import (
"github.com/grafana/grafana/pkg/cmd/grafana-cli/logger"
"github.com/grafana/grafana/pkg/cmd/grafana-cli/models"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/plugins/config"
"github.com/grafana/grafana/pkg/plugins/manager/loader/finder"
"github.com/grafana/grafana/pkg/plugins/manager/sources"
)
var (
@ -62,43 +66,25 @@ func makeHttpClient(skipTLSVerify bool, timeout time.Duration) http.Client {
}
}
func ReadPlugin(pluginDir, pluginName string) (models.InstalledPlugin, error) {
distPluginDataPath := filepath.Join(pluginDir, pluginName, "dist", "plugin.json")
func GetLocalPlugin(pluginDir, pluginID string) (plugins.FoundPlugin, error) {
pluginPath := filepath.Join(pluginDir, pluginID)
data, err := IoHelper.ReadFile(distPluginDataPath)
ps := GetLocalPlugins(pluginPath)
if len(ps) == 0 {
return plugins.FoundPlugin{}, errors.New("could not find plugin " + pluginID + " in " + pluginDir)
}
return ps[0].Primary, nil
}
func GetLocalPlugins(pluginDir string) []*plugins.FoundBundle {
f := finder.NewLocalFinder(&config.Cfg{})
res, err := f.Find(context.Background(), sources.NewLocalSource(plugins.External, []string{pluginDir}))
if err != nil {
pluginDataPath := filepath.Join(pluginDir, pluginName, "plugin.json")
data, err = IoHelper.ReadFile(pluginDataPath)
if err != nil {
return models.InstalledPlugin{}, errors.New("Could not find dist/plugin.json or plugin.json for " + pluginName + " in " + pluginDir)
}
logger.Error("Could not get local plugins", err)
return make([]*plugins.FoundBundle, 0)
}
res := models.InstalledPlugin{}
if err := json.Unmarshal(data, &res); err != nil {
return res, err
}
if res.Info.Version == "" {
res.Info.Version = "0.0.0"
}
if res.ID == "" {
return models.InstalledPlugin{}, errors.New("could not find plugin " + pluginName + " in " + pluginDir)
}
return res, nil
}
func GetLocalPlugins(pluginDir string) []models.InstalledPlugin {
result := make([]models.InstalledPlugin, 0)
files, _ := IoHelper.ReadDir(pluginDir)
for _, f := range files {
res, err := ReadPlugin(pluginDir, f.Name())
if err == nil {
result = append(result, res)
}
}
return result
return res
}

View File

@ -20,7 +20,6 @@ import (
var walk = util.Walk
var (
ErrInvalidPluginJSON = errors.New("did not find valid type or id properties in plugin.json")
ErrInvalidPluginJSONFilePath = errors.New("invalid plugin.json filepath was provided")
)
@ -149,7 +148,7 @@ func (l *Local) readPluginJSON(pluginJSONPath string) (plugins.JSONData, error)
l.log.Warn("Skipping plugin loading as its plugin.json could not be read", "path", pluginJSONPath, "err", err)
return plugins.JSONData{}, err
}
plugin, err := ReadPluginJSON(reader)
plugin, err := plugins.ReadPluginJSON(reader)
if err != nil {
l.log.Warn("Skipping plugin loading as its plugin.json could not be read", "path", pluginJSONPath, "err", err)
return plugins.JSONData{}, err

View File

@ -15,7 +15,6 @@ import (
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/plugins/manager/fakes"
"github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/services/pluginsintegration/config"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/util"
@ -331,127 +330,6 @@ func TestFinder_getAbsPluginJSONPaths(t *testing.T) {
})
}
func TestFinder_validatePluginJSON(t *testing.T) {
type args struct {
data plugins.JSONData
}
tests := []struct {
name string
args args
err error
}{
{
name: "Valid case",
args: args{
data: plugins.JSONData{
ID: "grafana-plugin-id",
Type: plugins.DataSource,
},
},
},
{
name: "Invalid plugin ID",
args: args{
data: plugins.JSONData{
Type: plugins.Panel,
},
},
err: ErrInvalidPluginJSON,
},
{
name: "Invalid plugin type",
args: args{
data: plugins.JSONData{
ID: "grafana-plugin-id",
Type: "test",
},
},
err: ErrInvalidPluginJSON,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if err := validatePluginJSON(tt.args.data); !errors.Is(err, tt.err) {
t.Errorf("validatePluginJSON() = %v, want %v", err, tt.err)
}
})
}
}
func TestFinder_readPluginJSON(t *testing.T) {
tests := []struct {
name string
pluginPath string
expected plugins.JSONData
err error
}{
{
name: "Valid plugin",
pluginPath: "../../testdata/test-app/plugin.json",
expected: plugins.JSONData{
ID: "test-app",
Type: "app",
Name: "Test App",
Info: plugins.Info{
Author: plugins.InfoLink{
Name: "Test Inc.",
URL: "http://test.com",
},
Description: "Official Grafana Test App & Dashboard bundle",
Version: "1.0.0",
Links: []plugins.InfoLink{
{Name: "Project site", URL: "http://project.com"},
{Name: "License & Terms", URL: "http://license.com"},
},
Logos: plugins.Logos{
Small: "img/logo_small.png",
Large: "img/logo_large.png",
},
Screenshots: []plugins.Screenshots{
{Path: "img/screenshot1.png", Name: "img1"},
{Path: "img/screenshot2.png", Name: "img2"},
},
Updated: "2015-02-10",
},
Dependencies: plugins.Dependencies{
GrafanaVersion: "3.x.x",
Plugins: []plugins.Dependency{
{Type: "datasource", ID: "graphite", Name: "Graphite", Version: "1.0.0"},
{Type: "panel", ID: "graph", Name: "Graph", Version: "1.0.0"},
},
},
Includes: []*plugins.Includes{
{Name: "Nginx Connections", Path: "dashboards/connections.json", Type: "dashboard", Role: org.RoleViewer},
{Name: "Nginx Memory", Path: "dashboards/memory.json", Type: "dashboard", Role: org.RoleViewer},
{Name: "Nginx Panel", Type: "panel", Role: org.RoleViewer},
{Name: "Nginx Datasource", Type: "datasource", Role: org.RoleViewer},
},
Backend: false,
},
},
{
name: "Invalid plugin JSON",
pluginPath: "../../testdata/invalid-plugin-json/plugin.json",
err: ErrInvalidPluginJSON,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
reader, err := os.Open(tt.pluginPath)
require.NoError(t, err)
got, err := ReadPluginJSON(reader)
if tt.err != nil {
require.ErrorIs(t, err, tt.err)
}
if !cmp.Equal(got, tt.expected) {
t.Errorf("Unexpected pluginJSONData: %v", cmp.Diff(got, tt.expected))
}
require.NoError(t, reader.Close())
})
}
}
var fsComparer = cmp.Comparer(func(fs1 plugins.FS, fs2 plugins.FS) bool {
fs1Files, err := fs1.Files()
if err != nil {

View File

@ -1,47 +0,0 @@
package finder
import (
"encoding/json"
"io"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/services/org"
)
func ReadPluginJSON(reader io.Reader) (plugins.JSONData, error) {
plugin := plugins.JSONData{}
if err := json.NewDecoder(reader).Decode(&plugin); err != nil {
return plugins.JSONData{}, err
}
if err := validatePluginJSON(plugin); err != nil {
return plugins.JSONData{}, err
}
if plugin.ID == "grafana-piechart-panel" {
plugin.Name = "Pie Chart (old)"
}
if len(plugin.Dependencies.Plugins) == 0 {
plugin.Dependencies.Plugins = []plugins.Dependency{}
}
if plugin.Dependencies.GrafanaVersion == "" {
plugin.Dependencies.GrafanaVersion = "*"
}
for _, include := range plugin.Includes {
if include.Role == "" {
include.Role = org.RoleViewer
}
}
return plugin, nil
}
func validatePluginJSON(data plugins.JSONData) error {
if data.ID == "" || !data.Type.IsValid() {
return ErrInvalidPluginJSON
}
return nil
}

View File

@ -5,6 +5,7 @@ import (
"encoding/json"
"errors"
"fmt"
"io"
"io/fs"
"path"
"runtime"
@ -24,6 +25,7 @@ var (
ErrFileNotExist = errors.New("file does not exist")
ErrPluginFileRead = errors.New("file could not be read")
ErrUninstallInvalidPluginDir = errors.New("cannot recognize as plugin folder")
ErrInvalidPluginJSON = errors.New("did not find valid type or id properties in plugin.json")
)
type Plugin struct {
@ -139,6 +141,44 @@ type JSONData struct {
Executable string `json:"executable,omitempty"`
}
func ReadPluginJSON(reader io.Reader) (JSONData, error) {
plugin := JSONData{}
if err := json.NewDecoder(reader).Decode(&plugin); err != nil {
return JSONData{}, err
}
if err := validatePluginJSON(plugin); err != nil {
return JSONData{}, err
}
if plugin.ID == "grafana-piechart-panel" {
plugin.Name = "Pie Chart (old)"
}
if len(plugin.Dependencies.Plugins) == 0 {
plugin.Dependencies.Plugins = []Dependency{}
}
if plugin.Dependencies.GrafanaVersion == "" {
plugin.Dependencies.GrafanaVersion = "*"
}
for _, include := range plugin.Includes {
if include.Role == "" {
include.Role = org.RoleViewer
}
}
return plugin, nil
}
func validatePluginJSON(data JSONData) error {
if data.ID == "" || !data.Type.IsValid() {
return ErrInvalidPluginJSON
}
return nil
}
func (d JSONData) DashboardIncludes() []*Includes {
result := []*Includes{}
for _, include := range d.Includes {

167
pkg/plugins/plugins_test.go Normal file
View File

@ -0,0 +1,167 @@
package plugins
import (
"errors"
"io"
"os"
"strings"
"testing"
"github.com/google/go-cmp/cmp"
"github.com/grafana/grafana/pkg/services/org"
"github.com/stretchr/testify/require"
)
func Test_ReadPluginJSON(t *testing.T) {
tests := []struct {
name string
pluginJSON func(t *testing.T) io.ReadCloser
expected JSONData
err error
}{
{
name: "Valid plugin",
pluginJSON: func(t *testing.T) io.ReadCloser {
reader, err := os.Open("manager/testdata/test-app/plugin.json")
require.NoError(t, err)
return reader
},
expected: JSONData{
ID: "test-app",
Type: "app",
Name: "Test App",
Info: Info{
Author: InfoLink{
Name: "Test Inc.",
URL: "http://test.com",
},
Description: "Official Grafana Test App & Dashboard bundle",
Version: "1.0.0",
Links: []InfoLink{
{Name: "Project site", URL: "http://project.com"},
{Name: "License & Terms", URL: "http://license.com"},
},
Logos: Logos{
Small: "img/logo_small.png",
Large: "img/logo_large.png",
},
Screenshots: []Screenshots{
{Path: "img/screenshot1.png", Name: "img1"},
{Path: "img/screenshot2.png", Name: "img2"},
},
Updated: "2015-02-10",
},
Dependencies: Dependencies{
GrafanaVersion: "3.x.x",
Plugins: []Dependency{
{Type: "datasource", ID: "graphite", Name: "Graphite", Version: "1.0.0"},
{Type: "panel", ID: "graph", Name: "Graph", Version: "1.0.0"},
},
},
Includes: []*Includes{
{Name: "Nginx Connections", Path: "dashboards/connections.json", Type: "dashboard", Role: org.RoleViewer},
{Name: "Nginx Memory", Path: "dashboards/memory.json", Type: "dashboard", Role: org.RoleViewer},
{Name: "Nginx Panel", Type: "panel", Role: org.RoleViewer},
{Name: "Nginx Datasource", Type: "datasource", Role: org.RoleViewer},
},
Backend: false,
},
},
{
name: "Invalid plugin JSON",
pluginJSON: func(t *testing.T) io.ReadCloser {
reader, err := os.Open("manager/testdata/invalid-plugin-json/plugin.json")
require.NoError(t, err)
return reader
},
err: ErrInvalidPluginJSON,
},
{
name: "Default value overrides",
pluginJSON: func(t *testing.T) io.ReadCloser {
pJSON := `{
"id": "grafana-piechart-panel",
"name": "This will be overwritten",
"type": "panel",
"includes": [
{"type": "dashboard", "name": "Pie Charts", "path": "dashboards/demo.json"}
]
}`
return io.NopCloser(strings.NewReader(pJSON))
},
expected: JSONData{
ID: "grafana-piechart-panel",
Type: "panel",
Name: "Pie Chart (old)",
Dependencies: Dependencies{
GrafanaVersion: "*",
Plugins: []Dependency{},
},
Includes: []*Includes{
{Name: "Pie Charts", Path: "dashboards/demo.json", Type: "dashboard", Role: org.RoleViewer},
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
p := tt.pluginJSON(t)
got, err := ReadPluginJSON(p)
if tt.err != nil {
require.ErrorIs(t, err, tt.err)
}
if !cmp.Equal(got, tt.expected) {
t.Errorf("Unexpected pluginJSONData: %v", cmp.Diff(got, tt.expected))
}
require.NoError(t, p.Close())
})
}
}
func Test_validatePluginJSON(t *testing.T) {
type args struct {
data JSONData
}
tests := []struct {
name string
args args
err error
}{
{
name: "Valid case",
args: args{
data: JSONData{
ID: "grafana-plugin-id",
Type: DataSource,
},
},
},
{
name: "Invalid plugin ID",
args: args{
data: JSONData{
Type: Panel,
},
},
err: ErrInvalidPluginJSON,
},
{
name: "Invalid plugin type",
args: args{
data: JSONData{
ID: "grafana-plugin-id",
Type: "test",
},
},
err: ErrInvalidPluginJSON,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if err := validatePluginJSON(tt.args.data); !errors.Is(err, tt.err) {
t.Errorf("validatePluginJSON() = %v, want %v", err, tt.err)
}
})
}
}

View File

@ -4,7 +4,6 @@ import (
"archive/zip"
"bytes"
"context"
"encoding/json"
"errors"
"fmt"
"io"
@ -13,6 +12,7 @@ import (
"regexp"
"strings"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/plugins/log"
)
@ -39,15 +39,15 @@ func (fs *FS) Extract(ctx context.Context, pluginID string, pluginArchive *zip.R
return nil, fmt.Errorf("%v: %w", "failed to extract plugin archive", err)
}
res, err := toPluginDTO(pluginID, pluginDir)
pluginJSON, err := readPluginJSON(pluginID, pluginDir)
if err != nil {
return nil, fmt.Errorf("%v: %w", "failed to convert to plugin DTO", err)
}
fs.log.Successf("Downloaded and extracted %s v%s zip successfully to %s", res.ID, res.Info.Version, pluginDir)
fs.log.Successf("Downloaded and extracted %s v%s zip successfully to %s", pluginJSON.ID, pluginJSON.Info.Version, pluginDir)
deps := make([]*Dependency, 0, len(res.Dependencies.Plugins))
for _, plugin := range res.Dependencies.Plugins {
deps := make([]*Dependency, 0, len(pluginJSON.Dependencies.Plugins))
for _, plugin := range pluginJSON.Dependencies.Plugins {
deps = append(deps, &Dependency{
ID: plugin.ID,
Version: plugin.Version,
@ -55,8 +55,8 @@ func (fs *FS) Extract(ctx context.Context, pluginID string, pluginArchive *zip.R
}
return &ExtractedPluginArchive{
ID: res.ID,
Version: res.Info.Version,
ID: pluginJSON.ID,
Version: pluginJSON.Info.Version,
Dependencies: deps,
Path: pluginDir,
}, nil
@ -220,34 +220,26 @@ func removeGitBuildFromName(filename, pluginID string) string {
return reGitBuild.ReplaceAllString(filename, pluginID+"/")
}
func toPluginDTO(pluginID, pluginDir string) (installedPlugin, error) {
distPluginDataPath := filepath.Join(pluginDir, "dist", "plugin.json")
func readPluginJSON(pluginID, pluginDir string) (plugins.JSONData, error) {
pluginPath := filepath.Join(pluginDir, "plugin.json")
// It's safe to ignore gosec warning G304 since the file path suffix is hardcoded
// nolint:gosec
data, err := os.ReadFile(distPluginDataPath)
data, err := os.ReadFile(pluginPath)
if err != nil {
pluginDataPath := filepath.Join(pluginDir, "plugin.json")
pluginPath = filepath.Join(pluginDir, "dist", "plugin.json")
// It's safe to ignore gosec warning G304 since the file path suffix is hardcoded
// nolint:gosec
data, err = os.ReadFile(pluginDataPath)
data, err = os.ReadFile(pluginPath)
if err != nil {
return installedPlugin{}, fmt.Errorf("could not find dist/plugin.json or plugin.json for %s in %s", pluginID, pluginDir)
return plugins.JSONData{}, fmt.Errorf("could not find plugin.json or dist/plugin.json for %s in %s", pluginID, pluginDir)
}
}
res := installedPlugin{}
if err = json.Unmarshal(data, &res); err != nil {
return res, err
pJSON, err := plugins.ReadPluginJSON(bytes.NewReader(data))
if err != nil {
return plugins.JSONData{}, err
}
if res.ID == "" {
return installedPlugin{}, fmt.Errorf("could not find valid plugin %s in %s", pluginID, pluginDir)
}
if res.Info.Version == "" {
res.Info.Version = "0.0.0"
}
return res, nil
return pJSON, nil
}

View File

@ -21,28 +21,3 @@ type Dependency struct {
ID string
Version string
}
type installedPlugin struct {
ID string `json:"id"`
Name string `json:"name"`
Type string `json:"type"`
Info pluginInfo `json:"info"`
Dependencies dependencies `json:"dependencies"`
}
type dependencies struct {
GrafanaVersion string `json:"grafanaVersion"`
Plugins []pluginDependency `json:"plugins"`
}
type pluginDependency struct {
ID string `json:"id"`
Type string `json:"type"`
Name string `json:"name"`
Version string `json:"version"`
}
type pluginInfo struct {
Version string `json:"version"`
Updated string `json:"updated"`
}