Plugins: Angular detector: Log detection patterns at debug level (#74802)

* Plugins: Angular detector: Log detection patterns at debug level

* Add tests
This commit is contained in:
Giuseppe Guerra 2023-09-13 18:35:21 +02:00 committed by GitHub
parent ad13663e74
commit 7b75bc6999
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 46 additions and 6 deletions

View File

@ -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.

View File

@ -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())
}

View File

@ -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())
})
}

View File

@ -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
}