Cloudwatch: Deprecate cloudwatchNewRegionsHandler feature toggle and remove core imports from featuremgmt (#81310)

* Remove core imports from grafana/pkg/services/featuremgmt in CloudWatch
This commit is contained in:
Nathan Vērzemnieks 2024-01-30 13:11:52 +01:00 committed by GitHub
parent cc56e0e75c
commit ec4fafa08f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
27 changed files with 120 additions and 218 deletions

View File

@ -30,7 +30,6 @@ Some features are enabled by default. You can disable these feature by setting t
| `cloudWatchCrossAccountQuerying` | Enables cross-account querying in CloudWatch datasources | Yes | | `cloudWatchCrossAccountQuerying` | Enables cross-account querying in CloudWatch datasources | Yes |
| `redshiftAsyncQueryDataSupport` | Enable async query data support for Redshift | Yes | | `redshiftAsyncQueryDataSupport` | Enable async query data support for Redshift | Yes |
| `athenaAsyncQueryDataSupport` | Enable async query data support for Athena | Yes | | `athenaAsyncQueryDataSupport` | Enable async query data support for Athena | Yes |
| `cloudwatchNewRegionsHandler` | Refactor of /regions endpoint, no user-facing changes | 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 |
| `disablePrometheusExemplarSampling` | Disable Prometheus exemplar sampling | | | `disablePrometheusExemplarSampling` | Disable Prometheus exemplar sampling | |
| `logsContextDatasourceUi` | Allow datasource to provide custom UI for context view | Yes | | `logsContextDatasourceUi` | Allow datasource to provide custom UI for context view | Yes |

View File

@ -48,7 +48,6 @@ export interface FeatureToggles {
cloudWatchCrossAccountQuerying?: boolean; cloudWatchCrossAccountQuerying?: boolean;
redshiftAsyncQueryDataSupport?: boolean; redshiftAsyncQueryDataSupport?: boolean;
athenaAsyncQueryDataSupport?: boolean; athenaAsyncQueryDataSupport?: boolean;
cloudwatchNewRegionsHandler?: boolean;
showDashboardValidationWarnings?: boolean; showDashboardValidationWarnings?: boolean;
mysqlAnsiQuotes?: boolean; mysqlAnsiQuotes?: boolean;
accessControlOnCall?: boolean; accessControlOnCall?: boolean;

View File

@ -264,15 +264,6 @@ var (
AllowSelfServe: false, AllowSelfServe: false,
Created: time.Date(2022, time.August, 27, 12, 0, 0, 0, time.UTC), Created: time.Date(2022, time.August, 27, 12, 0, 0, 0, time.UTC),
}, },
{
Name: "cloudwatchNewRegionsHandler",
Description: "Refactor of /regions endpoint, no user-facing changes",
Stage: FeatureStageGeneralAvailability,
Expression: "true", // enabled by default
Owner: awsDatasourcesSquad,
AllowSelfServe: true,
Created: time.Date(2023, time.September, 25, 12, 0, 0, 0, time.UTC),
},
{ {
Name: "showDashboardValidationWarnings", Name: "showDashboardValidationWarnings",
Description: "Show warnings when dashboards do not validate against the schema", Description: "Show warnings when dashboards do not validate against the schema",

View File

@ -29,7 +29,6 @@ unifiedStorage,experimental,@grafana/grafana-app-platform-squad,2022-12-01,true,
cloudWatchCrossAccountQuerying,GA,@grafana/aws-datasources,2022-11-28,false,false,false cloudWatchCrossAccountQuerying,GA,@grafana/aws-datasources,2022-11-28,false,false,false
redshiftAsyncQueryDataSupport,GA,@grafana/aws-datasources,2022-08-27,false,false,false redshiftAsyncQueryDataSupport,GA,@grafana/aws-datasources,2022-08-27,false,false,false
athenaAsyncQueryDataSupport,GA,@grafana/aws-datasources,2022-08-27,false,false,true athenaAsyncQueryDataSupport,GA,@grafana/aws-datasources,2022-08-27,false,false,true
cloudwatchNewRegionsHandler,GA,@grafana/aws-datasources,2023-09-25,false,false,false
showDashboardValidationWarnings,experimental,@grafana/dashboards-squad,2022-10-14,false,false,false showDashboardValidationWarnings,experimental,@grafana/dashboards-squad,2022-10-14,false,false,false
mysqlAnsiQuotes,experimental,@grafana/backend-platform,2022-10-12,false,false,false mysqlAnsiQuotes,experimental,@grafana/backend-platform,2022-10-12,false,false,false
accessControlOnCall,preview,@grafana/identity-access-team,2022-10-19,false,false,false accessControlOnCall,preview,@grafana/identity-access-team,2022-10-19,false,false,false

1 Name Stage Owner Created requiresDevMode RequiresRestart FrontendOnly
29 cloudWatchCrossAccountQuerying GA @grafana/aws-datasources 2022-11-28 false false false
30 redshiftAsyncQueryDataSupport GA @grafana/aws-datasources 2022-08-27 false false false
31 athenaAsyncQueryDataSupport GA @grafana/aws-datasources 2022-08-27 false false true
cloudwatchNewRegionsHandler GA @grafana/aws-datasources 2023-09-25 false false false
32 showDashboardValidationWarnings experimental @grafana/dashboards-squad 2022-10-14 false false false
33 mysqlAnsiQuotes experimental @grafana/backend-platform 2022-10-12 false false false
34 accessControlOnCall preview @grafana/identity-access-team 2022-10-19 false false false

View File

@ -127,10 +127,6 @@ const (
// Enable async query data support for Athena // Enable async query data support for Athena
FlagAthenaAsyncQueryDataSupport = "athenaAsyncQueryDataSupport" FlagAthenaAsyncQueryDataSupport = "athenaAsyncQueryDataSupport"
// FlagCloudwatchNewRegionsHandler
// Refactor of /regions endpoint, no user-facing changes
FlagCloudwatchNewRegionsHandler = "cloudwatchNewRegionsHandler"
// FlagShowDashboardValidationWarnings // FlagShowDashboardValidationWarnings
// Show warnings when dashboards do not validate against the schema // Show warnings when dashboards do not validate against the schema
FlagShowDashboardValidationWarnings = "showDashboardValidationWarnings" FlagShowDashboardValidationWarnings = "showDashboardValidationWarnings"

View File

@ -71,7 +71,7 @@ func TestIntegrationPluginManager(t *testing.T) {
hcp := httpclient.NewProvider() hcp := httpclient.NewProvider()
am := azuremonitor.ProvideService(hcp) am := azuremonitor.ProvideService(hcp)
cw := cloudwatch.ProvideService(cfg, hcp, features) cw := cloudwatch.ProvideService(cfg, hcp)
cm := cloudmonitoring.ProvideService(hcp) cm := cloudmonitoring.ProvideService(hcp)
es := elasticsearch.ProvideService(hcp, tracer) es := elasticsearch.ProvideService(hcp, tracer)
grap := graphite.ProvideService(hcp, tracer) grap := graphite.ProvideService(hcp, tracer)

View File

@ -12,7 +12,6 @@ import (
"github.com/grafana/grafana-plugin-sdk-go/backend" "github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana-plugin-sdk-go/backend/datasource" "github.com/grafana/grafana-plugin-sdk-go/backend/datasource"
"github.com/grafana/grafana-plugin-sdk-go/backend/instancemgmt" "github.com/grafana/grafana-plugin-sdk-go/backend/instancemgmt"
"github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/models" "github.com/grafana/grafana/pkg/tsdb/cloudwatch/models"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@ -35,7 +34,7 @@ func TestQuery_AnnotationQuery(t *testing.T) {
return DataSource{Settings: models.CloudWatchSettings{}}, nil return DataSource{Settings: models.CloudWatchSettings{}}, nil
}) })
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{}, featuremgmt.WithFeatures()) executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
_, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{ _, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{
PluginContext: backend.PluginContext{ PluginContext: backend.PluginContext{
DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}, DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{},
@ -69,7 +68,7 @@ func TestQuery_AnnotationQuery(t *testing.T) {
return DataSource{Settings: models.CloudWatchSettings{}}, nil return DataSource{Settings: models.CloudWatchSettings{}}, nil
}) })
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{}, featuremgmt.WithFeatures()) executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
_, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{ _, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{
PluginContext: backend.PluginContext{ PluginContext: backend.PluginContext{
DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}, DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{},

View File

@ -22,7 +22,6 @@ import (
"github.com/grafana/grafana-plugin-sdk-go/backend/instancemgmt" "github.com/grafana/grafana-plugin-sdk-go/backend/instancemgmt"
"github.com/grafana/grafana-plugin-sdk-go/backend/resource/httpadapter" "github.com/grafana/grafana-plugin-sdk-go/backend/resource/httpadapter"
"github.com/grafana/grafana/pkg/infra/log" "github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/clients" "github.com/grafana/grafana/pkg/tsdb/cloudwatch/clients"
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/kinds/dataquery" "github.com/grafana/grafana/pkg/tsdb/cloudwatch/kinds/dataquery"
@ -62,10 +61,10 @@ const (
var logger = log.New("tsdb.cloudwatch") var logger = log.New("tsdb.cloudwatch")
func ProvideService(cfg *setting.Cfg, httpClientProvider *httpclient.Provider, features featuremgmt.FeatureToggles) *CloudWatchService { func ProvideService(cfg *setting.Cfg, httpClientProvider *httpclient.Provider) *CloudWatchService {
logger.Debug("Initializing") logger.Debug("Initializing")
executor := newExecutor(datasource.NewInstanceManager(NewInstanceSettings(httpClientProvider)), cfg, awsds.NewSessionCache(), features) executor := newExecutor(datasource.NewInstanceManager(NewInstanceSettings(httpClientProvider)), cfg, awsds.NewSessionCache())
return &CloudWatchService{ return &CloudWatchService{
Cfg: cfg, Cfg: cfg,
@ -82,12 +81,11 @@ type SessionCache interface {
GetSession(c awsds.SessionConfig) (*session.Session, error) GetSession(c awsds.SessionConfig) (*session.Session, error)
} }
func newExecutor(im instancemgmt.InstanceManager, cfg *setting.Cfg, sessions SessionCache, features featuremgmt.FeatureToggles) *cloudWatchExecutor { func newExecutor(im instancemgmt.InstanceManager, cfg *setting.Cfg, sessions SessionCache) *cloudWatchExecutor {
e := &cloudWatchExecutor{ e := &cloudWatchExecutor{
im: im, im: im,
cfg: cfg, cfg: cfg,
sessions: sessions, sessions: sessions,
features: features,
} }
e.resourceHandler = httpadapter.New(e.newResourceMux()) e.resourceHandler = httpadapter.New(e.newResourceMux())
@ -124,7 +122,6 @@ type cloudWatchExecutor struct {
im instancemgmt.InstanceManager im instancemgmt.InstanceManager
cfg *setting.Cfg cfg *setting.Cfg
sessions SessionCache sessions SessionCache
features featuremgmt.FeatureToggles
regionCache sync.Map regionCache sync.Map
resourceHandler backend.CallResourceHandler resourceHandler backend.CallResourceHandler
@ -156,7 +153,6 @@ func (e *cloudWatchExecutor) getRequestContext(ctx context.Context, pluginCtx ba
LogsAPIProvider: NewLogsAPI(sess), LogsAPIProvider: NewLogsAPI(sess),
EC2APIProvider: ec2Client, EC2APIProvider: ec2Client,
Settings: instance.Settings, Settings: instance.Settings,
Features: e.features,
Logger: logger, Logger: logger,
}, nil }, nil
} }

View File

@ -16,7 +16,6 @@ import (
"github.com/grafana/grafana-plugin-sdk-go/backend" "github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana-plugin-sdk-go/backend/datasource" "github.com/grafana/grafana-plugin-sdk-go/backend/datasource"
"github.com/grafana/grafana-plugin-sdk-go/backend/instancemgmt" "github.com/grafana/grafana-plugin-sdk-go/backend/instancemgmt"
"github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/mocks" "github.com/grafana/grafana/pkg/tsdb/cloudwatch/mocks"
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/models" "github.com/grafana/grafana/pkg/tsdb/cloudwatch/models"
@ -55,13 +54,13 @@ func Test_CloudWatch_CallResource_Integration_Test(t *testing.T) {
return &api return &api
} }
im := datasource.NewInstanceManager((func(ctx context.Context, s backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) { im := datasource.NewInstanceManager(func(ctx context.Context, s backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
return DataSource{Settings: models.CloudWatchSettings{ return DataSource{Settings: models.CloudWatchSettings{
AWSDatasourceSettings: awsds.AWSDatasourceSettings{ AWSDatasourceSettings: awsds.AWSDatasourceSettings{
Region: "us-east-1", Region: "us-east-1",
}, },
}}, nil }}, nil
})) })
t.Run("Should handle dimension value request and return values from the api", func(t *testing.T) { t.Run("Should handle dimension value request and return values from the api", func(t *testing.T) {
pageLimit := 100 pageLimit := 100
@ -77,7 +76,7 @@ func Test_CloudWatch_CallResource_Integration_Test(t *testing.T) {
{MetricName: aws.String("Test_MetricName8"), Dimensions: []*cloudwatch.Dimension{{Name: aws.String("Test_DimensionName4"), Value: aws.String("Value1")}}}, {MetricName: aws.String("Test_MetricName8"), Dimensions: []*cloudwatch.Dimension{{Name: aws.String("Test_DimensionName4"), Value: aws.String("Value1")}}},
{MetricName: aws.String("Test_MetricName9"), Dimensions: []*cloudwatch.Dimension{{Name: aws.String("Test_DimensionName1"), Value: aws.String("Value2")}}}, {MetricName: aws.String("Test_MetricName9"), Dimensions: []*cloudwatch.Dimension{{Name: aws.String("Test_DimensionName1"), Value: aws.String("Value2")}}},
}, MetricsPerPage: 100} }, MetricsPerPage: 100}
executor := newExecutor(im, &setting.Cfg{AWSListMetricsPageLimit: pageLimit}, &fakeSessionCache{}, featuremgmt.WithFeatures()) executor := newExecutor(im, &setting.Cfg{AWSListMetricsPageLimit: pageLimit}, &fakeSessionCache{})
req := &backend.CallResourceRequest{ req := &backend.CallResourceRequest{
Method: "GET", Method: "GET",
@ -113,7 +112,7 @@ func Test_CloudWatch_CallResource_Integration_Test(t *testing.T) {
{MetricName: aws.String("Test_MetricName8"), Dimensions: []*cloudwatch.Dimension{{Name: aws.String("Test_DimensionName4")}}}, {MetricName: aws.String("Test_MetricName8"), Dimensions: []*cloudwatch.Dimension{{Name: aws.String("Test_DimensionName4")}}},
{MetricName: aws.String("Test_MetricName9"), Dimensions: []*cloudwatch.Dimension{{Name: aws.String("Test_DimensionName1")}}}, {MetricName: aws.String("Test_MetricName9"), Dimensions: []*cloudwatch.Dimension{{Name: aws.String("Test_DimensionName1")}}},
}, MetricsPerPage: 2} }, MetricsPerPage: 2}
executor := newExecutor(im, &setting.Cfg{AWSListMetricsPageLimit: pageLimit}, &fakeSessionCache{}, featuremgmt.WithFeatures()) executor := newExecutor(im, &setting.Cfg{AWSListMetricsPageLimit: pageLimit}, &fakeSessionCache{})
req := &backend.CallResourceRequest{ req := &backend.CallResourceRequest{
Method: "GET", Method: "GET",
@ -137,7 +136,7 @@ func Test_CloudWatch_CallResource_Integration_Test(t *testing.T) {
t.Run("Should handle standard dimension key query and return hard coded keys", func(t *testing.T) { t.Run("Should handle standard dimension key query and return hard coded keys", func(t *testing.T) {
api = mocks.FakeMetricsAPI{} api = mocks.FakeMetricsAPI{}
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{}, featuremgmt.WithFeatures()) executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
req := &backend.CallResourceRequest{ req := &backend.CallResourceRequest{
Method: "GET", Method: "GET",
@ -161,7 +160,7 @@ func Test_CloudWatch_CallResource_Integration_Test(t *testing.T) {
t.Run("Should handle custom namespace dimension key query and return hard coded keys", func(t *testing.T) { t.Run("Should handle custom namespace dimension key query and return hard coded keys", func(t *testing.T) {
api = mocks.FakeMetricsAPI{} api = mocks.FakeMetricsAPI{}
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{}, featuremgmt.WithFeatures()) executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
req := &backend.CallResourceRequest{ req := &backend.CallResourceRequest{
Method: "GET", Method: "GET",
@ -197,7 +196,7 @@ func Test_CloudWatch_CallResource_Integration_Test(t *testing.T) {
{MetricName: aws.String("Test_MetricName8"), Namespace: aws.String("AWS/EC2"), Dimensions: []*cloudwatch.Dimension{{Name: aws.String("Test_DimensionName4")}}}, {MetricName: aws.String("Test_MetricName8"), Namespace: aws.String("AWS/EC2"), Dimensions: []*cloudwatch.Dimension{{Name: aws.String("Test_DimensionName4")}}},
{MetricName: aws.String("Test_MetricName9"), Namespace: aws.String("AWS/EC2"), Dimensions: []*cloudwatch.Dimension{{Name: aws.String("Test_DimensionName1")}}}, {MetricName: aws.String("Test_MetricName9"), Namespace: aws.String("AWS/EC2"), Dimensions: []*cloudwatch.Dimension{{Name: aws.String("Test_DimensionName1")}}},
}, MetricsPerPage: 2} }, MetricsPerPage: 2}
executor := newExecutor(im, &setting.Cfg{AWSListMetricsPageLimit: pageLimit}, &fakeSessionCache{}, featuremgmt.WithFeatures()) executor := newExecutor(im, &setting.Cfg{AWSListMetricsPageLimit: pageLimit}, &fakeSessionCache{})
req := &backend.CallResourceRequest{ req := &backend.CallResourceRequest{
Method: "GET", Method: "GET",
@ -233,7 +232,7 @@ func Test_CloudWatch_CallResource_Integration_Test(t *testing.T) {
}, },
}, },
}, nil) }, nil)
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{}, featuremgmt.WithFeatures()) executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
req := &backend.CallResourceRequest{ req := &backend.CallResourceRequest{
Method: "GET", Method: "GET",
@ -254,7 +253,7 @@ func Test_CloudWatch_CallResource_Integration_Test(t *testing.T) {
}) })
t.Run("Should handle region requests and return regions from the api", func(t *testing.T) { t.Run("Should handle region requests and return regions from the api", func(t *testing.T) {
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{}, featuremgmt.WithFeatures(featuremgmt.FlagCloudwatchNewRegionsHandler, true)) executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
req := &backend.CallResourceRequest{ req := &backend.CallResourceRequest{
Method: "GET", Method: "GET",
Path: `/regions`, Path: `/regions`,
@ -272,25 +271,6 @@ func Test_CloudWatch_CallResource_Integration_Test(t *testing.T) {
assert.Contains(t, string(sent.Body), `"name":"us-east-1"`) assert.Contains(t, string(sent.Body), `"name":"us-east-1"`)
}) })
t.Run("Should handle legacy region requests and feature toggle is turned off", func(t *testing.T) {
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{}, featuremgmt.WithFeatures(featuremgmt.FlagCloudwatchNewRegionsHandler, false))
req := &backend.CallResourceRequest{
Method: "GET",
Path: `/regions`,
PluginContext: backend.PluginContext{
DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{ID: 0},
PluginID: "cloudwatch",
},
}
err := executor.CallResource(context.Background(), req, sender)
require.NoError(t, err)
sent := sender.Response
require.NotNil(t, sent)
require.Equal(t, http.StatusOK, sent.Status)
require.Nil(t, err)
assert.Contains(t, string(sent.Body), `"text":"us-east-1"`)
})
t.Run("Should error for any request when a default region is not selected", func(t *testing.T) { t.Run("Should error for any request when a default region is not selected", func(t *testing.T) {
imWithoutDefaultRegion := datasource.NewInstanceManager(func(ctx context.Context, s backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) { imWithoutDefaultRegion := datasource.NewInstanceManager(func(ctx context.Context, s backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
return DataSource{Settings: models.CloudWatchSettings{ return DataSource{Settings: models.CloudWatchSettings{
@ -298,7 +278,7 @@ func Test_CloudWatch_CallResource_Integration_Test(t *testing.T) {
}}, nil }}, nil
}) })
executor := newExecutor(imWithoutDefaultRegion, newTestConfig(), &fakeSessionCache{}, featuremgmt.WithFeatures(featuremgmt.FlagCloudwatchNewRegionsHandler, false)) executor := newExecutor(imWithoutDefaultRegion, newTestConfig(), &fakeSessionCache{})
req := &backend.CallResourceRequest{ req := &backend.CallResourceRequest{
Method: "GET", Method: "GET",
Path: `/regions`, Path: `/regions`,
@ -313,6 +293,6 @@ func Test_CloudWatch_CallResource_Integration_Test(t *testing.T) {
require.NotNil(t, sent) require.NotNil(t, sent)
require.Equal(t, http.StatusBadRequest, sent.Status) require.Equal(t, http.StatusBadRequest, sent.Status)
require.Nil(t, err) require.Nil(t, err)
assert.Contains(t, string(sent.Body), "unexpected error missing default region") assert.Contains(t, string(sent.Body), "missing default region")
}) })
} }

View File

@ -16,7 +16,7 @@ import (
"github.com/grafana/grafana-plugin-sdk-go/backend/datasource" "github.com/grafana/grafana-plugin-sdk-go/backend/datasource"
"github.com/grafana/grafana-plugin-sdk-go/backend/httpclient" "github.com/grafana/grafana-plugin-sdk-go/backend/httpclient"
"github.com/grafana/grafana-plugin-sdk-go/backend/instancemgmt" "github.com/grafana/grafana-plugin-sdk-go/backend/instancemgmt"
"github.com/grafana/grafana/pkg/services/featuremgmt" "github.com/grafana/grafana/pkg/tsdb/cloudwatch/features"
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/mocks" "github.com/grafana/grafana/pkg/tsdb/cloudwatch/mocks"
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/models" "github.com/grafana/grafana/pkg/tsdb/cloudwatch/models"
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/utils" "github.com/grafana/grafana/pkg/tsdb/cloudwatch/utils"
@ -119,7 +119,7 @@ func Test_CheckHealth(t *testing.T) {
t.Run("successfully query metrics and logs", func(t *testing.T) { t.Run("successfully query metrics and logs", func(t *testing.T) {
client = fakeCheckHealthClient{} client = fakeCheckHealthClient{}
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{}, featuremgmt.WithFeatures()) executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
resp, err := executor.CheckHealth(context.Background(), &backend.CheckHealthRequest{ resp, err := executor.CheckHealth(context.Background(), &backend.CheckHealthRequest{
PluginContext: backend.PluginContext{DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}}, PluginContext: backend.PluginContext{DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}},
@ -138,7 +138,7 @@ func Test_CheckHealth(t *testing.T) {
return nil, fmt.Errorf("some logs query error") return nil, fmt.Errorf("some logs query error")
}} }}
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{}, featuremgmt.WithFeatures()) executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
resp, err := executor.CheckHealth(context.Background(), &backend.CheckHealthRequest{ resp, err := executor.CheckHealth(context.Background(), &backend.CheckHealthRequest{
PluginContext: backend.PluginContext{DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}}, PluginContext: backend.PluginContext{DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}},
@ -157,7 +157,7 @@ func Test_CheckHealth(t *testing.T) {
return fmt.Errorf("some list metrics error") return fmt.Errorf("some list metrics error")
}} }}
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{}, featuremgmt.WithFeatures()) executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
resp, err := executor.CheckHealth(context.Background(), &backend.CheckHealthRequest{ resp, err := executor.CheckHealth(context.Background(), &backend.CheckHealthRequest{
PluginContext: backend.PluginContext{DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}}, PluginContext: backend.PluginContext{DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}},
@ -175,7 +175,7 @@ func Test_CheckHealth(t *testing.T) {
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{getSession: func(c awsds.SessionConfig) (*session.Session, error) { executor := newExecutor(im, newTestConfig(), &fakeSessionCache{getSession: func(c awsds.SessionConfig) (*session.Session, error) {
return nil, fmt.Errorf("some sessions error") return nil, fmt.Errorf("some sessions error")
}}, featuremgmt.WithFeatures()) }})
resp, err := executor.CheckHealth(context.Background(), &backend.CheckHealthRequest{ resp, err := executor.CheckHealth(context.Background(), &backend.CheckHealthRequest{
PluginContext: backend.PluginContext{DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}}, PluginContext: backend.PluginContext{DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}},
@ -234,8 +234,8 @@ func TestQuery_ResourceRequest_DescribeLogGroups_with_CrossAccountQuerying(t *te
}, },
} }
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{}, featuremgmt.WithFeatures(featuremgmt.FlagCloudWatchCrossAccountQuerying)) executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
err := executor.CallResource(context.Background(), req, sender) err := executor.CallResource(contextWithFeaturesEnabled(features.FlagCloudWatchCrossAccountQuerying), req, sender)
assert.NoError(t, err) assert.NoError(t, err)
assert.JSONEq(t, `[ assert.JSONEq(t, `[

View File

@ -0,0 +1,17 @@
package features
import (
"context"
"github.com/grafana/grafana-plugin-sdk-go/backend"
)
const (
FlagCloudWatchCrossAccountQuerying = "cloudWatchCrossAccountQuerying"
FlagCloudWatchWildCardDimensionValues = "cloudWatchWildCardDimensionValues"
FlagCloudWatchBatchQueries = "cloudWatchBatchQueries"
)
func IsEnabled(ctx context.Context, feature string) bool {
return backend.GrafanaConfigFromContext(ctx).FeatureToggles().IsEnabled(feature)
}

View File

@ -16,10 +16,10 @@ import (
"github.com/aws/aws-sdk-go/service/cloudwatchlogs/cloudwatchlogsiface" "github.com/aws/aws-sdk-go/service/cloudwatchlogs/cloudwatchlogsiface"
"github.com/grafana/grafana-plugin-sdk-go/backend" "github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana-plugin-sdk-go/data" "github.com/grafana/grafana-plugin-sdk-go/data"
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/features"
"golang.org/x/sync/errgroup" "golang.org/x/sync/errgroup"
"github.com/grafana/grafana/pkg/infra/log" "github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/models" "github.com/grafana/grafana/pkg/tsdb/cloudwatch/models"
) )
@ -212,7 +212,7 @@ func (e *cloudWatchExecutor) executeStartQuery(ctx context.Context, logsClient c
QueryString: aws.String(modifiedQueryString), QueryString: aws.String(modifiedQueryString),
} }
if logsQuery.LogGroups != nil && len(logsQuery.LogGroups) > 0 && e.features.IsEnabled(ctx, featuremgmt.FlagCloudWatchCrossAccountQuerying) { if logsQuery.LogGroups != nil && len(logsQuery.LogGroups) > 0 && features.IsEnabled(ctx, features.FlagCloudWatchCrossAccountQuerying) {
var logGroupIdentifiers []string var logGroupIdentifiers []string
for _, lg := range logsQuery.LogGroups { for _, lg := range logsQuery.LogGroups {
arn := lg.Arn arn := lg.Arn

View File

@ -15,7 +15,7 @@ import (
"github.com/grafana/grafana-plugin-sdk-go/backend/datasource" "github.com/grafana/grafana-plugin-sdk-go/backend/datasource"
"github.com/grafana/grafana-plugin-sdk-go/backend/instancemgmt" "github.com/grafana/grafana-plugin-sdk-go/backend/instancemgmt"
"github.com/grafana/grafana-plugin-sdk-go/data" "github.com/grafana/grafana-plugin-sdk-go/data"
"github.com/grafana/grafana/pkg/services/featuremgmt" "github.com/grafana/grafana/pkg/tsdb/cloudwatch/features"
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/mocks" "github.com/grafana/grafana/pkg/tsdb/cloudwatch/mocks"
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/models" "github.com/grafana/grafana/pkg/tsdb/cloudwatch/models"
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/utils" "github.com/grafana/grafana/pkg/tsdb/cloudwatch/utils"
@ -90,7 +90,7 @@ func TestQuery_handleGetLogEvents_passes_nil_start_and_end_times_to_GetLogEvents
return DataSource{Settings: models.CloudWatchSettings{}}, nil return DataSource{Settings: models.CloudWatchSettings{}}, nil
}) })
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{}, featuremgmt.WithFeatures()) executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
_, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{ _, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{
PluginContext: backend.PluginContext{ PluginContext: backend.PluginContext{
DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}, DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{},
@ -123,7 +123,7 @@ func TestQuery_GetLogEvents_returns_response_from_GetLogEvents_to_data_frame_fie
im := datasource.NewInstanceManager(func(ctx context.Context, s backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) { im := datasource.NewInstanceManager(func(ctx context.Context, s backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
return DataSource{Settings: models.CloudWatchSettings{}}, nil return DataSource{Settings: models.CloudWatchSettings{}}, nil
}) })
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{}, featuremgmt.WithFeatures()) executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
cli = &mocks.MockLogEvents{} cli = &mocks.MockLogEvents{}
cli.On("GetLogEventsWithContext", mock.Anything, mock.Anything, mock.Anything).Return(&cloudwatchlogs.GetLogEventsOutput{ cli.On("GetLogEventsWithContext", mock.Anything, mock.Anything, mock.Anything).Return(&cloudwatchlogs.GetLogEventsOutput{
@ -208,7 +208,7 @@ func TestQuery_StartQuery(t *testing.T) {
}}, nil }}, nil
}) })
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{}, featuremgmt.WithFeatures()) executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
_, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{ _, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{
PluginContext: backend.PluginContext{ PluginContext: backend.PluginContext{
DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}, DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{},
@ -265,7 +265,7 @@ func TestQuery_StartQuery(t *testing.T) {
}}, nil }}, nil
}) })
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{}, featuremgmt.WithFeatures()) executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
resp, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{ resp, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{
PluginContext: backend.PluginContext{ PluginContext: backend.PluginContext{
DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}, DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{},
@ -322,7 +322,7 @@ func Test_executeStartQuery(t *testing.T) {
im := datasource.NewInstanceManager(func(ctx context.Context, s backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) { im := datasource.NewInstanceManager(func(ctx context.Context, s backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
return DataSource{Settings: models.CloudWatchSettings{}}, nil return DataSource{Settings: models.CloudWatchSettings{}}, nil
}) })
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{}, featuremgmt.WithFeatures()) executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
_, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{ _, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{
PluginContext: backend.PluginContext{DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}}, PluginContext: backend.PluginContext{DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}},
@ -358,7 +358,7 @@ func Test_executeStartQuery(t *testing.T) {
im := datasource.NewInstanceManager(func(ctx context.Context, s backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) { im := datasource.NewInstanceManager(func(ctx context.Context, s backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
return DataSource{Settings: models.CloudWatchSettings{}}, nil return DataSource{Settings: models.CloudWatchSettings{}}, nil
}) })
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{}, featuremgmt.WithFeatures()) executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
_, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{ _, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{
PluginContext: backend.PluginContext{DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}}, PluginContext: backend.PluginContext{DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}},
@ -384,9 +384,9 @@ func Test_executeStartQuery(t *testing.T) {
im := datasource.NewInstanceManager(func(ctx context.Context, s backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) { im := datasource.NewInstanceManager(func(ctx context.Context, s backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
return DataSource{Settings: models.CloudWatchSettings{}}, nil return DataSource{Settings: models.CloudWatchSettings{}}, nil
}) })
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{}, featuremgmt.WithFeatures(featuremgmt.FlagCloudWatchCrossAccountQuerying)) executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
_, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{ _, err := executor.QueryData(contextWithFeaturesEnabled(features.FlagCloudWatchCrossAccountQuerying), &backend.QueryDataRequest{
PluginContext: backend.PluginContext{DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}}, PluginContext: backend.PluginContext{DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}},
Queries: []backend.DataQuery{ Queries: []backend.DataQuery{
{ {
@ -420,9 +420,9 @@ func Test_executeStartQuery(t *testing.T) {
im := datasource.NewInstanceManager(func(ctx context.Context, s backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) { im := datasource.NewInstanceManager(func(ctx context.Context, s backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
return DataSource{Settings: models.CloudWatchSettings{}}, nil return DataSource{Settings: models.CloudWatchSettings{}}, nil
}) })
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{}, featuremgmt.WithFeatures(featuremgmt.FlagCloudWatchCrossAccountQuerying)) executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
_, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{ _, err := executor.QueryData(contextWithFeaturesEnabled(features.FlagCloudWatchCrossAccountQuerying), &backend.QueryDataRequest{
PluginContext: backend.PluginContext{DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}}, PluginContext: backend.PluginContext{DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}},
Queries: []backend.DataQuery{ Queries: []backend.DataQuery{
{ {
@ -456,7 +456,7 @@ func Test_executeStartQuery(t *testing.T) {
im := datasource.NewInstanceManager(func(ctx context.Context, s backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) { im := datasource.NewInstanceManager(func(ctx context.Context, s backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
return DataSource{Settings: models.CloudWatchSettings{}}, nil return DataSource{Settings: models.CloudWatchSettings{}}, nil
}) })
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{}, featuremgmt.WithFeatures()) executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
_, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{ _, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{
PluginContext: backend.PluginContext{DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}}, PluginContext: backend.PluginContext{DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}},
Queries: []backend.DataQuery{ Queries: []backend.DataQuery{
@ -491,7 +491,7 @@ func Test_executeStartQuery(t *testing.T) {
im := datasource.NewInstanceManager(func(ctx context.Context, s backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) { im := datasource.NewInstanceManager(func(ctx context.Context, s backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
return DataSource{Settings: models.CloudWatchSettings{}}, nil return DataSource{Settings: models.CloudWatchSettings{}}, nil
}) })
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{}, featuremgmt.WithFeatures()) executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
_, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{ _, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{
PluginContext: backend.PluginContext{DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}}, PluginContext: backend.PluginContext{DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}},
Queries: []backend.DataQuery{ Queries: []backend.DataQuery{
@ -525,8 +525,8 @@ func Test_executeStartQuery(t *testing.T) {
im := datasource.NewInstanceManager(func(ctx context.Context, s backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) { im := datasource.NewInstanceManager(func(ctx context.Context, s backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
return DataSource{Settings: models.CloudWatchSettings{}}, nil return DataSource{Settings: models.CloudWatchSettings{}}, nil
}) })
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{}, featuremgmt.WithFeatures(featuremgmt.FlagCloudWatchCrossAccountQuerying)) executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
_, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{ _, err := executor.QueryData(contextWithFeaturesEnabled(features.FlagCloudWatchCrossAccountQuerying), &backend.QueryDataRequest{
PluginContext: backend.PluginContext{DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}}, PluginContext: backend.PluginContext{DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}},
Queries: []backend.DataQuery{ Queries: []backend.DataQuery{
{ {
@ -596,7 +596,7 @@ func TestQuery_StopQuery(t *testing.T) {
To: time.Unix(1584700643, 0), To: time.Unix(1584700643, 0),
} }
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{}, featuremgmt.WithFeatures()) executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
resp, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{ resp, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{
PluginContext: backend.PluginContext{ PluginContext: backend.PluginContext{
DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}, DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{},
@ -686,7 +686,7 @@ func TestQuery_GetQueryResults(t *testing.T) {
return DataSource{Settings: models.CloudWatchSettings{}}, nil return DataSource{Settings: models.CloudWatchSettings{}}, nil
}) })
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{}, featuremgmt.WithFeatures()) executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
resp, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{ resp, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{
PluginContext: backend.PluginContext{ PluginContext: backend.PluginContext{
DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}, DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{},

View File

@ -16,7 +16,6 @@ import (
"github.com/grafana/grafana-plugin-sdk-go/backend/datasource" "github.com/grafana/grafana-plugin-sdk-go/backend/datasource"
"github.com/grafana/grafana-plugin-sdk-go/backend/instancemgmt" "github.com/grafana/grafana-plugin-sdk-go/backend/instancemgmt"
"github.com/grafana/grafana-plugin-sdk-go/data" "github.com/grafana/grafana-plugin-sdk-go/data"
"github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/models" "github.com/grafana/grafana/pkg/tsdb/cloudwatch/models"
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/utils" "github.com/grafana/grafana/pkg/tsdb/cloudwatch/utils"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
@ -41,7 +40,7 @@ func Test_executeSyncLogQuery(t *testing.T) {
return DataSource{Settings: models.CloudWatchSettings{}}, nil return DataSource{Settings: models.CloudWatchSettings{}}, nil
}) })
sess := fakeSessionCache{} sess := fakeSessionCache{}
executor := newExecutor(im, newTestConfig(), &sess, featuremgmt.WithFeatures()) executor := newExecutor(im, newTestConfig(), &sess)
_, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{ _, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{
Headers: map[string]string{headerFromAlert: "some value"}, Headers: map[string]string{headerFromAlert: "some value"},
@ -68,7 +67,7 @@ func Test_executeSyncLogQuery(t *testing.T) {
}) })
sess := fakeSessionCache{} sess := fakeSessionCache{}
executor := newExecutor(im, newTestConfig(), &sess, featuremgmt.WithFeatures()) executor := newExecutor(im, newTestConfig(), &sess)
_, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{ _, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{
Headers: map[string]string{headerFromAlert: "some value"}, Headers: map[string]string{headerFromAlert: "some value"},
PluginContext: backend.PluginContext{DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}}, PluginContext: backend.PluginContext{DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}},
@ -125,7 +124,7 @@ func Test_executeSyncLogQuery(t *testing.T) {
}) })
sess := fakeSessionCache{} sess := fakeSessionCache{}
executor := newExecutor(im, newTestConfig(), &sess, featuremgmt.WithFeatures()) executor := newExecutor(im, newTestConfig(), &sess)
_, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{ _, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{
Headers: tc.headers, Headers: tc.headers,
PluginContext: backend.PluginContext{DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}}, PluginContext: backend.PluginContext{DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}},
@ -168,7 +167,7 @@ func Test_executeSyncLogQuery(t *testing.T) {
}) })
sess := fakeSessionCache{} sess := fakeSessionCache{}
executor := newExecutor(im, newTestConfig(), &sess, featuremgmt.WithFeatures()) executor := newExecutor(im, newTestConfig(), &sess)
_, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{ _, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{
PluginContext: backend.PluginContext{DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}}, PluginContext: backend.PluginContext{DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}},
Queries: []backend.DataQuery{ Queries: []backend.DataQuery{
@ -207,7 +206,7 @@ func Test_executeSyncLogQuery_handles_RefId_from_input_queries(t *testing.T) {
im := datasource.NewInstanceManager(func(ctx context.Context, s backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) { im := datasource.NewInstanceManager(func(ctx context.Context, s backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
return DataSource{Settings: models.CloudWatchSettings{}}, nil return DataSource{Settings: models.CloudWatchSettings{}}, nil
}) })
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{}, featuremgmt.WithFeatures()) executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
res, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{ res, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{
Headers: map[string]string{headerFromAlert: "some value"}, Headers: map[string]string{headerFromAlert: "some value"},
@ -236,7 +235,7 @@ func Test_executeSyncLogQuery_handles_RefId_from_input_queries(t *testing.T) {
im := datasource.NewInstanceManager(func(ctx context.Context, s backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) { im := datasource.NewInstanceManager(func(ctx context.Context, s backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
return DataSource{Settings: models.CloudWatchSettings{}}, nil return DataSource{Settings: models.CloudWatchSettings{}}, nil
}) })
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{}, featuremgmt.WithFeatures()) executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
res, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{ res, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{
Headers: map[string]string{headerFromAlert: "some value"}, Headers: map[string]string{headerFromAlert: "some value"},
@ -305,7 +304,7 @@ func Test_executeSyncLogQuery_handles_RefId_from_input_queries(t *testing.T) {
im := datasource.NewInstanceManager(func(ctx context.Context, s backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) { im := datasource.NewInstanceManager(func(ctx context.Context, s backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
return DataSource{Settings: models.CloudWatchSettings{}}, nil return DataSource{Settings: models.CloudWatchSettings{}}, nil
}) })
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{}, featuremgmt.WithFeatures()) executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
res, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{ res, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{
Headers: map[string]string{headerFromAlert: "some value"}, Headers: map[string]string{headerFromAlert: "some value"},
@ -351,7 +350,7 @@ func Test_executeSyncLogQuery_handles_RefId_from_input_queries(t *testing.T) {
return DataSource{Settings: models.CloudWatchSettings{LogsTimeout: models.Duration{Duration: time.Millisecond}}}, nil return DataSource{Settings: models.CloudWatchSettings{LogsTimeout: models.Duration{Duration: time.Millisecond}}}, nil
}) })
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{}, featuremgmt.WithFeatures()) executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
_, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{ _, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{
Headers: map[string]string{headerFromAlert: "some value"}, Headers: map[string]string{headerFromAlert: "some value"},
@ -383,7 +382,7 @@ func Test_executeSyncLogQuery_handles_RefId_from_input_queries(t *testing.T) {
im := datasource.NewInstanceManager(func(ctx context.Context, s backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) { im := datasource.NewInstanceManager(func(ctx context.Context, s backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
return DataSource{Settings: models.CloudWatchSettings{}}, nil return DataSource{Settings: models.CloudWatchSettings{}}, nil
}) })
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{}, featuremgmt.WithFeatures()) executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
res, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{ res, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{
Headers: map[string]string{headerFromAlert: "some value"}, Headers: map[string]string{headerFromAlert: "some value"},

View File

@ -9,7 +9,6 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/models" "github.com/grafana/grafana/pkg/tsdb/cloudwatch/models"
) )
@ -27,7 +26,7 @@ func TestMetricDataInputBuilder(t *testing.T) {
for _, tc := range tests { for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) { t.Run(tc.name, func(t *testing.T) {
executor := newExecutor(nil, newTestConfig(), &fakeSessionCache{}, featuremgmt.WithFeatures()) executor := newExecutor(nil, newTestConfig(), &fakeSessionCache{})
query := getBaseQuery() query := getBaseQuery()
query.TimezoneUTCOffset = tc.timezoneUTCOffset query.TimezoneUTCOffset = tc.timezoneUTCOffset

View File

@ -4,7 +4,6 @@ import (
"testing" "testing"
"github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws"
"github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/models" "github.com/grafana/grafana/pkg/tsdb/cloudwatch/models"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@ -13,7 +12,7 @@ import (
func TestMetricDataQueryBuilder(t *testing.T) { func TestMetricDataQueryBuilder(t *testing.T) {
t.Run("buildMetricDataQuery", func(t *testing.T) { t.Run("buildMetricDataQuery", func(t *testing.T) {
t.Run("should use metric stat", func(t *testing.T) { t.Run("should use metric stat", func(t *testing.T) {
executor := newExecutor(nil, newTestConfig(), &fakeSessionCache{}, featuremgmt.WithFeatures()) executor := newExecutor(nil, newTestConfig(), &fakeSessionCache{})
query := getBaseQuery() query := getBaseQuery()
query.MetricEditorMode = models.MetricEditorModeBuilder query.MetricEditorMode = models.MetricEditorModeBuilder
query.MetricQueryType = models.MetricQueryTypeSearch query.MetricQueryType = models.MetricQueryTypeSearch
@ -25,7 +24,7 @@ func TestMetricDataQueryBuilder(t *testing.T) {
}) })
t.Run("should pass AccountId in metric stat query", func(t *testing.T) { t.Run("should pass AccountId in metric stat query", func(t *testing.T) {
executor := newExecutor(nil, newTestConfig(), &fakeSessionCache{}, featuremgmt.WithFeatures()) executor := newExecutor(nil, newTestConfig(), &fakeSessionCache{})
query := getBaseQuery() query := getBaseQuery()
query.MetricEditorMode = models.MetricEditorModeBuilder query.MetricEditorMode = models.MetricEditorModeBuilder
query.MetricQueryType = models.MetricQueryTypeSearch query.MetricQueryType = models.MetricQueryTypeSearch
@ -36,7 +35,7 @@ func TestMetricDataQueryBuilder(t *testing.T) {
}) })
t.Run("should leave AccountId in metric stat query", func(t *testing.T) { t.Run("should leave AccountId in metric stat query", func(t *testing.T) {
executor := newExecutor(nil, newTestConfig(), &fakeSessionCache{}, featuremgmt.WithFeatures()) executor := newExecutor(nil, newTestConfig(), &fakeSessionCache{})
query := getBaseQuery() query := getBaseQuery()
query.MetricEditorMode = models.MetricEditorModeBuilder query.MetricEditorMode = models.MetricEditorModeBuilder
query.MetricQueryType = models.MetricQueryTypeSearch query.MetricQueryType = models.MetricQueryTypeSearch
@ -46,7 +45,7 @@ func TestMetricDataQueryBuilder(t *testing.T) {
}) })
t.Run("should use custom built expression", func(t *testing.T) { t.Run("should use custom built expression", func(t *testing.T) {
executor := newExecutor(nil, newTestConfig(), &fakeSessionCache{}, featuremgmt.WithFeatures()) executor := newExecutor(nil, newTestConfig(), &fakeSessionCache{})
query := getBaseQuery() query := getBaseQuery()
query.MetricEditorMode = models.MetricEditorModeBuilder query.MetricEditorMode = models.MetricEditorModeBuilder
query.MetricQueryType = models.MetricQueryTypeSearch query.MetricQueryType = models.MetricQueryTypeSearch
@ -58,7 +57,7 @@ func TestMetricDataQueryBuilder(t *testing.T) {
}) })
t.Run("should use sql expression", func(t *testing.T) { t.Run("should use sql expression", func(t *testing.T) {
executor := newExecutor(nil, newTestConfig(), &fakeSessionCache{}, featuremgmt.WithFeatures()) executor := newExecutor(nil, newTestConfig(), &fakeSessionCache{})
query := getBaseQuery() query := getBaseQuery()
query.MetricEditorMode = models.MetricEditorModeRaw query.MetricEditorMode = models.MetricEditorModeRaw
query.MetricQueryType = models.MetricQueryTypeQuery query.MetricQueryType = models.MetricQueryTypeQuery
@ -70,7 +69,7 @@ func TestMetricDataQueryBuilder(t *testing.T) {
}) })
t.Run("should use user defined math expression", func(t *testing.T) { t.Run("should use user defined math expression", func(t *testing.T) {
executor := newExecutor(nil, newTestConfig(), &fakeSessionCache{}, featuremgmt.WithFeatures()) executor := newExecutor(nil, newTestConfig(), &fakeSessionCache{})
query := getBaseQuery() query := getBaseQuery()
query.MetricEditorMode = models.MetricEditorModeRaw query.MetricEditorMode = models.MetricEditorModeRaw
query.MetricQueryType = models.MetricQueryTypeSearch query.MetricQueryType = models.MetricQueryTypeSearch
@ -82,7 +81,7 @@ func TestMetricDataQueryBuilder(t *testing.T) {
}) })
t.Run("should set period in user defined expression", func(t *testing.T) { t.Run("should set period in user defined expression", func(t *testing.T) {
executor := newExecutor(nil, newTestConfig(), &fakeSessionCache{}, featuremgmt.WithFeatures()) executor := newExecutor(nil, newTestConfig(), &fakeSessionCache{})
query := getBaseQuery() query := getBaseQuery()
query.MetricEditorMode = models.MetricEditorModeRaw query.MetricEditorMode = models.MetricEditorModeRaw
query.MetricQueryType = models.MetricQueryTypeSearch query.MetricQueryType = models.MetricQueryTypeSearch
@ -96,7 +95,7 @@ func TestMetricDataQueryBuilder(t *testing.T) {
}) })
t.Run("should set label", func(t *testing.T) { t.Run("should set label", func(t *testing.T) {
executor := newExecutor(nil, newTestConfig(), &fakeSessionCache{}, featuremgmt.WithFeatures()) executor := newExecutor(nil, newTestConfig(), &fakeSessionCache{})
query := getBaseQuery() query := getBaseQuery()
query.Label = "some label" query.Label = "some label"
@ -108,7 +107,7 @@ func TestMetricDataQueryBuilder(t *testing.T) {
}) })
t.Run("should not set label for empty string query label", func(t *testing.T) { t.Run("should not set label for empty string query label", func(t *testing.T) {
executor := newExecutor(nil, newTestConfig(), &fakeSessionCache{}, featuremgmt.WithFeatures()) executor := newExecutor(nil, newTestConfig(), &fakeSessionCache{})
query := getBaseQuery() query := getBaseQuery()
query.Label = "" query.Label = ""
@ -119,7 +118,7 @@ func TestMetricDataQueryBuilder(t *testing.T) {
}) })
t.Run(`should not specify accountId when it is "all"`, func(t *testing.T) { t.Run(`should not specify accountId when it is "all"`, func(t *testing.T) {
executor := newExecutor(nil, newTestConfig(), &fakeSessionCache{}, featuremgmt.WithFeatures()) executor := newExecutor(nil, newTestConfig(), &fakeSessionCache{})
query := &models.CloudWatchQuery{ query := &models.CloudWatchQuery{
Namespace: "AWS/EC2", Namespace: "AWS/EC2",
MetricName: "CPUUtilization", MetricName: "CPUUtilization",
@ -137,7 +136,7 @@ func TestMetricDataQueryBuilder(t *testing.T) {
}) })
t.Run("should set accountId when it is specified", func(t *testing.T) { t.Run("should set accountId when it is specified", func(t *testing.T) {
executor := newExecutor(nil, newTestConfig(), &fakeSessionCache{}, featuremgmt.WithFeatures()) executor := newExecutor(nil, newTestConfig(), &fakeSessionCache{})
query := &models.CloudWatchQuery{ query := &models.CloudWatchQuery{
Namespace: "AWS/EC2", Namespace: "AWS/EC2",
MetricName: "CPUUtilization", MetricName: "CPUUtilization",

View File

@ -17,7 +17,6 @@ import (
"github.com/grafana/grafana-plugin-sdk-go/backend/datasource" "github.com/grafana/grafana-plugin-sdk-go/backend/datasource"
"github.com/grafana/grafana-plugin-sdk-go/backend/instancemgmt" "github.com/grafana/grafana-plugin-sdk-go/backend/instancemgmt"
"github.com/grafana/grafana-plugin-sdk-go/data" "github.com/grafana/grafana-plugin-sdk-go/data"
"github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/constants" "github.com/grafana/grafana/pkg/tsdb/cloudwatch/constants"
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/mocks" "github.com/grafana/grafana/pkg/tsdb/cloudwatch/mocks"
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/models" "github.com/grafana/grafana/pkg/tsdb/cloudwatch/models"
@ -51,7 +50,7 @@ func TestQuery_Regions(t *testing.T) {
return DataSource{Settings: models.CloudWatchSettings{AWSDatasourceSettings: awsds.AWSDatasourceSettings{Region: "us-east-2"}}}, nil return DataSource{Settings: models.CloudWatchSettings{AWSDatasourceSettings: awsds.AWSDatasourceSettings{Region: "us-east-2"}}}, nil
}) })
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{}, featuremgmt.WithFeatures()) executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
resp, err := executor.handleGetRegions( resp, err := executor.handleGetRegions(
context.Background(), context.Background(),
backend.PluginContext{ backend.PluginContext{
@ -110,7 +109,7 @@ func Test_handleGetRegions_regionCache(t *testing.T) {
t.Run("AWS only called once for multiple calls to handleGetRegions", func(t *testing.T) { t.Run("AWS only called once for multiple calls to handleGetRegions", func(t *testing.T) {
cli.On("DescribeRegionsWithContext", mock.Anything, mock.Anything).Return(&ec2.DescribeRegionsOutput{}, nil) cli.On("DescribeRegionsWithContext", mock.Anything, mock.Anything).Return(&ec2.DescribeRegionsOutput{}, nil)
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{}, featuremgmt.WithFeatures()) executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
_, err := executor.handleGetRegions( _, err := executor.handleGetRegions(
context.Background(), context.Background(),
backend.PluginContext{DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}}, nil) backend.PluginContext{DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}}, nil)
@ -166,7 +165,7 @@ func TestQuery_InstanceAttributes(t *testing.T) {
filterJson, err := json.Marshal(filterMap) filterJson, err := json.Marshal(filterMap)
require.NoError(t, err) require.NoError(t, err)
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{}, featuremgmt.WithFeatures()) executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
resp, err := executor.handleGetEc2InstanceAttribute( resp, err := executor.handleGetEc2InstanceAttribute(
context.Background(), context.Background(),
backend.PluginContext{ backend.PluginContext{
@ -244,7 +243,7 @@ func TestQuery_EBSVolumeIDs(t *testing.T) {
return DataSource{Settings: models.CloudWatchSettings{}}, nil return DataSource{Settings: models.CloudWatchSettings{}}, nil
}) })
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{}, featuremgmt.WithFeatures()) executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
resp, err := executor.handleGetEbsVolumeIds( resp, err := executor.handleGetEbsVolumeIds(
context.Background(), context.Background(),
backend.PluginContext{ backend.PluginContext{
@ -311,7 +310,7 @@ func TestQuery_ResourceARNs(t *testing.T) {
tagJson, err := json.Marshal(tagMap) tagJson, err := json.Marshal(tagMap)
require.NoError(t, err) require.NoError(t, err)
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{}, featuremgmt.WithFeatures()) executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
resp, err := executor.handleGetResourceArns( resp, err := executor.handleGetResourceArns(
context.Background(), context.Background(),
backend.PluginContext{ backend.PluginContext{

View File

@ -11,7 +11,6 @@ import (
"github.com/aws/aws-sdk-go/service/oam" "github.com/aws/aws-sdk-go/service/oam"
"github.com/grafana/grafana-plugin-sdk-go/backend" "github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana/pkg/infra/log" "github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/models/resources" "github.com/grafana/grafana/pkg/tsdb/cloudwatch/models/resources"
) )
@ -25,7 +24,6 @@ type RequestContext struct {
OAMAPIProvider OAMAPIProvider OAMAPIProvider OAMAPIProvider
EC2APIProvider EC2APIProvider EC2APIProvider EC2APIProvider
Settings CloudWatchSettings Settings CloudWatchSettings
Features featuremgmt.FeatureToggles
Logger log.Logger Logger log.Logger
} }

View File

@ -10,7 +10,6 @@ import (
"github.com/grafana/grafana-plugin-sdk-go/backend" "github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana-plugin-sdk-go/backend/resource/httpadapter" "github.com/grafana/grafana-plugin-sdk-go/backend/resource/httpadapter"
"github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/routes" "github.com/grafana/grafana/pkg/tsdb/cloudwatch/routes"
) )
@ -27,14 +26,7 @@ func (e *cloudWatchExecutor) newResourceMux() *http.ServeMux {
mux.HandleFunc("/namespaces", routes.ResourceRequestMiddleware(routes.NamespacesHandler, logger, e.getRequestContext)) mux.HandleFunc("/namespaces", routes.ResourceRequestMiddleware(routes.NamespacesHandler, logger, e.getRequestContext))
mux.HandleFunc("/log-group-fields", routes.ResourceRequestMiddleware(routes.LogGroupFieldsHandler, logger, e.getRequestContext)) mux.HandleFunc("/log-group-fields", routes.ResourceRequestMiddleware(routes.LogGroupFieldsHandler, logger, e.getRequestContext))
mux.HandleFunc("/external-id", routes.ResourceRequestMiddleware(routes.ExternalIdHandler, logger, e.getRequestContext)) mux.HandleFunc("/external-id", routes.ResourceRequestMiddleware(routes.ExternalIdHandler, logger, e.getRequestContext))
// feature is enabled by default, just putting behind a feature flag in case of unexpected bugs
if e.features.IsEnabledGlobally(featuremgmt.FlagCloudwatchNewRegionsHandler) {
mux.HandleFunc("/regions", routes.ResourceRequestMiddleware(routes.RegionsHandler, logger, e.getRequestContext)) mux.HandleFunc("/regions", routes.ResourceRequestMiddleware(routes.RegionsHandler, logger, e.getRequestContext))
} else {
mux.HandleFunc("/regions", handleResourceReq(e.handleGetRegions))
}
// remove this once AWS's Cross Account Observability is supported in GovCloud // remove this once AWS's Cross Account Observability is supported in GovCloud
mux.HandleFunc("/legacy-log-groups", handleResourceReq(e.handleGetLogGroups)) mux.HandleFunc("/legacy-log-groups", handleResourceReq(e.handleGetLogGroups))

View File

@ -11,16 +11,14 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock" "github.com/stretchr/testify/mock"
"github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/mocks" "github.com/grafana/grafana/pkg/tsdb/cloudwatch/mocks"
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/models" "github.com/grafana/grafana/pkg/tsdb/cloudwatch/models"
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/models/resources" "github.com/grafana/grafana/pkg/tsdb/cloudwatch/models/resources"
) )
func TestLogGroupFieldsRoute(t *testing.T) { func TestLogGroupFieldsRoute(t *testing.T) {
mockFeatures := featuremgmt.WithFeatures()
reqCtxFunc := func(_ context.Context, pluginCtx backend.PluginContext, region string) (reqCtx models.RequestContext, err error) { reqCtxFunc := func(_ context.Context, pluginCtx backend.PluginContext, region string) (reqCtx models.RequestContext, err error) {
return models.RequestContext{Features: mockFeatures}, err return models.RequestContext{}, err
} }
t.Run("returns 400 if an invalid LogGroupFieldsRequest is used", func(t *testing.T) { t.Run("returns 400 if an invalid LogGroupFieldsRequest is used", func(t *testing.T) {
rr := httptest.NewRecorder() rr := httptest.NewRecorder()

View File

@ -7,8 +7,7 @@ import (
"net/url" "net/url"
"github.com/grafana/grafana-plugin-sdk-go/backend" "github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/features"
"github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/models" "github.com/grafana/grafana/pkg/tsdb/cloudwatch/models"
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/models/resources" "github.com/grafana/grafana/pkg/tsdb/cloudwatch/models/resources"
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/services" "github.com/grafana/grafana/pkg/tsdb/cloudwatch/services"
@ -47,5 +46,5 @@ var newLogGroupsService = func(ctx context.Context, pluginCtx backend.PluginCont
return nil, err return nil, err
} }
return services.NewLogGroupsService(reqCtx.LogsAPIProvider, reqCtx.Features.IsEnabled(ctx, featuremgmt.FlagCloudWatchCrossAccountQuerying)), nil return services.NewLogGroupsService(reqCtx.LogsAPIProvider, features.IsEnabled(ctx, features.FlagCloudWatchCrossAccountQuerying)), nil
} }

View File

@ -11,7 +11,6 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock" "github.com/stretchr/testify/mock"
"github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/mocks" "github.com/grafana/grafana/pkg/tsdb/cloudwatch/mocks"
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/models" "github.com/grafana/grafana/pkg/tsdb/cloudwatch/models"
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/models/resources" "github.com/grafana/grafana/pkg/tsdb/cloudwatch/models/resources"
@ -24,9 +23,8 @@ func TestLogGroupsRoute(t *testing.T) {
newLogGroupsService = origLogGroupsService newLogGroupsService = origLogGroupsService
}) })
mockFeatures := featuremgmt.WithFeatures()
reqCtxFunc := func(_ context.Context, pluginCtx backend.PluginContext, region string) (reqCtx models.RequestContext, err error) { reqCtxFunc := func(_ context.Context, pluginCtx backend.PluginContext, region string) (reqCtx models.RequestContext, err error) {
return models.RequestContext{Features: mockFeatures}, err return models.RequestContext{}, err
} }
t.Run("successfully returns 1 log group with account id", func(t *testing.T) { t.Run("successfully returns 1 log group with account id", func(t *testing.T) {

View File

@ -2,6 +2,7 @@ package cloudwatch
import ( import (
"context" "context"
"strings"
"github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/request" "github.com/aws/aws-sdk-go/aws/request"
@ -16,6 +17,7 @@ import (
"github.com/aws/aws-sdk-go/service/resourcegroupstaggingapi/resourcegroupstaggingapiiface" "github.com/aws/aws-sdk-go/service/resourcegroupstaggingapi/resourcegroupstaggingapiiface"
"github.com/grafana/grafana-aws-sdk/pkg/awsds" "github.com/grafana/grafana-aws-sdk/pkg/awsds"
"github.com/grafana/grafana-plugin-sdk-go/backend" "github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana-plugin-sdk-go/experimental/featuretoggles"
"github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/setting"
"github.com/stretchr/testify/mock" "github.com/stretchr/testify/mock"
) )
@ -270,3 +272,9 @@ func (e fakeAWSError) Code() string {
func (e fakeAWSError) Message() string { func (e fakeAWSError) Message() string {
return e.message return e.message
} }
func contextWithFeaturesEnabled(enabled ...string) context.Context {
featureString := strings.Join(enabled, ",")
cfg := backend.NewGrafanaCfg(map[string]string{featuretoggles.EnabledFeatures: featureString})
return backend.WithGrafanaConfig(context.Background(), cfg)
}

View File

@ -9,7 +9,7 @@ import (
"golang.org/x/sync/errgroup" "golang.org/x/sync/errgroup"
"github.com/grafana/grafana/pkg/infra/log" "github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/services/featuremgmt" "github.com/grafana/grafana/pkg/tsdb/cloudwatch/features"
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/models" "github.com/grafana/grafana/pkg/tsdb/cloudwatch/models"
) )
@ -38,7 +38,7 @@ func (e *cloudWatchExecutor) executeTimeSeriesQuery(ctx context.Context, logger
} }
requestQueries, err := models.ParseMetricDataQueries(req.Queries, startTime, endTime, instance.Settings.Region, logger, requestQueries, err := models.ParseMetricDataQueries(req.Queries, startTime, endTime, instance.Settings.Region, logger,
e.features.IsEnabled(ctx, featuremgmt.FlagCloudWatchCrossAccountQuerying)) features.IsEnabled(ctx, features.FlagCloudWatchCrossAccountQuerying))
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -61,7 +61,7 @@ func (e *cloudWatchExecutor) executeTimeSeriesQuery(ctx context.Context, logger
region := r region := r
batches := [][]*models.CloudWatchQuery{regionQueries} batches := [][]*models.CloudWatchQuery{regionQueries}
if e.features.IsEnabled(ctx, featuremgmt.FlagCloudWatchBatchQueries) { if features.IsEnabled(ctx, features.FlagCloudWatchBatchQueries) {
batches = getMetricQueryBatches(regionQueries, logger) batches = getMetricQueryBatches(regionQueries, logger)
} }
@ -96,7 +96,7 @@ func (e *cloudWatchExecutor) executeTimeSeriesQuery(ctx context.Context, logger
return err return err
} }
if e.features.IsEnabled(ctx, featuremgmt.FlagCloudWatchWildCardDimensionValues) { if features.IsEnabled(ctx, features.FlagCloudWatchWildCardDimensionValues) {
requestQueries, err = e.getDimensionValuesForWildcards(ctx, req.PluginContext, region, client, requestQueries, instance.tagValueCache, logger) requestQueries, err = e.getDimensionValuesForWildcards(ctx, req.PluginContext, region, client, requestQueries, instance.tagValueCache, logger)
if err != nil { if err != nil {
return err return err

View File

@ -16,7 +16,7 @@ import (
"github.com/grafana/grafana-plugin-sdk-go/backend/instancemgmt" "github.com/grafana/grafana-plugin-sdk-go/backend/instancemgmt"
"github.com/stretchr/testify/mock" "github.com/stretchr/testify/mock"
"github.com/grafana/grafana/pkg/services/featuremgmt" "github.com/grafana/grafana/pkg/tsdb/cloudwatch/features"
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/kinds/dataquery" "github.com/grafana/grafana/pkg/tsdb/cloudwatch/kinds/dataquery"
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/mocks" "github.com/grafana/grafana/pkg/tsdb/cloudwatch/mocks"
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/models" "github.com/grafana/grafana/pkg/tsdb/cloudwatch/models"
@ -26,7 +26,7 @@ import (
) )
func TestTimeSeriesQuery(t *testing.T) { func TestTimeSeriesQuery(t *testing.T) {
executor := newExecutor(nil, newTestConfig(), &fakeSessionCache{}, featuremgmt.WithFeatures()) executor := newExecutor(nil, newTestConfig(), &fakeSessionCache{})
now := time.Now() now := time.Now()
origNewCWClient := NewCWClient origNewCWClient := NewCWClient
@ -54,7 +54,7 @@ func TestTimeSeriesQuery(t *testing.T) {
return DataSource{Settings: models.CloudWatchSettings{}}, nil return DataSource{Settings: models.CloudWatchSettings{}}, nil
}) })
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{}, featuremgmt.WithFeatures()) executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
resp, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{ resp, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{
PluginContext: backend.PluginContext{ PluginContext: backend.PluginContext{
DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}, DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{},
@ -160,7 +160,7 @@ func Test_executeTimeSeriesQuery_getCWClient_is_called_once_per_region_and_GetMe
mockMetricClient = mocks.MetricsAPI{} mockMetricClient = mocks.MetricsAPI{}
mockMetricClient.On("GetMetricDataWithContext", mock.Anything, mock.Anything, mock.Anything).Return(nil, nil) mockMetricClient.On("GetMetricDataWithContext", mock.Anything, mock.Anything, mock.Anything).Return(nil, nil)
executor := newExecutor(im, newTestConfig(), mockSessionCache, featuremgmt.WithFeatures()) executor := newExecutor(im, newTestConfig(), mockSessionCache)
_, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{ _, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{
PluginContext: backend.PluginContext{ PluginContext: backend.PluginContext{
DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}, DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{},
@ -211,7 +211,7 @@ func Test_executeTimeSeriesQuery_getCWClient_is_called_once_per_region_and_GetMe
mockMetricClient = mocks.MetricsAPI{} mockMetricClient = mocks.MetricsAPI{}
mockMetricClient.On("GetMetricDataWithContext", mock.Anything, mock.Anything, mock.Anything).Return(nil, nil) mockMetricClient.On("GetMetricDataWithContext", mock.Anything, mock.Anything, mock.Anything).Return(nil, nil)
executor := newExecutor(im, newTestConfig(), sessionCache, featuremgmt.WithFeatures()) executor := newExecutor(im, newTestConfig(), sessionCache)
_, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{ _, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{
PluginContext: backend.PluginContext{ PluginContext: backend.PluginContext{
DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}, DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{},
@ -344,7 +344,7 @@ func Test_QueryData_timeSeriesQuery_GetMetricDataWithContext(t *testing.T) {
t.Run("passes query label as GetMetricData label", func(t *testing.T) { t.Run("passes query label as GetMetricData label", func(t *testing.T) {
api = mocks.MetricsAPI{} api = mocks.MetricsAPI{}
api.On("GetMetricDataWithContext", mock.Anything, mock.Anything, mock.Anything).Return(&cloudwatch.GetMetricDataOutput{}, nil) api.On("GetMetricDataWithContext", mock.Anything, mock.Anything, mock.Anything).Return(&cloudwatch.GetMetricDataOutput{}, nil)
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{}, featuremgmt.WithFeatures()) executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
query := newTestQuery(t, queryParameters{ query := newTestQuery(t, queryParameters{
Label: aws.String("${PROP('Period')} some words ${PROP('Dim.InstanceId')}"), Label: aws.String("${PROP('Period')} some words ${PROP('Dim.InstanceId')}"),
}) })
@ -383,7 +383,7 @@ func Test_QueryData_timeSeriesQuery_GetMetricDataWithContext(t *testing.T) {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
api = mocks.MetricsAPI{} api = mocks.MetricsAPI{}
api.On("GetMetricDataWithContext", mock.Anything, mock.Anything, mock.Anything).Return(&cloudwatch.GetMetricDataOutput{}, nil) api.On("GetMetricDataWithContext", mock.Anything, mock.Anything, mock.Anything).Return(&cloudwatch.GetMetricDataOutput{}, nil)
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{}, featuremgmt.WithFeatures()) executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
_, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{ _, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{
PluginContext: backend.PluginContext{DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}}, PluginContext: backend.PluginContext{DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}},
@ -436,7 +436,7 @@ func Test_QueryData_response_data_frame_name_is_always_response_label(t *testing
im := datasource.NewInstanceManager(func(ctx context.Context, s backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) { im := datasource.NewInstanceManager(func(ctx context.Context, s backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
return DataSource{Settings: models.CloudWatchSettings{}}, nil return DataSource{Settings: models.CloudWatchSettings{}}, nil
}) })
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{}, featuremgmt.WithFeatures()) executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
t.Run("where user defines search expression", func(t *testing.T) { t.Run("where user defines search expression", func(t *testing.T) {
query := newTestQuery(t, queryParameters{ query := newTestQuery(t, queryParameters{
@ -595,9 +595,9 @@ func TestTimeSeriesQuery_CrossAccountQuerying(t *testing.T) {
t.Run("should call GetMetricDataInput with AccountId nil when no AccountId is provided", func(t *testing.T) { t.Run("should call GetMetricDataInput with AccountId nil when no AccountId is provided", func(t *testing.T) {
api = mocks.MetricsAPI{} api = mocks.MetricsAPI{}
api.On("GetMetricDataWithContext", mock.Anything, mock.Anything, mock.Anything).Return(&cloudwatch.GetMetricDataOutput{}, nil) api.On("GetMetricDataWithContext", mock.Anything, mock.Anything, mock.Anything).Return(&cloudwatch.GetMetricDataOutput{}, nil)
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{}, featuremgmt.WithFeatures(featuremgmt.FlagCloudWatchCrossAccountQuerying)) executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
_, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{ _, err := executor.QueryData(contextWithFeaturesEnabled(features.FlagCloudWatchCrossAccountQuerying), &backend.QueryDataRequest{
PluginContext: backend.PluginContext{ PluginContext: backend.PluginContext{
DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}, DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{},
}, },
@ -636,7 +636,7 @@ func TestTimeSeriesQuery_CrossAccountQuerying(t *testing.T) {
t.Run("should call GetMetricDataInput with AccountId nil when feature flag is false", func(t *testing.T) { t.Run("should call GetMetricDataInput with AccountId nil when feature flag is false", func(t *testing.T) {
api = mocks.MetricsAPI{} api = mocks.MetricsAPI{}
api.On("GetMetricDataWithContext", mock.Anything, mock.Anything, mock.Anything).Return(&cloudwatch.GetMetricDataOutput{}, nil) api.On("GetMetricDataWithContext", mock.Anything, mock.Anything, mock.Anything).Return(&cloudwatch.GetMetricDataOutput{}, nil)
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{}, featuremgmt.WithFeatures()) executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
_, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{ _, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{
PluginContext: backend.PluginContext{ PluginContext: backend.PluginContext{
DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}, DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{},
@ -677,8 +677,8 @@ func TestTimeSeriesQuery_CrossAccountQuerying(t *testing.T) {
t.Run("should call GetMetricDataInput with AccountId in a MetricStat query", func(t *testing.T) { t.Run("should call GetMetricDataInput with AccountId in a MetricStat query", func(t *testing.T) {
api = mocks.MetricsAPI{} api = mocks.MetricsAPI{}
api.On("GetMetricDataWithContext", mock.Anything, mock.Anything, mock.Anything).Return(&cloudwatch.GetMetricDataOutput{}, nil) api.On("GetMetricDataWithContext", mock.Anything, mock.Anything, mock.Anything).Return(&cloudwatch.GetMetricDataOutput{}, nil)
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{}, featuremgmt.WithFeatures(featuremgmt.FlagCloudWatchCrossAccountQuerying)) executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
_, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{ _, err := executor.QueryData(contextWithFeaturesEnabled(features.FlagCloudWatchCrossAccountQuerying), &backend.QueryDataRequest{
PluginContext: backend.PluginContext{ PluginContext: backend.PluginContext{
DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}, DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{},
}, },
@ -718,8 +718,8 @@ func TestTimeSeriesQuery_CrossAccountQuerying(t *testing.T) {
t.Run("should GetMetricDataInput with AccountId in an inferred search expression query", func(t *testing.T) { t.Run("should GetMetricDataInput with AccountId in an inferred search expression query", func(t *testing.T) {
api = mocks.MetricsAPI{} api = mocks.MetricsAPI{}
api.On("GetMetricDataWithContext", mock.Anything, mock.Anything, mock.Anything).Return(&cloudwatch.GetMetricDataOutput{}, nil) api.On("GetMetricDataWithContext", mock.Anything, mock.Anything, mock.Anything).Return(&cloudwatch.GetMetricDataOutput{}, nil)
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{}, featuremgmt.WithFeatures(featuremgmt.FlagCloudWatchCrossAccountQuerying)) executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
_, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{ _, err := executor.QueryData(contextWithFeaturesEnabled(features.FlagCloudWatchCrossAccountQuerying), &backend.QueryDataRequest{
PluginContext: backend.PluginContext{ PluginContext: backend.PluginContext{
DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}, DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{},
}, },

View File

@ -1,5 +1,3 @@
import { config } from '@grafana/runtime';
import { setupMockedResourcesAPI } from '../__mocks__/ResourcesAPI'; import { setupMockedResourcesAPI } from '../__mocks__/ResourcesAPI';
describe('ResourcesAPI', () => { describe('ResourcesAPI', () => {
@ -121,63 +119,8 @@ describe('ResourcesAPI', () => {
}); });
}); });
const originalFeatureToggleValue = config.featureToggles.cloudwatchNewRegionsHandler;
describe('getRegions', () => { describe('getRegions', () => {
afterEach(() => { it('should always return regions as an array of options', async () => {
config.featureToggles.cloudwatchNewRegionsHandler = originalFeatureToggleValue;
});
it('should return regions as an array of options when using legacy regions route', async () => {
config.featureToggles.cloudwatchNewRegionsHandler = false;
const response = Promise.resolve([
{
text: 'US East (Ohio)',
value: 'us-east-2',
label: 'US East (Ohio)',
},
{
text: 'US East (N. Virginia)',
value: 'us-east-1',
label: 'US East (N. Virginia)',
},
{
text: 'US West (N. California)',
value: 'us-west-1',
label: 'US West (N. California)',
},
]);
const { api } = setupMockedResourcesAPI({ response });
const expectedRegions = [
{
text: 'default',
value: 'default',
label: 'default',
},
{
text: 'US East (Ohio)',
value: 'us-east-2',
label: 'US East (Ohio)',
},
{
text: 'US East (N. Virginia)',
value: 'us-east-1',
label: 'US East (N. Virginia)',
},
{
text: 'US West (N. California)',
value: 'us-west-1',
label: 'US West (N. California)',
},
];
const regions = await api.getRegions();
expect(regions).toEqual(expectedRegions);
});
it('should return regions as an array of options when using new regions route', async () => {
config.featureToggles.cloudwatchNewRegionsHandler = true;
const response = Promise.resolve([ const response = Promise.resolve([
{ {
value: { value: {

View File

@ -1,7 +1,7 @@
import { memoize } from 'lodash'; import { memoize } from 'lodash';
import { DataSourceInstanceSettings, SelectableValue } from '@grafana/data'; import { DataSourceInstanceSettings, SelectableValue } from '@grafana/data';
import { getBackendSrv, config, TemplateSrv } from '@grafana/runtime'; import { getBackendSrv, TemplateSrv } from '@grafana/runtime';
import { CloudWatchRequest } from '../query-runner/CloudWatchRequest'; import { CloudWatchRequest } from '../query-runner/CloudWatchRequest';
import { CloudWatchJsonData, LogGroupField, MultiFilters } from '../types'; import { CloudWatchJsonData, LogGroupField, MultiFilters } from '../types';
@ -52,12 +52,6 @@ export class ResourcesAPI extends CloudWatchRequest {
} }
getRegions(): Promise<SelectableResourceValue[]> { getRegions(): Promise<SelectableResourceValue[]> {
if (!config.featureToggles.cloudwatchNewRegionsHandler) {
return this.memoizedGetRequest<SelectableResourceValue[]>('regions').then((regions) => [
{ label: 'default', value: 'default', text: 'default' },
...regions.filter((r) => r.value),
]);
}
return this.memoizedGetRequest<Array<ResourceResponse<RegionResponse>>>('regions').then((regions) => { return this.memoizedGetRequest<Array<ResourceResponse<RegionResponse>>>('regions').then((regions) => {
return [ return [
{ label: 'default', value: 'default', text: 'default' }, { label: 'default', value: 'default', text: 'default' },