Plugins: Enable feature toggle `pluginsDynamicAngularDetectionPatterns` by default (#84723)

* Enable feature toggle pluginsDynamicAngularDetectionPatterns by default

* Change backgroundJobInterval to 24h

* re-generate feature toggles

* Use different intervals for cloud vs on-prem

* temporarily switch interval log to info level

* debug level again

* Simplify provideDynamic for tests

* re-generated feature toggles files

* PR review feedback

* PR review feedback: removed dependency from plugin management config
pull/84933/head
Giuseppe Guerra 1 year ago committed by GitHub
parent 6c1de260a2
commit eb31f71f60
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 72
      docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md
  2. 3
      pkg/services/featuremgmt/registry.go
  3. 2
      pkg/services/featuremgmt/toggles_gen.csv
  4. 9
      pkg/services/featuremgmt/toggles_gen.json
  5. 49
      pkg/services/pluginsintegration/angulardetectorsprovider/dynamic.go
  6. 31
      pkg/services/pluginsintegration/angulardetectorsprovider/dynamic_test.go
  7. 6
      pkg/services/pluginsintegration/angularinspector/angularinspector_test.go

@ -19,41 +19,42 @@ This page contains a list of available feature toggles. To learn how to turn on
Some features are enabled by default. You can disable these feature by setting the feature flag to "false" in the configuration. Some features are enabled by default. You can disable these feature by setting the feature flag to "false" in the configuration.
| Feature toggle name | Description | Enabled by default | | Feature toggle name | Description | Enabled by default |
| ------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------ | | ---------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------ |
| `disableEnvelopeEncryption` | Disable envelope encryption (emergency only) | | | `disableEnvelopeEncryption` | Disable envelope encryption (emergency only) | |
| `publicDashboards` | [Deprecated] Public dashboards are now enabled by default; to disable them, use the configuration setting. This feature toggle will be removed in the next major version. | Yes | | `publicDashboards` | [Deprecated] Public dashboards are now enabled by default; to disable them, use the configuration setting. This feature toggle will be removed in the next major version. | Yes |
| `featureHighlights` | Highlight Grafana Enterprise features | | | `featureHighlights` | Highlight Grafana Enterprise features | |
| `correlations` | Correlations page | | | `correlations` | Correlations page | |
| `exploreContentOutline` | Content outline sidebar | Yes | | `exploreContentOutline` | Content outline sidebar | Yes |
| `cloudWatchCrossAccountQuerying` | Enables cross-account querying in CloudWatch datasources | Yes | | `cloudWatchCrossAccountQuerying` | Enables cross-account querying in CloudWatch datasources | Yes |
| `nestedFolderPicker` | Enables the new folder picker to work with nested folders. Requires the nestedFolders feature toggle | Yes | | `nestedFolderPicker` | Enables the new folder picker to work with nested folders. Requires the nestedFolders feature toggle | Yes |
| `logsContextDatasourceUi` | Allow datasource to provide custom UI for context view | Yes | | `logsContextDatasourceUi` | Allow datasource to provide custom UI for context view | Yes |
| `lokiQuerySplitting` | Split large interval queries into subqueries with smaller time intervals | Yes | | `lokiQuerySplitting` | Split large interval queries into subqueries with smaller time intervals | Yes |
| `prometheusMetricEncyclopedia` | Adds the metrics explorer component to the Prometheus query builder as an option in metric select | Yes | | `prometheusMetricEncyclopedia` | Adds the metrics explorer component to the Prometheus query builder as an option in metric select | Yes |
| `influxdbBackendMigration` | Query InfluxDB InfluxQL without the proxy | Yes | | `influxdbBackendMigration` | Query InfluxDB InfluxQL without the proxy | Yes |
| `prometheusDataplane` | Changes responses to from Prometheus to be compliant with the dataplane specification. In particular, when this feature toggle is active, the numeric `Field.Name` is set from 'Value' to the value of the `__name__` label. | Yes | | `prometheusDataplane` | Changes responses to from Prometheus to be compliant with the dataplane specification. In particular, when this feature toggle is active, the numeric `Field.Name` is set from 'Value' to the value of the `__name__` label. | Yes |
| `lokiMetricDataplane` | Changes metric responses from Loki to be compliant with the dataplane specification. | Yes | | `lokiMetricDataplane` | Changes metric responses from Loki to be compliant with the dataplane specification. | Yes |
| `dataplaneFrontendFallback` | Support dataplane contract field name change for transformations and field name matchers where the name is different | Yes | | `dataplaneFrontendFallback` | Support dataplane contract field name change for transformations and field name matchers where the name is different | Yes |
| `enableElasticsearchBackendQuerying` | Enable the processing of queries and responses in the Elasticsearch data source through backend | Yes | | `enableElasticsearchBackendQuerying` | Enable the processing of queries and responses in the Elasticsearch data source through backend | Yes |
| `recordedQueriesMulti` | Enables writing multiple items from a single query within Recorded Queries | Yes | | `recordedQueriesMulti` | Enables writing multiple items from a single query within Recorded Queries | Yes |
| `logsExploreTableVisualisation` | A table visualisation for logs in Explore | Yes | | `pluginsDynamicAngularDetectionPatterns` | Enables fetching Angular detection patterns for plugins from GCOM and fallback to hardcoded ones | Yes |
| `transformationsRedesign` | Enables the transformations redesign | Yes | | `logsExploreTableVisualisation` | A table visualisation for logs in Explore | Yes |
| `traceQLStreaming` | Enables response streaming of TraceQL queries of the Tempo data source | | | `transformationsRedesign` | Enables the transformations redesign | Yes |
| `awsAsyncQueryCaching` | Enable caching for async queries for Redshift and Athena. Requires that the datasource has caching and async query support enabled | Yes | | `traceQLStreaming` | Enables response streaming of TraceQL queries of the Tempo data source | |
| `prometheusConfigOverhaulAuth` | Update the Prometheus configuration page with the new auth component | Yes | | `awsAsyncQueryCaching` | Enable caching for async queries for Redshift and Athena. Requires that the datasource has caching and async query support enabled | Yes |
| `influxdbSqlSupport` | Enable InfluxDB SQL query language support with new querying UI | Yes | | `prometheusConfigOverhaulAuth` | Update the Prometheus configuration page with the new auth component | Yes |
| `alertingNoDataErrorExecution` | Changes how Alerting state manager handles execution of NoData/Error | Yes | | `influxdbSqlSupport` | Enable InfluxDB SQL query language support with new querying UI | Yes |
| `angularDeprecationUI` | Display Angular warnings in dashboards and panels | Yes | | `alertingNoDataErrorExecution` | Changes how Alerting state manager handles execution of NoData/Error | Yes |
| `alertingInsights` | Show the new alerting insights landing page | Yes | | `angularDeprecationUI` | Display Angular warnings in dashboards and panels | Yes |
| `panelMonitoring` | Enables panel monitoring through logs and measurements | Yes | | `alertingInsights` | Show the new alerting insights landing page | Yes |
| `recoveryThreshold` | Enables feature recovery threshold (aka hysteresis) for threshold server-side expression | Yes | | `panelMonitoring` | Enables panel monitoring through logs and measurements | Yes |
| `lokiStructuredMetadata` | Enables the loki data source to request structured metadata from the Loki server | Yes | | `recoveryThreshold` | Enables feature recovery threshold (aka hysteresis) for threshold server-side expression | Yes |
| `managedPluginsInstall` | Install managed plugins directly from plugins catalog | Yes | | `lokiStructuredMetadata` | Enables the loki data source to request structured metadata from the Loki server | Yes |
| `logRowsPopoverMenu` | Enable filtering menu displayed when text of a log line is selected | Yes | | `managedPluginsInstall` | Install managed plugins directly from plugins catalog | Yes |
| `lokiQueryHints` | Enables query hints for Loki | Yes | | `logRowsPopoverMenu` | Enable filtering menu displayed when text of a log line is selected | Yes |
| `alertingQueryOptimization` | Optimizes eligible queries in order to reduce load on datasources | | | `lokiQueryHints` | Enables query hints for Loki | Yes |
| `betterPageScrolling` | Removes CustomScrollbar from the UI, relying on native browser scrollbars | Yes | | `alertingQueryOptimization` | Optimizes eligible queries in order to reduce load on datasources | |
| `betterPageScrolling` | Removes CustomScrollbar from the UI, relying on native browser scrollbars | Yes |
## Preview feature toggles ## Preview feature toggles
@ -130,7 +131,6 @@ Experimental features might be changed or removed without prior notice.
| `dashboardEmbed` | Allow embedding dashboard for external use in Code editors | | `dashboardEmbed` | Allow embedding dashboard for external use in Code editors |
| `frontendSandboxMonitorOnly` | Enables monitor only in the plugin frontend sandbox (if enabled) | | `frontendSandboxMonitorOnly` | Enables monitor only in the plugin frontend sandbox (if enabled) |
| `lokiFormatQuery` | Enables the ability to format Loki queries | | `lokiFormatQuery` | Enables the ability to format Loki queries |
| `pluginsDynamicAngularDetectionPatterns` | Enables fetching Angular detection patterns for plugins from GCOM and fallback to hardcoded ones |
| `vizAndWidgetSplit` | Split panels between visualizations and widgets | | `vizAndWidgetSplit` | Split panels between visualizations and widgets |
| `prometheusIncrementalQueryInstrumentation` | Adds RudderStack events to incremental queries | | `prometheusIncrementalQueryInstrumentation` | Adds RudderStack events to incremental queries |
| `awsDatasourcesTempCredentials` | Support temporary security credentials in AWS plugins for Grafana Cloud customers | | `awsDatasourcesTempCredentials` | Support temporary security credentials in AWS plugins for Grafana Cloud customers |

@ -510,9 +510,10 @@ var (
{ {
Name: "pluginsDynamicAngularDetectionPatterns", Name: "pluginsDynamicAngularDetectionPatterns",
Description: "Enables fetching Angular detection patterns for plugins from GCOM and fallback to hardcoded ones", Description: "Enables fetching Angular detection patterns for plugins from GCOM and fallback to hardcoded ones",
Stage: FeatureStageExperimental, Stage: FeatureStageGeneralAvailability,
FrontendOnly: false, FrontendOnly: false,
Owner: grafanaPluginsPlatformSquad, Owner: grafanaPluginsPlatformSquad,
Expression: "true", // enabled by default
}, },
{ {
Name: "vizAndWidgetSplit", Name: "vizAndWidgetSplit",

@ -67,7 +67,7 @@ frontendSandboxMonitorOnly,experimental,@grafana/plugins-platform-backend,false,
sqlDatasourceDatabaseSelection,preview,@grafana/dataviz-squad,false,false,true sqlDatasourceDatabaseSelection,preview,@grafana/dataviz-squad,false,false,true
lokiFormatQuery,experimental,@grafana/observability-logs,false,false,true lokiFormatQuery,experimental,@grafana/observability-logs,false,false,true
recordedQueriesMulti,GA,@grafana/observability-metrics,false,false,false recordedQueriesMulti,GA,@grafana/observability-metrics,false,false,false
pluginsDynamicAngularDetectionPatterns,experimental,@grafana/plugins-platform-backend,false,false,false pluginsDynamicAngularDetectionPatterns,GA,@grafana/plugins-platform-backend,false,false,false
vizAndWidgetSplit,experimental,@grafana/dashboards-squad,false,false,true vizAndWidgetSplit,experimental,@grafana/dashboards-squad,false,false,true
prometheusIncrementalQueryInstrumentation,experimental,@grafana/observability-metrics,false,false,true prometheusIncrementalQueryInstrumentation,experimental,@grafana/observability-metrics,false,false,true
logsExploreTableVisualisation,GA,@grafana/observability-logs,false,false,true logsExploreTableVisualisation,GA,@grafana/observability-logs,false,false,true

1 Name Stage Owner requiresDevMode RequiresRestart FrontendOnly
67 sqlDatasourceDatabaseSelection preview @grafana/dataviz-squad false false true
68 lokiFormatQuery experimental @grafana/observability-logs false false true
69 recordedQueriesMulti GA @grafana/observability-metrics false false false
70 pluginsDynamicAngularDetectionPatterns experimental GA @grafana/plugins-platform-backend false false false
71 vizAndWidgetSplit experimental @grafana/dashboards-squad false false true
72 prometheusIncrementalQueryInstrumentation experimental @grafana/observability-metrics false false true
73 logsExploreTableVisualisation GA @grafana/observability-logs false false true

@ -441,12 +441,15 @@
{ {
"metadata": { "metadata": {
"name": "pluginsDynamicAngularDetectionPatterns", "name": "pluginsDynamicAngularDetectionPatterns",
"resourceVersion": "1709648236447", "resourceVersion": "1710847676897",
"creationTimestamp": "2024-03-05T14:17:16Z" "creationTimestamp": "2024-03-05T14:17:16Z",
"annotations": {
"grafana.app/updatedTimestamp": "2024-03-19 11:27:56.897962695 +0000 UTC"
}
}, },
"spec": { "spec": {
"description": "Enables fetching Angular detection patterns for plugins from GCOM and fallback to hardcoded ones", "description": "Enables fetching Angular detection patterns for plugins from GCOM and fallback to hardcoded ones",
"stage": "experimental", "stage": "GA",
"codeowner": "@grafana/plugins-platform-backend" "codeowner": "@grafana/plugins-platform-backend"
} }
}, },

@ -12,18 +12,21 @@ import (
"sync" "sync"
"time" "time"
"github.com/grafana/grafana/pkg/plugins/config"
"github.com/grafana/grafana/pkg/plugins/log" "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"
"github.com/grafana/grafana/pkg/services/featuremgmt" "github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/services/pluginsintegration/angularpatternsstore" "github.com/grafana/grafana/pkg/services/pluginsintegration/angularpatternsstore"
"github.com/grafana/grafana/pkg/setting"
) )
var errNotModified = errors.New("not modified") var errNotModified = errors.New("not modified")
// backgroundJobInterval is the interval that passes between background job runs. // Intervals that passes between background job runs.
// It can be overwritten in tests. // Can be overwritten in tests.
var backgroundJobInterval = time.Hour * 1 var (
backgroundJobIntervalOnPrem = time.Hour * 24
backgroundJobIntervalCloud = time.Hour * 1
)
// Dynamic is an angulardetector.DetectorsProvider that calls GCOM to get Angular detection patterns, // Dynamic is an angulardetector.DetectorsProvider that calls GCOM to get Angular detection patterns,
// converts them to detectors and caches them for all future calls. // converts them to detectors and caches them for all future calls.
@ -45,20 +48,32 @@ type Dynamic struct {
// mux is the mutex used to read/write the cached detectors in a concurrency-safe way. // mux is the mutex used to read/write the cached detectors in a concurrency-safe way.
mux sync.RWMutex mux sync.RWMutex
// backgroundJobInterval is the interval that passes between background job runs.
backgroundJobInterval time.Duration
} }
func ProvideDynamic(cfg *config.PluginManagementCfg, store angularpatternsstore.Service, features featuremgmt.FeatureToggles) (*Dynamic, error) { func ProvideDynamic(cfg *setting.Cfg, store angularpatternsstore.Service, features featuremgmt.FeatureToggles) (*Dynamic, error) {
backgroundJobInterval := backgroundJobIntervalOnPrem
if cfg.StackID != "" {
// Use a shorter interval for cloud.
// (in cloud, cfg.StackID is always set).
backgroundJobInterval = backgroundJobIntervalCloud
}
d := &Dynamic{ d := &Dynamic{
log: log.New("plugin.angulardetectorsprovider.dynamic"), log: log.New("plugin.angulardetectorsprovider.dynamic"),
features: features, features: features,
store: store, store: store,
httpClient: makeHttpClient(), httpClient: makeHttpClient(),
baseURL: cfg.GrafanaComURL, baseURL: cfg.GrafanaComURL,
backgroundJobInterval: backgroundJobInterval,
} }
if d.IsDisabled() { if d.IsDisabled() {
// Do not attempt to restore if the background service is disabled (no feature flag) // Do not attempt to restore if the background service is disabled (no feature flag)
return d, nil return d, nil
} }
d.log.Debug("Providing dynamic angular detection patterns", "baseURL", d.baseURL, "interval", d.backgroundJobInterval)
// Perform the initial restore from db // Perform the initial restore from db
st := time.Now() st := time.Now()
@ -224,7 +239,7 @@ func (d *Dynamic) IsDisabled() bool {
} }
// randomSkew returns a random time.Duration between 0 and maxSkew. // randomSkew returns a random time.Duration between 0 and maxSkew.
// This can be added to backgroundJobInterval to skew it by a random amount. // This can be added to d.backgroundJobInterval to skew it by a random amount.
func (d *Dynamic) randomSkew(maxSkew time.Duration) time.Duration { func (d *Dynamic) randomSkew(maxSkew time.Duration) time.Duration {
return time.Duration(rand.Float64() * float64(maxSkew)) return time.Duration(rand.Float64() * float64(maxSkew))
} }
@ -242,15 +257,15 @@ func (d *Dynamic) Run(ctx context.Context) error {
// Offset the background job interval a bit to skew GCOM calls from all instances, // Offset the background job interval a bit to skew GCOM calls from all instances,
// so GCOM is not overwhelmed with lots of requests all at the same time. // so GCOM is not overwhelmed with lots of requests all at the same time.
// Important when lots of HG instances restart at the same time. // Important when lots of HG instances restart at the same time.
skew := d.randomSkew(backgroundJobInterval / 4) skew := d.randomSkew(d.backgroundJobInterval / 4)
backgroundJobInterval += skew d.backgroundJobInterval += skew
d.log.Debug( d.log.Debug(
"Applied background job skew", "Applied background job skew",
"skew", backgroundJobInterval, "interval", backgroundJobInterval, "skew", d.backgroundJobInterval, "interval", d.backgroundJobInterval,
) )
nextRunUntil := time.Until(lastUpdate.Add(backgroundJobInterval)) nextRunUntil := time.Until(lastUpdate.Add(d.backgroundJobInterval))
ticker := time.NewTicker(backgroundJobInterval) ticker := time.NewTicker(d.backgroundJobInterval)
defer ticker.Stop() defer ticker.Stop()
var tick <-chan time.Time var tick <-chan time.Time
@ -286,7 +301,7 @@ func (d *Dynamic) Run(ctx context.Context) error {
d.log.Info("Patterns update finished", "duration", time.Since(st)) d.log.Info("Patterns update finished", "duration", time.Since(st))
// Restore default ticker if we run with a shorter interval the first time // Restore default ticker if we run with a shorter interval the first time
ticker.Reset(backgroundJobInterval) ticker.Reset(d.backgroundJobInterval)
tick = ticker.C tick = ticker.C
case <-ctx.Done(): case <-ctx.Done():
return ctx.Err() return ctx.Err()

@ -14,10 +14,10 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/infra/kvstore" "github.com/grafana/grafana/pkg/infra/kvstore"
"github.com/grafana/grafana/pkg/plugins/config"
"github.com/grafana/grafana/pkg/plugins/manager/loader/angular/angulardetector" "github.com/grafana/grafana/pkg/plugins/manager/loader/angular/angulardetector"
"github.com/grafana/grafana/pkg/services/featuremgmt" "github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/services/pluginsintegration/angularpatternsstore" "github.com/grafana/grafana/pkg/services/pluginsintegration/angularpatternsstore"
"github.com/grafana/grafana/pkg/setting"
) )
func TestDynamicAngularDetectorsProvider(t *testing.T) { func TestDynamicAngularDetectorsProvider(t *testing.T) {
@ -314,6 +314,22 @@ func TestDynamicAngularDetectorsProvider(t *testing.T) {
}) })
} }
func TestDynamicAngularDetectorsProviderCloudVsOnPrem(t *testing.T) {
gcom := newDefaultGCOMScenario()
srv := gcom.newHTTPTestServer()
t.Cleanup(srv.Close)
t.Run("should use cloud interval if stack_id is set", func(t *testing.T) {
svc := provideDynamic(t, srv.URL, provideDynamicOpts{cfg: &setting.Cfg{StackID: "1234"}})
require.Equal(t, backgroundJobIntervalCloud, svc.backgroundJobInterval)
})
t.Run("should use on-prem interval if stack_id is not set", func(t *testing.T) {
svc := provideDynamic(t, srv.URL, provideDynamicOpts{cfg: &setting.Cfg{StackID: ""}})
require.Equal(t, backgroundJobIntervalOnPrem, svc.backgroundJobInterval)
})
}
func TestDynamicAngularDetectorsProviderBackgroundService(t *testing.T) { func TestDynamicAngularDetectorsProviderBackgroundService(t *testing.T) {
mockGCOMPatterns := newMockGCOMPatterns() mockGCOMPatterns := newMockGCOMPatterns()
gcom := newDefaultGCOMScenario() gcom := newDefaultGCOMScenario()
@ -321,10 +337,10 @@ func TestDynamicAngularDetectorsProviderBackgroundService(t *testing.T) {
t.Cleanup(srv.Close) t.Cleanup(srv.Close)
t.Run("background service", func(t *testing.T) { t.Run("background service", func(t *testing.T) {
oldBackgroundJobInterval := backgroundJobInterval oldBackgroundJobInterval := backgroundJobIntervalOnPrem
backgroundJobInterval = time.Millisecond * 500 backgroundJobIntervalOnPrem = time.Millisecond * 500
t.Cleanup(func() { t.Cleanup(func() {
backgroundJobInterval = oldBackgroundJobInterval backgroundJobIntervalOnPrem = oldBackgroundJobInterval
}) })
t.Run("is disabled if feature flag is not present", func(t *testing.T) { t.Run("is disabled if feature flag is not present", func(t *testing.T) {
@ -563,6 +579,7 @@ func newError500GCOMScenario() *gcomScenario {
type provideDynamicOpts struct { type provideDynamicOpts struct {
store angularpatternsstore.Service store angularpatternsstore.Service
cfg *setting.Cfg
} }
func provideDynamic(t *testing.T, gcomURL string, opts ...provideDynamicOpts) *Dynamic { func provideDynamic(t *testing.T, gcomURL string, opts ...provideDynamicOpts) *Dynamic {
@ -573,8 +590,12 @@ func provideDynamic(t *testing.T, gcomURL string, opts ...provideDynamicOpts) *D
if opt.store == nil { if opt.store == nil {
opt.store = angularpatternsstore.ProvideService(kvstore.NewFakeKVStore()) opt.store = angularpatternsstore.ProvideService(kvstore.NewFakeKVStore())
} }
if opt.cfg == nil {
opt.cfg = setting.NewCfg()
}
opt.cfg.GrafanaComURL = gcomURL
d, err := ProvideDynamic( d, err := ProvideDynamic(
&config.PluginManagementCfg{GrafanaComURL: gcomURL}, opt.cfg,
opt.store, opt.store,
featuremgmt.WithFeatures(featuremgmt.FlagPluginsDynamicAngularDetectionPatterns), featuremgmt.WithFeatures(featuremgmt.FlagPluginsDynamicAngularDetectionPatterns),
) )

@ -7,19 +7,19 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/infra/kvstore" "github.com/grafana/grafana/pkg/infra/kvstore"
"github.com/grafana/grafana/pkg/plugins/config"
"github.com/grafana/grafana/pkg/plugins/manager/loader/angular/angulardetector" "github.com/grafana/grafana/pkg/plugins/manager/loader/angular/angulardetector"
"github.com/grafana/grafana/pkg/plugins/manager/loader/angular/angularinspector" "github.com/grafana/grafana/pkg/plugins/manager/loader/angular/angularinspector"
"github.com/grafana/grafana/pkg/services/featuremgmt" "github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/services/pluginsintegration/angulardetectorsprovider" "github.com/grafana/grafana/pkg/services/pluginsintegration/angulardetectorsprovider"
"github.com/grafana/grafana/pkg/services/pluginsintegration/angularpatternsstore" "github.com/grafana/grafana/pkg/services/pluginsintegration/angularpatternsstore"
"github.com/grafana/grafana/pkg/setting"
) )
func TestProvideService(t *testing.T) { func TestProvideService(t *testing.T) {
t.Run("uses hardcoded inspector if feature flag is not present", func(t *testing.T) { t.Run("uses hardcoded inspector if feature flag is not present", func(t *testing.T) {
features := featuremgmt.WithFeatures() features := featuremgmt.WithFeatures()
dynamic, err := angulardetectorsprovider.ProvideDynamic( dynamic, err := angulardetectorsprovider.ProvideDynamic(
&config.PluginManagementCfg{}, setting.NewCfg(),
angularpatternsstore.ProvideService(kvstore.NewFakeKVStore()), angularpatternsstore.ProvideService(kvstore.NewFakeKVStore()),
features, features,
) )
@ -37,7 +37,7 @@ func TestProvideService(t *testing.T) {
featuremgmt.FlagPluginsDynamicAngularDetectionPatterns, featuremgmt.FlagPluginsDynamicAngularDetectionPatterns,
) )
dynamic, err := angulardetectorsprovider.ProvideDynamic( dynamic, err := angulardetectorsprovider.ProvideDynamic(
&config.PluginManagementCfg{}, setting.NewCfg(),
angularpatternsstore.ProvideService(kvstore.NewFakeKVStore()), angularpatternsstore.ProvideService(kvstore.NewFakeKVStore()),
features, features,
) )

Loading…
Cancel
Save