mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
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:
@@ -3,6 +3,7 @@ package angulardetector
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"regexp"
|
"regexp"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -16,6 +17,8 @@ var (
|
|||||||
|
|
||||||
// AngularDetector implements a check to see if a js file is using angular APIs.
|
// AngularDetector implements a check to see if a js file is using angular APIs.
|
||||||
type AngularDetector interface {
|
type AngularDetector interface {
|
||||||
|
fmt.Stringer
|
||||||
|
|
||||||
// DetectAngular takes the content of a js file and returns true if the plugin is using Angular.
|
// DetectAngular takes the content of a js file and returns true if the plugin is using Angular.
|
||||||
DetectAngular(js []byte) bool
|
DetectAngular(js []byte) bool
|
||||||
}
|
}
|
||||||
@@ -30,6 +33,11 @@ func (d *ContainsBytesDetector) DetectAngular(moduleJs []byte) bool {
|
|||||||
return bytes.Contains(moduleJs, d.Pattern)
|
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.
|
// RegexDetector is an AngularDetector that returns true if the module.js content matches a regular expression.
|
||||||
type RegexDetector struct {
|
type RegexDetector struct {
|
||||||
Regex *regexp.Regexp
|
Regex *regexp.Regexp
|
||||||
@@ -40,6 +48,11 @@ func (d *RegexDetector) DetectAngular(moduleJs []byte) bool {
|
|||||||
return d.Regex.Match(moduleJs)
|
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.
|
// DetectorsProvider can provide multiple AngularDetectors used for Angular detection.
|
||||||
type DetectorsProvider interface {
|
type DetectorsProvider interface {
|
||||||
// ProvideDetectors returns a slice of AngularDetector.
|
// ProvideDetectors returns a slice of AngularDetector.
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"regexp"
|
"regexp"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/plugins"
|
"github.com/grafana/grafana/pkg/plugins"
|
||||||
|
"github.com/grafana/grafana/pkg/plugins/log"
|
||||||
"github.com/grafana/grafana/pkg/plugins/manager/loader/angular/angulardetector"
|
"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
|
// PatternsListInspector is an Inspector that matches a plugin's module.js against all the patterns returned by
|
||||||
// the detectorsProvider, in sequence.
|
// the detectorsProvider, in sequence.
|
||||||
type PatternsListInspector struct {
|
type PatternsListInspector struct {
|
||||||
|
log log.Logger
|
||||||
|
|
||||||
// DetectorsProvider returns the detectors that will be used by Inspect.
|
// DetectorsProvider returns the detectors that will be used by Inspect.
|
||||||
DetectorsProvider angulardetector.DetectorsProvider
|
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) {
|
func (i *PatternsListInspector) Inspect(ctx context.Context, p *plugins.Plugin) (isAngular bool, err error) {
|
||||||
f, err := p.FS.Open("module.js")
|
f, err := p.FS.Open("module.js")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -44,6 +54,7 @@ func (i *PatternsListInspector) Inspect(ctx context.Context, p *plugins.Plugin)
|
|||||||
}
|
}
|
||||||
for _, d := range i.DetectorsProvider.ProvideDetectors(ctx) {
|
for _, d := range i.DetectorsProvider.ProvideDetectors(ctx) {
|
||||||
if d.DetectAngular(b) {
|
if d.DetectAngular(b) {
|
||||||
|
i.log.Debug("Angular detected", "pluginId", p.ID, "version", p.Info.Version, "detector", d.String())
|
||||||
isAngular = true
|
isAngular = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -74,5 +85,5 @@ func NewDefaultStaticDetectorsProvider() angulardetector.DetectorsProvider {
|
|||||||
// NewStaticInspector returns the default Inspector, which is a PatternsListInspector that only uses the
|
// NewStaticInspector returns the default Inspector, which is a PatternsListInspector that only uses the
|
||||||
// static (hardcoded) angular detection patterns.
|
// static (hardcoded) angular detection patterns.
|
||||||
func NewStaticInspector() Inspector {
|
func NewStaticInspector() Inspector {
|
||||||
return &PatternsListInspector{DetectorsProvider: NewDefaultStaticDetectorsProvider()}
|
return NewPatternListInspector(NewDefaultStaticDetectorsProvider())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package angularinspector
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@@ -21,6 +22,10 @@ func (d *fakeDetector) DetectAngular(_ []byte) bool {
|
|||||||
return d.returns
|
return d.returns
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *fakeDetector) String() string {
|
||||||
|
return "fake"
|
||||||
|
}
|
||||||
|
|
||||||
func TestPatternsListInspector(t *testing.T) {
|
func TestPatternsListInspector(t *testing.T) {
|
||||||
plugin := &plugins.Plugin{
|
plugin := &plugins.Plugin{
|
||||||
FS: plugins.NewInMemoryFS(map[string][]byte{"module.js": nil}),
|
FS: plugins.NewInMemoryFS(map[string][]byte{"module.js": nil}),
|
||||||
@@ -73,9 +78,7 @@ func TestPatternsListInspector(t *testing.T) {
|
|||||||
for _, d := range tc.fakeDetectors {
|
for _, d := range tc.fakeDetectors {
|
||||||
detectors = append(detectors, angulardetector.AngularDetector(d))
|
detectors = append(detectors, angulardetector.AngularDetector(d))
|
||||||
}
|
}
|
||||||
inspector := &PatternsListInspector{
|
inspector := NewPatternListInspector(&angulardetector.StaticDetectorsProvider{Detectors: detectors})
|
||||||
DetectorsProvider: &angulardetector.StaticDetectorsProvider{Detectors: detectors},
|
|
||||||
}
|
|
||||||
r, err := inspector.Inspect(context.Background(), plugin)
|
r, err := inspector.Inspect(context.Background(), plugin)
|
||||||
tc.exp(t, r, err, tc.fakeDetectors)
|
tc.exp(t, r, err, tc.fakeDetectors)
|
||||||
})
|
})
|
||||||
@@ -128,7 +131,7 @@ func TestDefaultStaticDetectorsInspector(t *testing.T) {
|
|||||||
exp: false,
|
exp: false,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
inspector := PatternsListInspector{DetectorsProvider: NewDefaultStaticDetectorsProvider()}
|
inspector := NewPatternListInspector(NewDefaultStaticDetectorsProvider())
|
||||||
for _, tc := range tcs {
|
for _, tc := range tcs {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
isAngular, err := inspector.Inspect(context.Background(), tc.plugin)
|
isAngular, err := inspector.Inspect(context.Background(), tc.plugin)
|
||||||
@@ -143,3 +146,16 @@ func TestDefaultStaticDetectorsInspector(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
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())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
@@ -24,5 +24,5 @@ func ProvideService(cfg *config.Cfg, dynamic *angulardetectorsprovider.Dynamic)
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &Service{Inspector: &angularinspector.PatternsListInspector{DetectorsProvider: detectorsProvider}}, nil
|
return &Service{Inspector: angularinspector.NewPatternListInspector(detectorsProvider)}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user