Plugins: Replace CDN class with FS CDN type (#113968)

replace cdn class with fs type
This commit is contained in:
Will Browne
2025-11-20 14:03:24 +00:00
committed by GitHub
parent 3999d108f7
commit 7d179120b6
21 changed files with 122 additions and 114 deletions
+2 -2
View File
@@ -13,7 +13,7 @@ pluginV0Alpha1: {
id: string
version: string
url?: string
class: "core" | "external" | "cdn"
class: "core" | "external"
}
}
routes: {
@@ -233,4 +233,4 @@ pluginV0Alpha1: {
title?: string
description?: string
}]
}
}
@@ -21,5 +21,4 @@ type PluginSpecClass string
const (
PluginSpecClassCore PluginSpecClass = "core"
PluginSpecClassExternal PluginSpecClass = "external"
PluginSpecClassCdn PluginSpecClass = "cdn"
)
File diff suppressed because one or more lines are too long
@@ -23,7 +23,6 @@ type Class = string
const (
ClassCore Class = "core"
ClassExternal Class = "external"
ClassCDN Class = "cdn"
)
type Source = string
@@ -446,19 +446,6 @@ func TestPluginInstall_ToPluginInstallV0Alpha1(t *testing.T) {
require.Equal(t, pluginsv0alpha1.PluginSpecClass(ClassCore), p.Spec.Class)
},
},
{
name: "cdn class is mapped correctly",
install: PluginInstall{
ID: "plugin-cdn",
Version: "3.0.0",
Class: ClassCDN,
Source: SourcePluginStore,
},
namespace: "org-3",
validate: func(t *testing.T, p *pluginsv0alpha1.Plugin) {
require.Equal(t, pluginsv0alpha1.PluginSpecClass(ClassCDN), p.Spec.Class)
},
},
{
name: "source annotation is set correctly",
install: PluginInstall{
+12 -2
View File
@@ -19,6 +19,7 @@ import (
"github.com/grafana/grafana/pkg/login/social/socialimpl"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/plugins/config"
"github.com/grafana/grafana/pkg/plugins/manager/pluginfakes"
"github.com/grafana/grafana/pkg/plugins/manager/signature"
"github.com/grafana/grafana/pkg/plugins/manager/signature/statickey"
"github.com/grafana/grafana/pkg/plugins/pluginscdn"
@@ -265,6 +266,7 @@ func TestIntegrationHTTPServer_GetFrontendSettings_apps(t *testing.T) {
Type: plugins.TypeApp,
Preload: true,
},
FS: &pluginfakes.FakePluginFS{},
},
},
}
@@ -302,6 +304,7 @@ func TestIntegrationHTTPServer_GetFrontendSettings_apps(t *testing.T) {
Type: plugins.TypeApp,
Preload: true,
},
FS: &pluginfakes.FakePluginFS{},
},
},
}
@@ -339,6 +342,7 @@ func TestIntegrationHTTPServer_GetFrontendSettings_apps(t *testing.T) {
Preload: true,
},
Angular: plugins.AngularMeta{Detected: true},
FS: &pluginfakes.FakePluginFS{},
},
},
}
@@ -404,12 +408,12 @@ func TestIntegrationHTTPServer_GetFrontendSettings_apps(t *testing.T) {
},
},
{
desc: "app plugin with CDN class",
desc: "app plugin with CDN fs",
pluginStore: func() pluginstore.Store {
return &pluginstore.FakePluginStore{
PluginList: []pluginstore.Plugin{
{
Class: plugins.ClassCDN,
Class: plugins.ClassExternal,
Module: fmt.Sprintf("/%s/module.js", "test-app"),
JSONData: plugins.JSONData{
ID: "test-app",
@@ -417,6 +421,9 @@ func TestIntegrationHTTPServer_GetFrontendSettings_apps(t *testing.T) {
Type: plugins.TypeApp,
Preload: true,
},
FS: &pluginfakes.FakePluginFS{TypeFunc: func() plugins.FSType {
return plugins.FSTypeCDN
}},
},
},
}
@@ -545,6 +552,7 @@ func TestIntegrationHTTPServer_GetFrontendSettings_translations(t *testing.T) {
"en-US": "public/plugins/test-app/locales/en-US/test-app.json",
"pt-BR": "public/plugins/test-app/locales/pt-BR/test-app.json",
},
FS: &pluginfakes.FakePluginFS{},
},
},
}
@@ -594,6 +602,7 @@ func TestIntegrationHTTPServer_GetFrontendSettings_translations(t *testing.T) {
"en-US": "public/plugins/test-app/locales/en-US/test-app.json",
"pt-BR": "public/plugins/test-app/locales/pt-BR/test-app.json",
},
FS: &pluginfakes.FakePluginFS{},
},
},
}
@@ -633,6 +642,7 @@ func TestIntegrationHTTPServer_GetFrontendSettings_translations(t *testing.T) {
"en-US": "public/plugins/test-app/locales/en-US/test-app.json",
"pt-BR": "public/plugins/test-app/locales/pt-BR/test-app.json",
},
FS: &pluginfakes.FakePluginFS{},
},
},
}
+16 -1
View File
@@ -72,12 +72,27 @@ type UpdateInfo struct {
type FS interface {
fs.FS
Type() string
Type() FSType
Base() string
Files() ([]string, error)
Rel(string) (string, error)
}
type FSType string
const (
FSTypeCDN FSType = "cdn"
FSTypeLocal FSType = "local"
)
func (f FSType) CDN() bool {
return f == FSTypeCDN
}
func (f FSType) Local() bool {
return f == FSTypeLocal
}
type FSRemover interface {
Remove() error
}
+3 -3
View File
@@ -30,8 +30,8 @@ func NewLocalFS(basePath string) LocalFS {
return LocalFS{basePath: basePath}
}
func (f LocalFS) Type() string {
return "local"
func (f LocalFS) Type() FSType {
return FSTypeLocal
}
// fileIsAllowed takes an absolute path to a file and an os.FileInfo for that file, and it checks if access to that
@@ -219,7 +219,7 @@ func NewStaticFS(fs FS) (StaticFS, error) {
}, nil
}
func (f StaticFS) Type() string {
func (f StaticFS) Type() FSType {
return f.FS.Type()
}
@@ -36,7 +36,7 @@ func NewPatternListInspector(detectorsProvider angulardetector.DetectorsProvider
func (i *PatternsListInspector) Inspect(ctx context.Context, p *plugins.Plugin) (isAngular bool, err error) {
// CDN plugins are ignored because they should not be using Angular
if p.Class == plugins.ClassCDN {
if p.FS.Type().CDN() {
return false, nil
}
@@ -10,6 +10,7 @@ import (
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/plugins/manager/loader/angular/angulardetector"
"github.com/grafana/grafana/pkg/plugins/manager/pluginfakes"
)
type fakeDetector struct {
@@ -81,7 +82,11 @@ func TestPatternsListInspector(t *testing.T) {
{
name: "CDN plugins return false without calling detectors",
plugin: &plugins.Plugin{
Class: plugins.ClassCDN,
FS: &pluginfakes.FakePluginFS{
TypeFunc: func() plugins.FSType {
return plugins.FSTypeCDN
},
},
},
fakeDetectors: []*fakeDetector{
{returns: true},
+4 -30
View File
@@ -18,8 +18,6 @@ import (
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginerrs"
)
const concurrencyLimit = 32
type Loader struct {
cfg *pluginsCfg.PluginManagementCfg
discovery discovery.Discoverer
@@ -87,37 +85,13 @@ func (l *Loader) Load(ctx context.Context, src plugins.PluginSource) ([]*plugins
st = time.Now()
validatedPlugins := []*plugins.Plugin{}
type validateResult struct {
bootstrappedPlugin *plugins.Plugin
err error
}
validateResults := make(chan validateResult, len(bootstrappedPlugins))
var limitSize int
if src.PluginClass(ctx) == plugins.ClassCDN {
limitSize = min(len(bootstrappedPlugins), concurrencyLimit)
} else {
limitSize = 1
}
limit := make(chan struct{}, limitSize)
for _, bootstrappedPlugin := range bootstrappedPlugins {
limit <- struct{}{}
go func(p *plugins.Plugin) {
err := l.validation.Validate(ctx, p)
validateResults <- validateResult{
bootstrappedPlugin: bootstrappedPlugin,
err: err,
}
<-limit
}(bootstrappedPlugin)
}
for i := 0; i < len(bootstrappedPlugins); i++ {
r := <-validateResults
if r.err != nil {
l.recordError(ctx, r.bootstrappedPlugin, r.err)
err := l.validation.Validate(ctx, bootstrappedPlugin)
if err != nil {
l.recordError(ctx, bootstrappedPlugin, err)
continue
}
validatedPlugins = append(validatedPlugins, r.bootstrappedPlugin)
validatedPlugins = append(validatedPlugins, bootstrappedPlugin)
}
l.log.Debug("Validated", "class", src.PluginClass(ctx), "duration", time.Since(st), "total", len(validatedPlugins))
@@ -57,7 +57,7 @@ func newModuleJSValidator() *ModuleJSValidator {
func (v *ModuleJSValidator) Validate(_ context.Context, p *plugins.Plugin) error {
// CDN plugins are ignored because the module.js is guaranteed to exist
if p.Class == plugins.ClassCDN {
if p.FS.Type().CDN() {
return nil
}
@@ -96,6 +96,11 @@ func newAngularDetector(cfg *config.PluginManagementCfg, angularInspector angula
}
func (a *AngularDetector) Validate(ctx context.Context, p *plugins.Plugin) error {
// CDN plugins are ignored because they should not be using Angular
if p.FS.Type().CDN() {
return nil
}
if p.IsExternalPlugin() {
var err error
+8 -4
View File
@@ -433,6 +433,7 @@ func (f *FakeActionSetRegistry) RegisterActionSets(_ context.Context, _ string,
type FakePluginFS struct {
OpenFunc func(name string) (fs.File, error)
RemoveFunc func() error
TypeFunc func() plugins.FSType
RelFunc func(string) (string, error)
base string
@@ -444,10 +445,6 @@ func NewFakePluginFS(base string) *FakePluginFS {
}
}
func (f *FakePluginFS) Type() string {
return "fake"
}
func (f *FakePluginFS) Open(name string) (fs.File, error) {
if f.OpenFunc != nil {
return f.OpenFunc(name)
@@ -462,6 +459,13 @@ func (f *FakePluginFS) Rel(_ string) (string, error) {
return "", nil
}
func (f *FakePluginFS) Type() plugins.FSType {
if f.TypeFunc != nil {
return f.TypeFunc()
}
return "fake"
}
func (f *FakePluginFS) Base() string {
return f.base
}
@@ -345,7 +345,7 @@ func newPathSeparatorOverrideFS(sep string, ufs plugins.FS) (fsPathSeparatorFile
}, nil
}
func (f fsPathSeparatorFiles) Type() string {
func (f fsPathSeparatorFiles) Type() plugins.FSType {
return f.FS.Type()
}
@@ -42,15 +42,6 @@ func TestLocalProvider_Module(t *testing.T) {
},
expected: "public/plugins/external-plugin/module.js",
},
{
name: "CDN plugin should use standard path",
plugin: PluginInfo{
JsonData: plugins.JSONData{ID: "cdn-plugin"},
Class: plugins.ClassCDN,
FS: plugins.NewLocalFS("/cdn/plugins/cdn-plugin"),
},
expected: "public/plugins/cdn-plugin/module.js",
},
}
for _, tt := range tests {
+1 -2
View File
@@ -496,7 +496,7 @@ func (p *Plugin) IsCorePlugin() bool {
}
func (p *Plugin) IsExternalPlugin() bool {
return !p.IsCorePlugin()
return p.Class == ClassExternal
}
type Class string
@@ -504,7 +504,6 @@ type Class string
const (
ClassCore Class = "core"
ClassExternal Class = "external"
ClassCDN Class = "cdn"
)
func (c Class) String() string {
+1 -1
View File
@@ -47,7 +47,7 @@ func (f inMemoryFS) Open(fn string) (fs.File, error) {
return &inMemoryFile{path: fn, reader: bytes.NewReader(f.files[fn])}, nil
}
func (f inMemoryFS) Type() string {
func (f inMemoryFS) Type() FSType {
return "in-memory"
}
@@ -1076,9 +1076,9 @@ func TestLoader_AngularClass(t *testing.T) {
expAngularDetectionRun: true,
},
{
name: "other-class plugin should run angular detection",
class: "CDN", // (enterprise-only class)
expAngularDetectionRun: true,
name: "other class plugin should skip angular detection",
class: "foo",
expAngularDetectionRun: false,
},
} {
t.Run(tc.name, func(t *testing.T) {
@@ -1086,7 +1086,7 @@ func TestLoader_AngularClass(t *testing.T) {
PluginClassFunc: func(ctx context.Context) plugins.Class {
return tc.class
},
DiscoverFunc: sources.NewLocalSource(plugins.ClassExternal, []string{filepath.Join(testDataDir(t), "valid-v2-signature")}).Discover,
DiscoverFunc: sources.NewLocalSource(tc.class, []string{filepath.Join(testDataDir(t), "valid-v2-signature")}).Discover,
}
// if angularDetected = true, it means that the detection has run
l := newLoaderWithOpts(t, &config.PluginManagementCfg{}, loaderDepOpts{
@@ -149,7 +149,7 @@ func ReportFSMetrics(_ context.Context, p *plugins.Plugin) (*plugins.Plugin, err
return p, nil
}
metrics.SetPluginFSInformation(p.ID, p.FS.Type())
metrics.SetPluginFSInformation(p.ID, string(p.FS.Type()))
return p, nil
}
@@ -70,12 +70,12 @@ func (s *Service) LoadingStrategy(_ context.Context, p pluginstore.Plugin) plugi
// Since the parent plugin is not explicitly configured as script loading compatible,
// If the plugin is either loaded from the CDN (via its parent) or contains Angular, we should use fetch
if s.cdnEnabled(p.Parent.ID, p.Class) || p.Angular.Detected {
if s.cdnEnabled(p.Parent.ID, p.FS) || p.Angular.Detected {
return plugins.LoadingStrategyFetch
}
}
if !s.cdnEnabled(p.ID, p.Class) && !p.Angular.Detected {
if !s.cdnEnabled(p.ID, p.FS) && !p.Angular.Detected {
return plugins.LoadingStrategyScript
}
@@ -142,7 +142,7 @@ func (s *Service) moduleHash(ctx context.Context, p pluginstore.Plugin, childFSB
// CDN plugins have the version as part of the URL, which acts as a cache-buster.
// Needed due to: https://github.com/grafana/plugin-tools/pull/1426
// FS plugins build before this change will have SRI mismatch issues.
if !s.cdnEnabled(p.ID, p.Class) {
if !s.cdnEnabled(p.ID, p.FS) {
return "", nil
}
@@ -185,8 +185,8 @@ func (s *Service) compatibleCreatePluginVersion(ps map[string]string) bool {
return false
}
func (s *Service) cdnEnabled(pluginID string, class plugins.Class) bool {
return s.cdn.PluginSupported(pluginID) || class == plugins.ClassCDN
func (s *Service) cdnEnabled(pluginID string, fs plugins.FS) bool {
return s.cdn.PluginSupported(pluginID) || fs.Type().CDN()
}
// convertHashForSRI takes a SHA256 hash string and returns it as expected by the browser for SRI checks.
@@ -12,6 +12,7 @@ import (
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/plugins/config"
"github.com/grafana/grafana/pkg/plugins/manager/pluginfakes"
"github.com/grafana/grafana/pkg/plugins/manager/signature"
"github.com/grafana/grafana/pkg/plugins/manager/signature/statickey"
"github.com/grafana/grafana/pkg/plugins/pluginscdn"
@@ -58,7 +59,7 @@ func TestService_Calculate(t *testing.T) {
pluginSettings: newPluginSettings(pluginID, map[string]string{
CreatePluginVersionCfgKey: futureVersion,
}),
plugin: newPlugin(pluginID, withAngular(false)),
plugin: newPlugin(pluginID, withAngular(false), withFS(plugins.NewFakeFS())),
expected: plugins.LoadingStrategyScript,
},
{
@@ -66,16 +67,16 @@ func TestService_Calculate(t *testing.T) {
pluginSettings: newPluginSettings(pluginID, map[string]string{
// NOTE: cdn key is not set
}),
plugin: newPlugin(pluginID, withAngular(false)),
plugin: newPlugin(pluginID, withAngular(false), withFS(plugins.NewFakeFS())),
expected: plugins.LoadingStrategyScript,
},
{
name: "Expected LoadingStrategyScript when create-plugin version is not compatible, plugin is not angular, is not configured as CDN enabled and does not have the CDN class",
name: "Expected LoadingStrategyScript when create-plugin version is not compatible, plugin is not angular, is not configured as CDN enabled and does not have a CDN fs",
pluginSettings: newPluginSettings(pluginID, map[string]string{
CreatePluginVersionCfgKey: incompatVersion,
// NOTE: cdn key is not set
}),
plugin: newPlugin(pluginID, withAngular(false), withClass(plugins.ClassExternal)),
plugin: newPlugin(pluginID, withAngular(false), withClass(plugins.ClassExternal), withFS(plugins.NewFakeFS())),
expected: plugins.LoadingStrategyScript,
},
{
@@ -107,14 +108,14 @@ func TestService_Calculate(t *testing.T) {
{
name: "Expected LoadingStrategyFetch when parent create-plugin version is not set, is not configured as CDN enabled and plugin is angular",
pluginSettings: setting.PluginSettings{},
plugin: newPlugin(pluginID, withAngular(true), func(p pluginstore.Plugin) pluginstore.Plugin {
plugin: newPlugin(pluginID, withAngular(true), withFS(plugins.NewFakeFS()), func(p pluginstore.Plugin) pluginstore.Plugin {
p.Parent = &pluginstore.ParentPlugin{ID: "parent-datasource"}
return p
}),
expected: plugins.LoadingStrategyFetch,
},
{
name: "Expected LoadingStrategyFetch when create-plugin version is not compatible, plugin is not angular, is configured as CDN enabled and does not have the CDN class",
name: "Expected LoadingStrategyFetch when create-plugin version is not compatible, plugin is not angular, and plugin is configured as CDN enabled",
pluginSettings: newPluginSettings(pluginID, map[string]string{
"cdn": "true",
CreatePluginVersionCfgKey: incompatVersion,
@@ -127,7 +128,7 @@ func TestService_Calculate(t *testing.T) {
pluginSettings: newPluginSettings(pluginID, map[string]string{
CreatePluginVersionCfgKey: incompatVersion,
}),
plugin: newPlugin(pluginID, withAngular(true)),
plugin: newPlugin(pluginID, withAngular(true), withFS(plugins.NewFakeFS())),
expected: plugins.LoadingStrategyFetch,
},
{
@@ -140,19 +141,25 @@ func TestService_Calculate(t *testing.T) {
expected: plugins.LoadingStrategyFetch,
},
{
name: "Expected LoadingStrategyFetch when create-plugin version is not compatible, plugin is not angular and has the CDN class",
name: "Expected LoadingStrategyFetch when create-plugin version is not compatible, plugin is not angular and has a CDN fs",
pluginSettings: newPluginSettings(pluginID, map[string]string{
CreatePluginVersionCfgKey: incompatVersion,
}),
plugin: newPlugin(pluginID, withAngular(false), withClass(plugins.ClassCDN)),
plugin: newPlugin(pluginID, withAngular(false), withFS(
&pluginfakes.FakePluginFS{
TypeFunc: func() plugins.FSType {
return plugins.FSTypeCDN
},
},
)),
expected: plugins.LoadingStrategyFetch,
},
{
name: "Expected LoadingStrategyScript when plugin setting create-plugin version is badly formatted, plugin is not configured as CDN enabled and does not have the CDN class",
name: "Expected LoadingStrategyScript when plugin setting create-plugin version is badly formatted, plugin is not configured as CDN enabled and does not have a CDN fs",
pluginSettings: newPluginSettings(pluginID, map[string]string{
CreatePluginVersionCfgKey: "invalidSemver",
}),
plugin: newPlugin(pluginID, withAngular(false)),
plugin: newPlugin(pluginID, withAngular(false), withFS(plugins.NewFakeFS())),
expected: plugins.LoadingStrategyScript,
},
}
@@ -183,9 +190,9 @@ func TestService_ModuleHash(t *testing.T) {
features *config.Features
store []pluginstore.Plugin
// Can be used to configure plugin's class
// cdn class = loaded from CDN with no files on disk
// external class = files on disk but served from CDN only if cdn=true
// Can be used to configure plugin's fs
// fs cdn type = loaded from CDN with no files on disk
// fs local type = files on disk but served from CDN only if cdn=true
plugin pluginstore.Plugin
// When true, set cdn=true in config
@@ -204,7 +211,7 @@ func TestService_ModuleHash(t *testing.T) {
pluginID,
withSignatureStatus(plugins.SignatureStatusValid),
withFS(plugins.NewLocalFS(filepath.Join("testdata", "module-hash-valid"))),
withClass(plugins.ClassCDN),
withClass(plugins.ClassExternal),
),
cdn: true,
features: &config.Features{SriChecksEnabled: true},
@@ -236,7 +243,6 @@ func TestService_ModuleHash(t *testing.T) {
pluginID,
withSignatureStatus(plugins.SignatureStatusValid),
withFS(plugins.NewLocalFS(filepath.Join("testdata", "module-hash-valid"))),
withClass(plugins.ClassCDN),
),
cdn: true,
features: &config.Features{SriChecksEnabled: false},
@@ -261,7 +267,6 @@ func TestService_ModuleHash(t *testing.T) {
parentPluginID,
withSignatureStatus(plugins.SignatureStatusValid),
withFS(plugins.NewLocalFS(filepath.Join("testdata", "module-hash-valid-nested"))),
withClass(plugins.ClassCDN),
),
},
plugin: newPlugin(
@@ -269,7 +274,6 @@ func TestService_ModuleHash(t *testing.T) {
withSignatureStatus(plugins.SignatureStatusValid),
withFS(plugins.NewLocalFS(filepath.Join("testdata", "module-hash-valid-nested", "datasource"))),
withParent(parentPluginID),
withClass(plugins.ClassCDN),
),
cdn: true,
features: &config.Features{SriChecksEnabled: true},
@@ -284,7 +288,6 @@ func TestService_ModuleHash(t *testing.T) {
parentPluginID,
withSignatureStatus(plugins.SignatureStatusValid),
withFS(plugins.NewLocalFS(filepath.Join("testdata", "module-hash-valid-nested"))),
withClass(plugins.ClassCDN),
),
},
plugin: newPlugin(
@@ -292,7 +295,6 @@ func TestService_ModuleHash(t *testing.T) {
withSignatureStatus(plugins.SignatureStatusValid),
withFS(plugins.NewLocalFS(filepath.Join("testdata", "module-hash-valid-nested", "panels", "one"))),
withParent(parentPluginID),
withClass(plugins.ClassCDN),
),
cdn: true,
features: &config.Features{SriChecksEnabled: true},
@@ -308,14 +310,12 @@ func TestService_ModuleHash(t *testing.T) {
"grand-parent-app",
withSignatureStatus(plugins.SignatureStatusValid),
withFS(plugins.NewLocalFS(filepath.Join("testdata", "module-hash-valid-deeply-nested"))),
withClass(plugins.ClassCDN),
),
newPlugin(
"parent-datasource",
withSignatureStatus(plugins.SignatureStatusValid),
withFS(plugins.NewLocalFS(filepath.Join("testdata", "module-hash-valid-deeply-nested", "datasource"))),
withParent("grand-parent-app"),
withClass(plugins.ClassCDN),
),
},
plugin: newPlugin(
@@ -323,7 +323,6 @@ func TestService_ModuleHash(t *testing.T) {
withSignatureStatus(plugins.SignatureStatusValid),
withFS(plugins.NewLocalFS(filepath.Join("testdata", "module-hash-valid-deeply-nested", "datasource", "panels", "one"))),
withParent("parent-datasource"),
withClass(plugins.ClassCDN),
),
cdn: true,
features: &config.Features{SriChecksEnabled: true},
@@ -378,11 +377,17 @@ func TestService_ModuleHash(t *testing.T) {
t.Run(tc.name, func(t *testing.T) {
var pluginSettings setting.PluginSettings
if tc.cdn {
pluginSettings = newPluginSettings(pluginID, map[string]string{
"cdn": "true",
})
} else {
require.NotEqual(t, plugins.ClassCDN, tc.plugin.Class, "plugin should not have the CDN class because CDN is disabled")
pluginSettings = setting.PluginSettings{
pluginID: {
"cdn": "true",
},
parentPluginID: map[string]string{
"cdn": "true",
},
"grand-parent-app": map[string]string{
"cdn": "true",
},
}
}
features := tc.features
if features == nil {
@@ -439,8 +444,24 @@ func TestService_ModuleHash_Cache(t *testing.T) {
withInfo(plugins.Info{Version: "1.0.0"}),
withSignatureStatus(plugins.SignatureStatusValid),
withFS(plugins.NewLocalFS(filepath.Join("testdata", "module-hash-valid"))),
withClass(plugins.ClassCDN),
)
pCfg = &config.PluginManagementCfg{
PluginsCDNURLTemplate: "https://cdn.grafana.com",
PluginSettings: setting.PluginSettings{
pluginID: {
"cdn": "true",
},
},
Features: config.Features{SriChecksEnabled: true},
}
svc = ProvideService(
pCfg,
pluginscdn.ProvideService(pCfg),
signature.ProvideService(pCfg, statickey.New()),
pluginstore.NewFakePluginStore(),
)
k := svc.moduleHashCacheKey(pV1)
_, ok := svc.moduleHashCache.Load(k)
@@ -461,7 +482,6 @@ func TestService_ModuleHash_Cache(t *testing.T) {
withSignatureStatus(plugins.SignatureStatusValid),
// different fs for different hash
withFS(plugins.NewLocalFS(filepath.Join("testdata", "module-hash-valid-nested"))),
withClass(plugins.ClassCDN),
)
mhV2 := svc.ModuleHash(context.Background(), pV2)
require.NotEqual(t, mhV2, mhV1, "different version should have different hash")