Add apiVersion to plugin models (#87510)
This commit is contained in:
@@ -3,6 +3,8 @@ package validation
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"slices"
|
||||
"time"
|
||||
|
||||
@@ -115,3 +117,36 @@ func (a *AngularDetector) Validate(ctx context.Context, p *plugins.Plugin) error
|
||||
p.Angular.HideDeprecation = slices.Contains(a.cfg.HideAngularDeprecation, p.ID)
|
||||
return nil
|
||||
}
|
||||
|
||||
// APIVersionValidation implements a ValidateFunc for validating plugin API versions.
|
||||
type APIVersionValidation struct {
|
||||
}
|
||||
|
||||
// APIVersionValidationStep returns a new ValidateFunc for validating plugin signatures.
|
||||
func APIVersionValidationStep() ValidateFunc {
|
||||
sv := &APIVersionValidation{}
|
||||
return sv.Validate
|
||||
}
|
||||
|
||||
// Validate validates the plugin signature. If a signature error is encountered, the error is recorded with the
|
||||
// pluginerrs.ErrorTracker.
|
||||
func (v *APIVersionValidation) Validate(ctx context.Context, p *plugins.Plugin) error {
|
||||
if p.APIVersion != "" {
|
||||
if !p.Backend {
|
||||
return fmt.Errorf("plugin %s has an API version but is not a backend plugin", p.ID)
|
||||
}
|
||||
// Eventually, all backend plugins will be supported
|
||||
if p.Type != plugins.TypeDataSource {
|
||||
return fmt.Errorf("plugin %s has an API version but is not a datasource plugin", p.ID)
|
||||
}
|
||||
m, err := regexp.MatchString(`^v([\d]+)(?:(alpha|beta)([\d]+))?$`, p.APIVersion)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to verify apiVersion %s: %v", p.APIVersion, err)
|
||||
}
|
||||
if !m {
|
||||
return fmt.Errorf("plugin %s has an invalid API version %s", p.ID, p.APIVersion)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
package validation
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestAPIVersionValidation(t *testing.T) {
|
||||
s := APIVersionValidationStep()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
plugin *plugins.Plugin
|
||||
err bool
|
||||
}{
|
||||
{
|
||||
name: "valid plugin",
|
||||
plugin: &plugins.Plugin{
|
||||
JSONData: plugins.JSONData{
|
||||
Backend: true,
|
||||
Type: plugins.TypeDataSource,
|
||||
APIVersion: "v0alpha1",
|
||||
},
|
||||
},
|
||||
err: false,
|
||||
},
|
||||
{
|
||||
name: "invalid plugin - not backend",
|
||||
plugin: &plugins.Plugin{
|
||||
JSONData: plugins.JSONData{
|
||||
Backend: false,
|
||||
Type: plugins.TypeDataSource,
|
||||
APIVersion: "v0alpha1",
|
||||
},
|
||||
},
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "invalid plugin - not datasource",
|
||||
plugin: &plugins.Plugin{
|
||||
JSONData: plugins.JSONData{
|
||||
Backend: true,
|
||||
Type: plugins.TypeApp,
|
||||
APIVersion: "v0alpha1",
|
||||
},
|
||||
},
|
||||
err: true,
|
||||
},
|
||||
{
|
||||
name: "invalid plugin - invalid API version",
|
||||
plugin: &plugins.Plugin{
|
||||
JSONData: plugins.JSONData{
|
||||
Backend: true,
|
||||
Type: plugins.TypeDataSource,
|
||||
APIVersion: "invalid",
|
||||
},
|
||||
},
|
||||
err: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
err := s(context.Background(), tt.plugin)
|
||||
if tt.err {
|
||||
require.Error(t, err)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -119,6 +119,9 @@ type JSONData struct {
|
||||
|
||||
// App Service Auth Registration
|
||||
IAM *pfs.IAM `json:"iam,omitempty"`
|
||||
|
||||
// API Version: Temporary field while plugins don't expose a OpenAPI schema
|
||||
APIVersion string `json:"apiVersion,omitempty"`
|
||||
}
|
||||
|
||||
func ReadPluginJSON(reader io.Reader) (JSONData, error) {
|
||||
|
||||
Reference in New Issue
Block a user