diff --git a/pkg/plugins/manager/loader/angular/angulardetector/angulardetector.go b/pkg/plugins/manager/loader/angular/angulardetector/angulardetector.go index 7738c96ea29..d4d610edb24 100644 --- a/pkg/plugins/manager/loader/angular/angulardetector/angulardetector.go +++ b/pkg/plugins/manager/loader/angular/angulardetector/angulardetector.go @@ -3,6 +3,7 @@ package angulardetector import ( "bytes" "context" + "fmt" "regexp" ) @@ -16,6 +17,8 @@ var ( // AngularDetector implements a check to see if a js file is using angular APIs. type AngularDetector interface { + fmt.Stringer + // DetectAngular takes the content of a js file and returns true if the plugin is using Angular. DetectAngular(js []byte) bool } @@ -30,6 +33,11 @@ func (d *ContainsBytesDetector) DetectAngular(moduleJs []byte) bool { return bytes.Contains(moduleJs, d.Pattern) } +// String returns the string representation of the pattern. +func (d *ContainsBytesDetector) String() string { + return string(d.Pattern) +} + // RegexDetector is an AngularDetector that returns true if the module.js content matches a regular expression. type RegexDetector struct { Regex *regexp.Regexp @@ -40,6 +48,11 @@ func (d *RegexDetector) DetectAngular(moduleJs []byte) bool { return d.Regex.Match(moduleJs) } +// String returns the string representation of the regular expression. +func (d *RegexDetector) String() string { + return d.Regex.String() +} + // DetectorsProvider can provide multiple AngularDetectors used for Angular detection. type DetectorsProvider interface { // ProvideDetectors returns a slice of AngularDetector. diff --git a/pkg/plugins/manager/loader/angular/angularinspector/angularinspector.go b/pkg/plugins/manager/loader/angular/angularinspector/angularinspector.go index 015cbd26dbc..51f5e70f8e4 100644 --- a/pkg/plugins/manager/loader/angular/angularinspector/angularinspector.go +++ b/pkg/plugins/manager/loader/angular/angularinspector/angularinspector.go @@ -8,6 +8,7 @@ import ( "regexp" "github.com/grafana/grafana/pkg/plugins" + "github.com/grafana/grafana/pkg/plugins/log" "github.com/grafana/grafana/pkg/plugins/manager/loader/angular/angulardetector" ) @@ -20,10 +21,19 @@ type Inspector interface { // PatternsListInspector is an Inspector that matches a plugin's module.js against all the patterns returned by // the detectorsProvider, in sequence. type PatternsListInspector struct { + log log.Logger + // DetectorsProvider returns the detectors that will be used by Inspect. DetectorsProvider angulardetector.DetectorsProvider } +func NewPatternListInspector(detectorsProvider angulardetector.DetectorsProvider) *PatternsListInspector { + return &PatternsListInspector{ + log: log.New("plugins.validator.angular.patterns"), + DetectorsProvider: detectorsProvider, + } +} + func (i *PatternsListInspector) Inspect(ctx context.Context, p *plugins.Plugin) (isAngular bool, err error) { f, err := p.FS.Open("module.js") if err != nil { @@ -44,6 +54,7 @@ func (i *PatternsListInspector) Inspect(ctx context.Context, p *plugins.Plugin) } for _, d := range i.DetectorsProvider.ProvideDetectors(ctx) { if d.DetectAngular(b) { + i.log.Debug("Angular detected", "pluginId", p.ID, "version", p.Info.Version, "detector", d.String()) isAngular = true break } @@ -74,5 +85,5 @@ func NewDefaultStaticDetectorsProvider() angulardetector.DetectorsProvider { // NewStaticInspector returns the default Inspector, which is a PatternsListInspector that only uses the // static (hardcoded) angular detection patterns. func NewStaticInspector() Inspector { - return &PatternsListInspector{DetectorsProvider: NewDefaultStaticDetectorsProvider()} + return NewPatternListInspector(NewDefaultStaticDetectorsProvider()) } diff --git a/pkg/plugins/manager/loader/angular/angularinspector/angularinspector_test.go b/pkg/plugins/manager/loader/angular/angularinspector/angularinspector_test.go index c2ba0e0c260..d66fcf2b285 100644 --- a/pkg/plugins/manager/loader/angular/angularinspector/angularinspector_test.go +++ b/pkg/plugins/manager/loader/angular/angularinspector/angularinspector_test.go @@ -2,6 +2,7 @@ package angularinspector import ( "context" + "regexp" "strconv" "testing" @@ -21,6 +22,10 @@ func (d *fakeDetector) DetectAngular(_ []byte) bool { return d.returns } +func (d *fakeDetector) String() string { + return "fake" +} + func TestPatternsListInspector(t *testing.T) { plugin := &plugins.Plugin{ FS: plugins.NewInMemoryFS(map[string][]byte{"module.js": nil}), @@ -73,9 +78,7 @@ func TestPatternsListInspector(t *testing.T) { for _, d := range tc.fakeDetectors { detectors = append(detectors, angulardetector.AngularDetector(d)) } - inspector := &PatternsListInspector{ - DetectorsProvider: &angulardetector.StaticDetectorsProvider{Detectors: detectors}, - } + inspector := NewPatternListInspector(&angulardetector.StaticDetectorsProvider{Detectors: detectors}) r, err := inspector.Inspect(context.Background(), plugin) tc.exp(t, r, err, tc.fakeDetectors) }) @@ -128,7 +131,7 @@ func TestDefaultStaticDetectorsInspector(t *testing.T) { exp: false, }) } - inspector := PatternsListInspector{DetectorsProvider: NewDefaultStaticDetectorsProvider()} + inspector := NewPatternListInspector(NewDefaultStaticDetectorsProvider()) for _, tc := range tcs { t.Run(tc.name, func(t *testing.T) { isAngular, err := inspector.Inspect(context.Background(), tc.plugin) @@ -143,3 +146,16 @@ func TestDefaultStaticDetectorsInspector(t *testing.T) { require.NoError(t, err) }) } + +func TestDetectorStringer(t *testing.T) { + t.Run("contains bytes detector", func(t *testing.T) { + d := angulardetector.ContainsBytesDetector{Pattern: []byte("pattern")} + require.Equal(t, "pattern", d.String()) + }) + + t.Run("regex detector", func(t *testing.T) { + const r = `["']QueryCtrl["']` + d := angulardetector.RegexDetector{Regex: regexp.MustCompile(r)} + require.Equal(t, r, d.String()) + }) +} diff --git a/pkg/services/pluginsintegration/angularinspector/angularinspector.go b/pkg/services/pluginsintegration/angularinspector/angularinspector.go index b637c11ce73..3ac8734df5d 100644 --- a/pkg/services/pluginsintegration/angularinspector/angularinspector.go +++ b/pkg/services/pluginsintegration/angularinspector/angularinspector.go @@ -24,5 +24,5 @@ func ProvideService(cfg *config.Cfg, dynamic *angulardetectorsprovider.Dynamic) if err != nil { return nil, err } - return &Service{Inspector: &angularinspector.PatternsListInspector{DetectorsProvider: detectorsProvider}}, nil + return &Service{Inspector: angularinspector.NewPatternListInspector(detectorsProvider)}, nil }