Chore: use errutil for pluginRepo errors (#78647)

* Chore: use errutil for pluginRepo errors

* Update pkg/util/errutil/status.go

* Use errutil helper functions

Co-Authored-By: Marcus Efraimsson <marcus.efraimsson@gmail.com>

* Forgot the log level

* Use entity

---------

Co-authored-by: Marcus Efraimsson <marcus.efraimsson@gmail.com>
This commit is contained in:
Gabriel MABILLE
2023-11-30 15:49:27 +01:00
committed by GitHub
co-authored by Marcus Efraimsson
parent d64c2b6f4e
commit ef2c79d22a
9 changed files with 121 additions and 68 deletions
+1 -1
View File
@@ -164,7 +164,7 @@ func (c *Client) downloadFile(tmpFile *os.File, pluginURL, checksum string, comp
return fmt.Errorf("failed to write to %q: %w", tmpFile.Name(), err)
}
if len(checksum) > 0 && checksum != fmt.Sprintf("%x", h.Sum(nil)) {
return ErrChecksumMismatch{archiveURL: pluginURL}
return ErrChecksumMismatch(pluginURL)
}
return nil
}
+37 -36
View File
@@ -1,6 +1,10 @@
package repo
import "fmt"
import (
"fmt"
"github.com/grafana/grafana/pkg/util/errutil"
)
type ErrResponse4xx struct {
message string
@@ -43,47 +47,44 @@ func (e ErrResponse4xx) Error() string {
return fmt.Sprintf("%d", e.statusCode)
}
type ErrVersionUnsupported struct {
pluginID string
requestedVersion string
systemInfo string
var (
ErrVersionUnsupportedMsg = "{{.Public.PluginID}} v{{.Public.Version}} is not supported on your system {{.Public.SysInfo}}"
ErrVersionUnsupportedBase = errutil.Conflict("plugin.unsupportedVersion").
MustTemplate(ErrVersionUnsupportedMsg, errutil.WithPublic(ErrVersionUnsupportedMsg))
ErrVersionNotFoundMsg = "{{.Public.PluginID}} v{{.Public.Version}} either does not exist or is not supported on your system {{.Public.SysInfo}}"
ErrVersionNotFoundBase = errutil.NotFound("plugin.versionNotFound").
MustTemplate(ErrVersionNotFoundMsg, errutil.WithPublic(ErrVersionNotFoundMsg))
ErrArcNotFoundMsg = "{{.Public.PluginID}} is not compatible with your system architecture: {{.Public.SysInfo}}"
ErrArcNotFoundBase = errutil.NotFound("plugin.archNotFound").
MustTemplate(ErrArcNotFoundMsg, errutil.WithPublic(ErrArcNotFoundMsg))
ErrChecksumMismatchMsg = "expected SHA256 checksum does not match the downloaded archive ({{.Public.ArchiveURL}}) - please contact security@grafana.com"
ErrChecksumMismatchBase = errutil.UnprocessableEntity("plugin.checksumMismatch").
MustTemplate(ErrChecksumMismatchMsg, errutil.WithPublic(ErrChecksumMismatchMsg))
ErrCorePluginMsg = "plugin {{.Public.PluginID}} is a core plugin and cannot be installed separately"
ErrCorePluginBase = errutil.Forbidden("plugin.forbiddenCorePluginInstall").
MustTemplate(ErrCorePluginMsg, errutil.WithPublic(ErrCorePluginMsg))
)
func ErrVersionUnsupported(pluginID, requestedVersion, systemInfo string) error {
return ErrVersionUnsupportedBase.Build(errutil.TemplateData{Public: map[string]any{"PluginID": pluginID, "Version": requestedVersion, "SysInfo": systemInfo}})
}
func (e ErrVersionUnsupported) Error() string {
return fmt.Sprintf("%s v%s is not supported on your system (%s)", e.pluginID, e.requestedVersion, e.systemInfo)
func ErrVersionNotFound(pluginID, requestedVersion, systemInfo string) error {
return ErrVersionNotFoundBase.Build(errutil.TemplateData{Public: map[string]any{"PluginID": pluginID, "Version": requestedVersion, "SysInfo": systemInfo}})
}
type ErrVersionNotFound struct {
pluginID string
requestedVersion string
systemInfo string
func ErrArcNotFound(pluginID, systemInfo string) error {
return ErrArcNotFoundBase.Build(errutil.TemplateData{Public: map[string]any{"PluginID": pluginID, "SysInfo": systemInfo}})
}
func (e ErrVersionNotFound) Error() string {
return fmt.Sprintf("%s v%s either does not exist or is not supported on your system (%s)", e.pluginID, e.requestedVersion, e.systemInfo)
func ErrChecksumMismatch(archiveURL string) error {
return ErrChecksumMismatchBase.Build(errutil.TemplateData{Public: map[string]any{"ArchiveURL": archiveURL}})
}
type ErrArcNotFound struct {
pluginID string
systemInfo string
}
func (e ErrArcNotFound) Error() string {
return fmt.Sprintf("%s is not compatible with your system architecture: %s", e.pluginID, e.systemInfo)
}
type ErrChecksumMismatch struct {
archiveURL string
}
func (e ErrChecksumMismatch) Error() string {
return fmt.Sprintf("expected SHA256 checksum does not match the downloaded archive (%s) - please contact security@grafana.com", e.archiveURL)
}
type ErrCorePlugin struct {
id string
}
func (e ErrCorePlugin) Error() string {
return fmt.Sprintf("plugin %s is a core plugin and cannot be installed separately", e.id)
func ErrCorePlugin(pluginID string) error {
return ErrCorePluginBase.Build(errutil.TemplateData{Public: map[string]any{"PluginID": pluginID}})
}
+36
View File
@@ -1,9 +1,11 @@
package repo
import (
"errors"
"net/http"
"testing"
"github.com/grafana/grafana/pkg/util/errutil"
"github.com/stretchr/testify/require"
)
@@ -24,3 +26,37 @@ func TestErrResponse4xx(t *testing.T) {
require.Equal(t, compatInfo, err.compatibilityInfo)
})
}
func TestErrorTemplates(t *testing.T) {
base := &errutil.Error{}
err := ErrVersionUnsupported("grafana-test-app", "1.0.0", "darwin-amd64")
require.True(t, errors.As(err, base))
require.Equal(t, http.StatusConflict, base.Public().StatusCode)
require.Equal(t, "plugin.unsupportedVersion", base.Public().MessageID)
require.Equal(t, "grafana-test-app v1.0.0 is not supported on your system darwin-amd64", base.Public().Message)
err = ErrVersionNotFound("grafana-test-app", "1.0.0", "darwin-amd64")
require.True(t, errors.As(err, base))
require.Equal(t, http.StatusNotFound, base.Public().StatusCode)
require.Equal(t, "plugin.versionNotFound", base.Public().MessageID)
require.Equal(t, "grafana-test-app v1.0.0 either does not exist or is not supported on your system darwin-amd64", base.Public().Message)
err = ErrArcNotFound("grafana-test-app", "darwin-amd64")
require.True(t, errors.As(err, base))
require.Equal(t, http.StatusNotFound, base.Public().StatusCode)
require.Equal(t, "plugin.archNotFound", base.Public().MessageID)
require.Equal(t, "grafana-test-app is not compatible with your system architecture: darwin-amd64", base.Public().Message)
err = ErrChecksumMismatch("http://localhost:6481/grafana-test-app/versions/1.0.0/download")
require.True(t, errors.As(err, base))
require.Equal(t, http.StatusUnprocessableEntity, base.Public().StatusCode)
require.Equal(t, "plugin.checksumMismatch", base.Public().MessageID)
require.Equal(t, "expected SHA256 checksum does not match the downloaded archive (http://localhost:6481/grafana-test-app/versions/1.0.0/download) - please contact security@grafana.com", base.Public().Message)
err = ErrCorePlugin("grafana-test-app")
require.True(t, errors.As(err, base))
require.Equal(t, http.StatusForbidden, base.Public().StatusCode)
require.Equal(t, "plugin.forbiddenCorePluginInstall", base.Public().MessageID)
require.Equal(t, "plugin grafana-test-app is a core plugin and cannot be installed separately", base.Public().Message)
}
+1 -1
View File
@@ -98,7 +98,7 @@ func (m *Manager) PluginVersion(pluginID, version string, compatOpts CompatOpts)
_, hasAnyArch := compatibleVer.Arch["any"]
if isGrafanaCorePlugin && hasAnyArch {
// Trying to install a coupled core plugin
return VersionData{}, ErrCorePlugin{id: pluginID}
return VersionData{}, ErrCorePlugin(pluginID)
}
return compatibleVer, nil
+3 -3
View File
@@ -35,14 +35,14 @@ func TestGetPluginArchive(t *testing.T) {
{
name: "Incorrect SHA returns error",
sha: "1a2b3c",
err: &ErrChecksumMismatch{},
err: ErrChecksumMismatchBase,
},
{
name: "Core plugin",
sha: "69f698961b6ea651211a187874434821c4727cc22de022e3a7059116d21c75b1",
apiOpSys: "any",
apiUrl: "https://github.com/grafana/grafana/tree/main/public/app/plugins/test",
err: &ErrCorePlugin{},
err: ErrCorePluginBase,
},
{
name: "Decoupled core plugin",
@@ -99,7 +99,7 @@ func TestGetPluginArchive(t *testing.T) {
co := NewCompatOpts(grafanaVersion, opSys, arch)
archive, err := m.GetPluginArchive(context.Background(), pluginID, version, co)
if tc.err != nil {
require.ErrorAs(t, err, tc.err)
require.ErrorIs(t, err, tc.err)
return
}
require.NoError(t, err)
+3 -14
View File
@@ -25,10 +25,7 @@ func SelectSystemCompatibleVersion(log log.PrettyLogger, versions []Version, plu
var ver Version
latestForArch, exists := latestSupportedVersion(versions, compatOpts)
if !exists {
return VersionData{}, ErrArcNotFound{
pluginID: pluginID,
systemInfo: compatOpts.OSAndArch(),
}
return VersionData{}, ErrArcNotFound(pluginID, compatOpts.OSAndArch())
}
if version == "" {
@@ -49,21 +46,13 @@ func SelectSystemCompatibleVersion(log log.PrettyLogger, versions []Version, plu
if len(ver.Version) == 0 {
log.Debugf("Requested plugin version %s v%s not found but potential fallback version '%s' was found",
pluginID, version, latestForArch.Version)
return VersionData{}, ErrVersionNotFound{
pluginID: pluginID,
requestedVersion: version,
systemInfo: compatOpts.OSAndArch(),
}
return VersionData{}, ErrVersionNotFound(pluginID, version, compatOpts.OSAndArch())
}
if !supportsCurrentArch(ver, compatOpts) {
log.Debugf("Requested plugin version %s v%s is not supported on your system but potential fallback version '%s' was found",
pluginID, version, latestForArch.Version)
return VersionData{}, ErrVersionUnsupported{
pluginID: pluginID,
requestedVersion: version,
systemInfo: compatOpts.OSAndArch(),
}
return VersionData{}, ErrVersionUnsupported(pluginID, version, compatOpts.OSAndArch())
}
return VersionData{