CloudWatch: Remove dependencies on grafana/pkg/setting (#81208)

This commit is contained in:
Isabella Siu
2024-02-05 13:59:32 -05:00
committed by GitHub
parent 2ab7d3c725
commit 81da3ff753
28 changed files with 440 additions and 214 deletions

View File

@@ -874,6 +874,14 @@ list_metrics_page_limit = 500
# Experimental, for use in Grafana Cloud only. Please do not set.
external_id =
# Sets the expiry duration of an assumed role.
# This setting should be expressed as a duration. Examples: 6h (hours), 10d (days), 2w (weeks), 1M (month).
session_duration = "15m"
# Set the plugins that will receive AWS settings for each request (via plugin context)
# By default this will include all Grafana Labs owned AWS plugins, or those that make use of AWS settings (ElasticSearch, Prometheus).
forward_settings_to_plugins = cloudwatch, grafana-athena-datasource, grafana-redshift-datasource, grafana-x-ray-datasource, grafana-timestream-datasource, grafana-iot-sitewise-datasource, grafana-iot-twinmaker-app, grafana-opensearch-datasource, aws-datasource-provisioner, elasticsearch, prometheus
#################################### Azure ###############################
[azure]
# Azure cloud environment where Grafana is hosted

View File

@@ -808,6 +808,14 @@
# Experimental, for use in Grafana Cloud only. Please do not set.
; external_id =
# Sets the expiry duration of an assumed role.
# This setting should be expressed as a duration. Examples: 6h (hours), 10d (days), 2w (weeks), 1M (month).
; session_duration = "15m"
# Set the plugins that will receive AWS settings for each request (via plugin context)
# By default this will include all Grafana Labs owned AWS plugins, or those that make use of AWS settings (ElasticSearch, Prometheus).
; forward_settings_to_plugins = cloudwatch, grafana-athena-datasource, grafana-redshift-datasource, grafana-x-ray-datasource, grafana-timestream-datasource, grafana-iot-sitewise-datasource, grafana-iot-twinmaker-app, grafana-opensearch-datasource, aws-datasource-provisioner, elasticsearch, prometheus
#################################### Azure ###############################
[azure]
# Azure cloud environment where Grafana is hosted

15
go.mod
View File

@@ -61,7 +61,7 @@ require (
github.com/gorilla/websocket v1.5.0 // @grafana/grafana-app-platform-squad
github.com/grafana/alerting v0.0.0-20240123184432-1d58deb6074c // @grafana/alerting-squad-backend
github.com/grafana/cuetsy v0.1.11 // @grafana/grafana-as-code
github.com/grafana/grafana-aws-sdk v0.19.1 // @grafana/aws-datasources
github.com/grafana/grafana-aws-sdk v0.23.1 // @grafana/aws-datasources
github.com/grafana/grafana-azure-sdk-go v1.12.0 // @grafana/partner-datasources
github.com/grafana/grafana-plugin-sdk-go v0.206.0 // @grafana/plugins-platform-backend
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // @grafana/backend-platform
@@ -258,7 +258,7 @@ require (
github.com/dave/dst v0.27.2 // @grafana/grafana-as-code
github.com/go-jose/go-jose/v3 v3.0.1 // @grafana/grafana-authnz-team
github.com/grafana/dataplane/examples v0.0.1 // @grafana/observability-metrics
github.com/grafana/dataplane/sdata v0.0.6 // @grafana/observability-metrics
github.com/grafana/dataplane/sdata v0.0.7 // @grafana/observability-metrics
github.com/grafana/kindsys v0.0.0-20230508162304-452481b63482 // @grafana/grafana-as-code
github.com/grafana/tempo v1.5.1-0.20230524121406-1dc1bfe7085b // @grafana/observability-traces-and-profiling
github.com/grafana/thema v0.0.0-20230712153715-375c1b45f3ed // @grafana/grafana-as-code
@@ -344,7 +344,6 @@ require (
github.com/google/s2a-go v0.1.7 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
github.com/grafana/regexp v0.0.0-20221123153739-15dc172cd2db // indirect
github.com/grafana/sqlds/v2 v2.3.10 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-immutable-radix v1.3.1 // indirect
github.com/hashicorp/go-retryablehttp v0.7.2 // indirect
@@ -483,6 +482,16 @@ require (
require k8s.io/code-generator v0.29.1 // @grafana/grafana-app-platform-squad
require (
github.com/grafana/sqlds/v3 v3.2.0 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mithrandie/csvq v1.17.10 // indirect
github.com/mithrandie/csvq-driver v1.6.8 // indirect
github.com/mithrandie/go-file/v2 v2.1.0 // indirect
github.com/mithrandie/go-text v1.5.4 // indirect
github.com/mithrandie/ternary v1.1.1 // indirect
)
// Use fork of crewjam/saml with fixes for some issues until changes get merged into upstream
replace github.com/crewjam/saml => github.com/grafana/saml v0.4.15-0.20231025143828-a6c0e9b86a4c

24
go.sum
View File

@@ -1826,14 +1826,14 @@ github.com/grafana/cuetsy v0.1.11 h1:I3IwBhF+UaQxRM79HnImtrAn8REGdb5M3+C4QrYHoWk
github.com/grafana/cuetsy v0.1.11/go.mod h1:Ix97+CPD8ws9oSSxR3/Lf4ahU1I4Np83kjJmDVnLZvc=
github.com/grafana/dataplane/examples v0.0.1 h1:K9M5glueWyLoL4//H+EtTQq16lXuHLmOhb6DjSCahzA=
github.com/grafana/dataplane/examples v0.0.1/go.mod h1:h5YwY8s407/17XF5/dS8XrUtsTVV2RnuW8+m1Mp46mg=
github.com/grafana/dataplane/sdata v0.0.6 h1:Ejlj8d1Hvy/uDLeI4sOvL34Y8WLlVDd9iN270F+8aTw=
github.com/grafana/dataplane/sdata v0.0.6/go.mod h1:Jvs5ddpGmn6vcxT7tCTWAZ1mgi4sbcdFt9utQx5uMAU=
github.com/grafana/dataplane/sdata v0.0.7 h1:CImITypIyS1jxijCR6xqKx71JnYAxcwpH9ChK0gH164=
github.com/grafana/dataplane/sdata v0.0.7/go.mod h1:Jvs5ddpGmn6vcxT7tCTWAZ1mgi4sbcdFt9utQx5uMAU=
github.com/grafana/dskit v0.0.0-20240104111617-ea101a3b86eb h1:AWE6+kvtE18HP+lRWNUCyvymyrFSXs6TcS2vXIXGIuw=
github.com/grafana/dskit v0.0.0-20240104111617-ea101a3b86eb/go.mod h1:kkWM4WUV230bNG3urVRWPBnSJHs64y/0RmWjftnnn0c=
github.com/grafana/gofpdf v0.0.0-20231002120153-857cc45be447 h1:jxJJ5z0GxqhWFbQUsys3BHG8jnmniJ2Q74tXAG1NaDo=
github.com/grafana/gofpdf v0.0.0-20231002120153-857cc45be447/go.mod h1:IxsY6mns6Q5sAnWcrptrgUrSglTZJXH/kXr9nbpb/9I=
github.com/grafana/grafana-aws-sdk v0.19.1 h1:5GBiOv2AgdyjwlgAX+dtgPtXU4FgMTD9rfQUPQseEpQ=
github.com/grafana/grafana-aws-sdk v0.19.1/go.mod h1:ntq2NDH12Y2Fkbc6fozpF8kYsJM9k6KNr+Xfo5w3/iM=
github.com/grafana/grafana-aws-sdk v0.23.1 h1:YP6DqzB36fp8fXno0r+X9BxNB3apNfJnQxu8tdhYMH8=
github.com/grafana/grafana-aws-sdk v0.23.1/go.mod h1:iTbW395xv26qy6L17SjtZlVwxQTIZbmupBTe0sPHv7k=
github.com/grafana/grafana-azure-sdk-go v1.11.0 h1:nc6MgOZ5fIaxvBfZjYU5rSqB4zaD7rlU8BqnGcXZtWk=
github.com/grafana/grafana-azure-sdk-go v1.11.0/go.mod h1:5a3FuG2lEsYNop9HDNgTO1bx4ExCgsjvrFhpuqolYAU=
github.com/grafana/grafana-azure-sdk-go v1.12.0 h1:q71M2QxMlBqRZOXc5mFAycJWuZqQ3hPTzVEo1r3CUTY=
@@ -1842,7 +1842,6 @@ github.com/grafana/grafana-google-sdk-go v0.1.0 h1:LKGY8z2DSxKjYfr2flZsWgTRTZ6HG
github.com/grafana/grafana-google-sdk-go v0.1.0/go.mod h1:Vo2TKWfDVmNTELBUM+3lkrZvFtBws0qSZdXhQxRdJrE=
github.com/grafana/grafana-openapi-client-go v0.0.0-20231213163343-bd475d63fb79 h1:r+mU5bGMzcXCRVAuOrTn54S80qbfVkvTdUJZfSfTNbs=
github.com/grafana/grafana-openapi-client-go v0.0.0-20231213163343-bd475d63fb79/go.mod h1:wc6Hbh3K2TgCUSfBC/BOzabItujtHMESZeFk5ZhdxhQ=
github.com/grafana/grafana-plugin-sdk-go v0.94.0/go.mod h1:3VXz4nCv6wH5SfgB3mlW39s+c+LetqSCjFj7xxPC5+M=
github.com/grafana/grafana-plugin-sdk-go v0.114.0/go.mod h1:D7x3ah+1d4phNXpbnOaxa/osSaZlwh9/ZUnGGzegRbk=
github.com/grafana/grafana-plugin-sdk-go v0.206.0 h1:DQK2M07/q0t7wqcJBSw6O/FQJZC1tm24uzGfHbA71+A=
github.com/grafana/grafana-plugin-sdk-go v0.206.0/go.mod h1:MetVbF3bGwmUvxulWsl0SskJFUq3+ZGnyjDH0dQ4sSg=
@@ -1859,8 +1858,8 @@ github.com/grafana/regexp v0.0.0-20221123153739-15dc172cd2db h1:7aN5cccjIqCLTzed
github.com/grafana/regexp v0.0.0-20221123153739-15dc172cd2db/go.mod h1:M5qHK+eWfAv8VR/265dIuEpL3fNfeC21tXXp9itM24A=
github.com/grafana/saml v0.4.15-0.20231025143828-a6c0e9b86a4c h1:1pHLC1ZTz7N5QI3jzCs5sqmVvAKe+JwGnpp9lQ+iUjY=
github.com/grafana/saml v0.4.15-0.20231025143828-a6c0e9b86a4c/go.mod h1:S4+611dxnKt8z/ulbvaJzcgSHsuhjVc1QHNTcr1R7Fw=
github.com/grafana/sqlds/v2 v2.3.10 h1:HWKhE0vR6LoEiE+Is8CSZOgaB//D1yqb2ntkass9Fd4=
github.com/grafana/sqlds/v2 v2.3.10/go.mod h1:c6ibxnxRVGxV/0YkEgvy7QpQH/lyifFyV7K/14xvdIs=
github.com/grafana/sqlds/v3 v3.2.0 h1:WXuYEaFfiCvgm8kK2ixx44/zAEjFzCylA2+RF3GBqZA=
github.com/grafana/sqlds/v3 v3.2.0/go.mod h1:kH0WuHUR3j0Q7IEymbm2JiaPckUhRCbqjV9ajaBAnmM=
github.com/grafana/tempo v1.5.1-0.20230524121406-1dc1bfe7085b h1:mDlkqgTEJuK7vjPG44f3ZMtId5AAYLWHvBVbiGqIOOQ=
github.com/grafana/tempo v1.5.1-0.20230524121406-1dc1bfe7085b/go.mod h1:UK7kTP5llPeRcGBOe5mm4QTNTd0k/mAqTVSOFdDH6AU=
github.com/grafana/thema v0.0.0-20230712153715-375c1b45f3ed h1:TMtHc+B0SSNw2in6Ro1dAiBYSPRp4NzKgndFDfupt18=
@@ -2348,9 +2347,18 @@ github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RR
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/mitchellh/reflectwalk v1.0.1/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/mithrandie/csvq v1.17.10 h1:ba8W6rWgB6LfIhY1ttmgXzKNcCoVtT4e6zuZTaGuAQg=
github.com/mithrandie/csvq v1.17.10/go.mod h1:ALXIPvYIbBEJvcoB41WSQhhLqOXT+2P4VommU+2DLLc=
github.com/mithrandie/csvq-driver v1.6.8 h1:0rF4yZ0ByIECznd9Ld+Ry5tIEYq/zxbb3QYuni/JWFk=
github.com/mithrandie/csvq-driver v1.6.8/go.mod h1:SrUKsCbaFKaaxKrptvLJ882CFMJD2hJAjv+Ev1HcUM8=
github.com/mithrandie/go-file/v2 v2.1.0 h1:XA5Tl+73GXMDvgwSE3Sg0uC5FkLr3hnXs8SpUas0hyg=
github.com/mithrandie/go-file/v2 v2.1.0/go.mod h1:9YtTF3Xo59GqC1Pxw6KyGVcM/qubAMlxVsqI/u9r++c=
github.com/mithrandie/go-text v1.5.4 h1:2LIASku5RuCqxa6O6eOvQwQ0k5FYWP1ID2hk9egYYGc=
github.com/mithrandie/go-text v1.5.4/go.mod h1:yaVYauF3TLf7LvjGrrQB/mffIkohXTXJpW9zQ206UL8=
github.com/mithrandie/ternary v1.1.1 h1:k/joD6UGVYxHixYmSR8EGgDFNONBMqyD373xT4QRdC4=
github.com/mithrandie/ternary v1.1.1/go.mod h1:0D9Ba3+09K2TdSZO7/bFCC0GjSXetCvYuYq0u8FY/1g=
github.com/moby/moby v23.0.4+incompatible h1:A/pe8vi9KIKhNbzR0G3wW4ACKDsMgXILBveMqiJNa8M=
github.com/moby/moby v23.0.4+incompatible/go.mod h1:fDXVQ6+S340veQPv35CzDahGBmHsiclFwfEygB/TWMc=
github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8=

View File

@@ -21,9 +21,12 @@ type Cfg struct {
ForwardHostEnvVars []string
// AWS Plugin Auth
AWSAllowedAuthProviders []string
AWSAssumeRoleEnabled bool
AWSExternalId string
AWSAllowedAuthProviders []string
AWSAssumeRoleEnabled bool
AWSExternalId string
AWSSessionDuration string
AWSListMetricsPageLimit string
AWSForwardSettingsPlugins []string
// Azure Cloud settings
Azure *azsettings.AzureSettings
@@ -54,33 +57,36 @@ type Cfg struct {
}
func NewCfg(devMode bool, pluginsPath string, pluginSettings setting.PluginSettings, pluginsAllowUnsigned []string,
awsAllowedAuthProviders []string, awsAssumeRoleEnabled bool, awsExternalId string, azure *azsettings.AzureSettings, secureSocksDSProxy setting.SecureSocksDSProxySettings,
awsAllowedAuthProviders []string, awsAssumeRoleEnabled bool, awsExternalId string, awsSessionDuration string, awsListMetricsPageLimit string, AWSForwardSettingsPlugins []string, azure *azsettings.AzureSettings, secureSocksDSProxy setting.SecureSocksDSProxySettings,
grafanaVersion string, logDatasourceRequests bool, pluginsCDNURLTemplate string, appURL string, appSubURL string, tracing Tracing, features featuremgmt.FeatureToggles, angularSupportEnabled bool,
grafanaComURL string, disablePlugins []string, hideAngularDeprecation []string, forwardHostEnvVars []string, concurrentQueryCount int, azureAuthEnabled bool) *Cfg {
return &Cfg{
log: log.New("plugin.cfg"),
PluginsPath: pluginsPath,
BuildVersion: grafanaVersion,
DevMode: devMode,
PluginSettings: pluginSettings,
PluginsAllowUnsigned: pluginsAllowUnsigned,
DisablePlugins: disablePlugins,
AWSAllowedAuthProviders: awsAllowedAuthProviders,
AWSAssumeRoleEnabled: awsAssumeRoleEnabled,
AWSExternalId: awsExternalId,
Azure: azure,
ProxySettings: secureSocksDSProxy,
LogDatasourceRequests: logDatasourceRequests,
PluginsCDNURLTemplate: pluginsCDNURLTemplate,
Tracing: tracing,
GrafanaComURL: grafanaComURL,
GrafanaAppURL: appURL,
GrafanaAppSubURL: appSubURL,
Features: features,
AngularSupportEnabled: angularSupportEnabled,
HideAngularDeprecation: hideAngularDeprecation,
ForwardHostEnvVars: forwardHostEnvVars,
ConcurrentQueryCount: concurrentQueryCount,
AzureAuthEnabled: azureAuthEnabled,
log: log.New("plugin.cfg"),
PluginsPath: pluginsPath,
BuildVersion: grafanaVersion,
DevMode: devMode,
PluginSettings: pluginSettings,
PluginsAllowUnsigned: pluginsAllowUnsigned,
DisablePlugins: disablePlugins,
AWSAllowedAuthProviders: awsAllowedAuthProviders,
AWSAssumeRoleEnabled: awsAssumeRoleEnabled,
AWSExternalId: awsExternalId,
AWSSessionDuration: awsSessionDuration,
AWSListMetricsPageLimit: awsListMetricsPageLimit,
AWSForwardSettingsPlugins: AWSForwardSettingsPlugins,
Azure: azure,
ProxySettings: secureSocksDSProxy,
LogDatasourceRequests: logDatasourceRequests,
PluginsCDNURLTemplate: pluginsCDNURLTemplate,
Tracing: tracing,
GrafanaComURL: grafanaComURL,
GrafanaAppURL: appURL,
GrafanaAppSubURL: appSubURL,
Features: features,
AngularSupportEnabled: angularSupportEnabled,
HideAngularDeprecation: hideAngularDeprecation,
ForwardHostEnvVars: forwardHostEnvVars,
ConcurrentQueryCount: concurrentQueryCount,
AzureAuthEnabled: azureAuthEnabled,
}
}

View File

@@ -129,16 +129,24 @@ func (s *Service) GetConfigMap(ctx context.Context, pluginID string, _ *auth.Ext
m[featuretoggles.EnabledFeatures] = strings.Join(features, ",")
}
}
// TODO add support via plugin SDK
// if s.cfg.AWSAssumeRoleEnabled {
// m[awsds.AssumeRoleEnabledEnvVarKeyName] = "true"
// }
// if len(s.cfg.AWSAllowedAuthProviders) > 0 {
// m[awsds.AllowedAuthProvidersEnvVarKeyName] = strings.Join(s.cfg.AWSAllowedAuthProviders, ",")
// }
// if s.cfg.AWSExternalId != "" {
// m[awsds.GrafanaAssumeRoleExternalIdKeyName] = s.cfg.AWSExternalId
// }
if slices.Contains[[]string, string](s.cfg.AWSForwardSettingsPlugins, pluginID) {
if !s.cfg.AWSAssumeRoleEnabled {
m[awsds.AssumeRoleEnabledEnvVarKeyName] = "false"
}
if len(s.cfg.AWSAllowedAuthProviders) > 0 {
m[awsds.AllowedAuthProvidersEnvVarKeyName] = strings.Join(s.cfg.AWSAllowedAuthProviders, ",")
}
if s.cfg.AWSExternalId != "" {
m[awsds.GrafanaAssumeRoleExternalIdKeyName] = s.cfg.AWSExternalId
}
if s.cfg.AWSSessionDuration != "" {
m[awsds.SessionDurationEnvVarKeyName] = s.cfg.AWSSessionDuration
}
if s.cfg.AWSListMetricsPageLimit != "" {
m[awsds.ListMetricsPageLimitKeyName] = s.cfg.AWSListMetricsPageLimit
}
}
if s.cfg.ProxySettings.Enabled {
m[proxy.PluginSecureSocksProxyEnabled] = "true"
@@ -257,8 +265,8 @@ func (s *Service) featureToggleEnableVar(ctx context.Context) []string {
func (s *Service) awsEnvVars() []string {
var variables []string
if s.cfg.AWSAssumeRoleEnabled {
variables = append(variables, awsds.AssumeRoleEnabledEnvVarKeyName+"=true")
if !s.cfg.AWSAssumeRoleEnabled {
variables = append(variables, awsds.AssumeRoleEnabledEnvVarKeyName+"=false")
}
if len(s.cfg.AWSAllowedAuthProviders) > 0 {
variables = append(variables, awsds.AllowedAuthProvidersEnvVarKeyName+"="+strings.Join(s.cfg.AWSAllowedAuthProviders, ","))
@@ -266,6 +274,12 @@ func (s *Service) awsEnvVars() []string {
if s.cfg.AWSExternalId != "" {
variables = append(variables, awsds.GrafanaAssumeRoleExternalIdKeyName+"="+s.cfg.AWSExternalId)
}
if s.cfg.AWSSessionDuration != "" {
variables = append(variables, awsds.SessionDurationEnvVarKeyName+"="+s.cfg.AWSSessionDuration)
}
if s.cfg.AWSListMetricsPageLimit != "" {
variables = append(variables, awsds.ListMetricsPageLimitKeyName+"="+s.cfg.AWSListMetricsPageLimit)
}
return variables
}

View File

@@ -40,6 +40,7 @@ func TestInitializer_envVars(t *testing.T) {
"custom_env_var": "customVal",
},
},
AWSAssumeRoleEnabled: true,
}, licensing)
envVars := envVarsProvider.Get(context.Background(), p)
@@ -203,7 +204,8 @@ func TestInitializer_tracingEnvironmentVariables(t *testing.T) {
{
name: "otel not configured",
cfg: &config.Cfg{
Tracing: config.Tracing{},
Tracing: config.Tracing{},
AWSAssumeRoleEnabled: false,
},
plugin: defaultPlugin,
exp: expNoTracing,
@@ -257,6 +259,7 @@ func TestInitializer_tracingEnvironmentVariables(t *testing.T) {
PluginSettings: map[string]map[string]string{
pluginID: {"tracing": "true"},
},
AWSAssumeRoleEnabled: true,
},
plugin: defaultPlugin,
exp: func(t *testing.T, envVars []string) {
@@ -288,6 +291,7 @@ func TestInitializer_tracingEnvironmentVariables(t *testing.T) {
PluginSettings: map[string]map[string]string{
pluginID: {"tracing": "true"},
},
AWSAssumeRoleEnabled: true,
},
plugin: defaultPlugin,
exp: func(t *testing.T, envVars []string) {
@@ -337,6 +341,7 @@ func TestInitializer_tracingEnvironmentVariables(t *testing.T) {
PluginSettings: map[string]map[string]string{
pluginID: {"some_other_option": "true"},
},
AWSAssumeRoleEnabled: true,
},
plugin: defaultPlugin,
exp: expNoTracing,
@@ -581,12 +586,14 @@ func TestInitalizer_awsEnvVars(t *testing.T) {
t.Run("backend datasource with aws settings", func(t *testing.T) {
p := &plugins.Plugin{}
envVarsProvider := NewProvider(&config.Cfg{
AWSAssumeRoleEnabled: true,
AWSAssumeRoleEnabled: false,
AWSAllowedAuthProviders: []string{"grafana_assume_role", "keys"},
AWSExternalId: "mock_external_id",
AWSSessionDuration: "10m",
AWSListMetricsPageLimit: "100",
}, nil)
envVars := envVarsProvider.Get(context.Background(), p)
assert.ElementsMatch(t, []string{"GF_VERSION=", "AWS_AUTH_AssumeRoleEnabled=true", "AWS_AUTH_AllowedAuthProviders=grafana_assume_role,keys", "AWS_AUTH_EXTERNAL_ID=mock_external_id"}, envVars)
assert.ElementsMatch(t, []string{"GF_VERSION=", "AWS_AUTH_AssumeRoleEnabled=false", "AWS_AUTH_AllowedAuthProviders=grafana_assume_role,keys", "AWS_AUTH_EXTERNAL_ID=mock_external_id", "AWS_AUTH_SESSION_DURATION=10m", "AWS_CW_LIST_METRICS_PAGE_LIMIT=100"}, envVars)
})
}
@@ -604,7 +611,7 @@ func TestInitializer_featureToggleEnvVar(t *testing.T) {
}, nil)
envVars := envVarsProvider.Get(context.Background(), p)
assert.Equal(t, 2, len(envVars))
assert.Equal(t, 3, len(envVars))
toggleExpression := strings.Split(envVars[1], "=")
assert.Equal(t, 2, len(toggleExpression))
@@ -628,6 +635,7 @@ func TestInitalizer_azureEnvVars(t *testing.T) {
t.Run("backend datasource with azure settings", func(t *testing.T) {
p := &plugins.Plugin{}
envVarsProvider := NewProvider(&config.Cfg{
AWSAssumeRoleEnabled: true,
Azure: &azsettings.AzureSettings{
Cloud: azsettings.AzurePublic,
ManagedIdentityEnabled: true,
@@ -925,3 +933,48 @@ func TestService_GetConfigMap_azure(t *testing.T) {
}, s.GetConfigMap(context.Background(), "test-datasource", nil))
})
}
func TestService_GetConfigMap_aws(t *testing.T) {
cfg := &config.Cfg{
AWSAssumeRoleEnabled: false,
AWSAllowedAuthProviders: []string{"grafana_assume_role", "keys"},
AWSExternalId: "mock_external_id",
AWSSessionDuration: "10m",
AWSListMetricsPageLimit: "100",
AWSForwardSettingsPlugins: []string{"cloudwatch", "prometheus", "elasticsearch"},
}
t.Run("uses the aws settings for an AWS plugin", func(t *testing.T) {
s := &Service{
cfg: cfg,
}
require.Equal(t, map[string]string{
"AWS_AUTH_AssumeRoleEnabled": "false",
"AWS_AUTH_AllowedAuthProviders": "grafana_assume_role,keys",
"AWS_AUTH_EXTERNAL_ID": "mock_external_id",
"AWS_AUTH_SESSION_DURATION": "10m",
"AWS_CW_LIST_METRICS_PAGE_LIMIT": "100",
}, s.GetConfigMap(context.Background(), "cloudwatch", nil))
})
t.Run("does not use the aws settings for a non-aws plugin", func(t *testing.T) {
s := &Service{
cfg: cfg,
}
require.Equal(t, map[string]string{}, s.GetConfigMap(context.Background(), "", nil))
})
t.Run("uses the aws settings for a non-aws user-specified plugin", func(t *testing.T) {
cfg.AWSForwardSettingsPlugins = append(cfg.AWSForwardSettingsPlugins, "test-datasource")
s := &Service{
cfg: cfg,
}
require.Equal(t, map[string]string{
"AWS_AUTH_AssumeRoleEnabled": "false",
"AWS_AUTH_AllowedAuthProviders": "grafana_assume_role,keys",
"AWS_AUTH_EXTERNAL_ID": "mock_external_id",
"AWS_AUTH_SESSION_DURATION": "10m",
"AWS_CW_LIST_METRICS_PAGE_LIMIT": "100",
}, s.GetConfigMap(context.Background(), "test-datasource", nil))
})
}

View File

@@ -7,6 +7,7 @@ import (
pCfg "github.com/grafana/grafana/pkg/plugins/config"
"github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/util"
)
func ProvideConfig(settingProvider setting.Provider, grafanaCfg *setting.Cfg, features featuremgmt.FeatureToggles) (*pCfg.Cfg, error) {
@@ -16,11 +17,19 @@ func ProvideConfig(settingProvider setting.Provider, grafanaCfg *setting.Cfg, fe
allowedUnsigned = strings.Split(plugins.KeyValue("allow_loading_unsigned_plugins").Value(), ",")
}
// Get aws settings from settingProvider instead of grafanaCfg
aws := settingProvider.Section("aws")
allowedAuth := grafanaCfg.AWSAllowedAuthProviders
if len(aws.KeyValue("allowed_auth_providers").Value()) > 0 {
allowedAuth = util.SplitString(aws.KeyValue("allowed_auth_providers").Value())
}
if len(allowedAuth) > 0 {
allowedUnsigned = strings.Split(settingProvider.KeyValue("plugins", "allow_loading_unsigned_plugins").Value(), ",")
}
awsForwardSettingsPlugins := grafanaCfg.AWSForwardSettingsPlugins
if len(aws.KeyValue("forward_settings_to_plugins").Value()) > 0 {
awsForwardSettingsPlugins = util.SplitString(aws.KeyValue("forward_settings_to_plugins").Value())
}
tracingCfg, err := newTracingCfg(grafanaCfg)
if err != nil {
@@ -35,6 +44,9 @@ func ProvideConfig(settingProvider setting.Provider, grafanaCfg *setting.Cfg, fe
allowedAuth,
aws.KeyValue("assume_role_enabled").MustBool(grafanaCfg.AWSAssumeRoleEnabled),
aws.KeyValue("external_id").Value(),
aws.KeyValue("session_duration").Value(),
aws.KeyValue("list_metrics_page_limit").Value(),
awsForwardSettingsPlugins,
grafanaCfg.Azure,
grafanaCfg.SecureSocksDSProxy,
grafanaCfg.BuildVersion,

View File

@@ -509,6 +509,7 @@ func TestLoader_Load_ExternalRegistration(t *testing.T) {
cfg := &config.Cfg{
Features: featuremgmt.WithFeatures(featuremgmt.FlagExternalServiceAuth),
PluginsAllowUnsigned: []string{"grafana-test-datasource"},
AWSAssumeRoleEnabled: true,
}
pluginPaths := []string{filepath.Join(testDataDir(t), "oauth-external-registration")}
expected := []*plugins.Plugin{
@@ -610,6 +611,7 @@ func TestLoader_Load_ExternalRegistration(t *testing.T) {
cfg := &config.Cfg{
Features: featuremgmt.WithFeatures(featuremgmt.FlagExternalServiceAuth),
PluginsAllowUnsigned: []string{"grafana-test-datasource"},
AWSAssumeRoleEnabled: true,
}
pluginPaths := []string{filepath.Join(testDataDir(t), "external-registration")}
expected := []*plugins.Plugin{

View File

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

View File

@@ -240,10 +240,12 @@ type Cfg struct {
AuthConfigUIAdminAccess bool
// AWS Plugin Auth
AWSAllowedAuthProviders []string
AWSAssumeRoleEnabled bool
AWSListMetricsPageLimit int
AWSExternalId string
AWSAllowedAuthProviders []string
AWSAssumeRoleEnabled bool
AWSSessionDuration string
AWSExternalId string
AWSListMetricsPageLimit int
AWSForwardSettingsPlugins []string
// Azure Cloud settings
Azure *azsettings.AzureSettings
@@ -1325,6 +1327,10 @@ func (cfg *Cfg) handleAWSConfig() {
}
}
cfg.AWSListMetricsPageLimit = awsPluginSec.Key("list_metrics_page_limit").MustInt(500)
cfg.AWSExternalId = awsPluginSec.Key("external_id").Value()
cfg.AWSSessionDuration = awsPluginSec.Key("session_duration").Value()
cfg.AWSForwardSettingsPlugins = util.SplitString(awsPluginSec.Key("forward_settings_to_plugins").String())
// Also set environment variables that can be used by core plugins
err := os.Setenv(awsds.AssumeRoleEnabledEnvVarKeyName, strconv.FormatBool(cfg.AWSAssumeRoleEnabled))
if err != nil {
@@ -1336,11 +1342,20 @@ func (cfg *Cfg) handleAWSConfig() {
cfg.Logger.Error(fmt.Sprintf("could not set environment variable '%s'", awsds.AllowedAuthProvidersEnvVarKeyName), err)
}
cfg.AWSExternalId = awsPluginSec.Key("external_id").Value()
err = os.Setenv(awsds.ListMetricsPageLimitKeyName, strconv.Itoa(cfg.AWSListMetricsPageLimit))
if err != nil {
cfg.Logger.Error(fmt.Sprintf("could not set environment variable '%s'", awsds.ListMetricsPageLimitKeyName), err)
}
err = os.Setenv(awsds.GrafanaAssumeRoleExternalIdKeyName, cfg.AWSExternalId)
if err != nil {
cfg.Logger.Error(fmt.Sprintf("could not set environment variable '%s'", awsds.GrafanaAssumeRoleExternalIdKeyName), err)
}
err = os.Setenv(awsds.SessionDurationEnvVarKeyName, cfg.AWSSessionDuration)
if err != nil {
cfg.Logger.Error(fmt.Sprintf("could not set environment variable '%s'", awsds.SessionDurationEnvVarKeyName), err)
}
}
func (cfg *Cfg) readSessionConfig() {

View File

@@ -10,9 +10,6 @@ import (
"github.com/aws/aws-sdk-go/service/cloudwatch"
"github.com/aws/aws-sdk-go/service/cloudwatch/cloudwatchiface"
"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/instancemgmt"
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/models"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@@ -30,11 +27,9 @@ func TestQuery_AnnotationQuery(t *testing.T) {
t.Run("DescribeAlarmsForMetric is called with minimum parameters", func(t *testing.T) {
client = fakeCWAnnotationsClient{describeAlarmsForMetricOutput: &cloudwatch.DescribeAlarmsForMetricOutput{}}
im := datasource.NewInstanceManager(func(ctx context.Context, s backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
return DataSource{Settings: models.CloudWatchSettings{}}, nil
})
im := defaultTestInstanceManager()
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
executor := newExecutor(im, &fakeSessionCache{})
_, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{
PluginContext: backend.PluginContext{
DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{},
@@ -64,11 +59,9 @@ func TestQuery_AnnotationQuery(t *testing.T) {
t.Run("DescribeAlarms is called when prefixMatching is true", func(t *testing.T) {
client = fakeCWAnnotationsClient{describeAlarmsOutput: &cloudwatch.DescribeAlarmsOutput{}}
im := datasource.NewInstanceManager(func(ctx context.Context, s backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
return DataSource{Settings: models.CloudWatchSettings{}}, nil
})
im := defaultTestInstanceManager()
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
executor := newExecutor(im, &fakeSessionCache{})
_, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{
PluginContext: backend.PluginContext{
DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{},

View File

@@ -6,7 +6,6 @@ import (
"github.com/aws/aws-sdk-go/aws/awsutil"
"github.com/aws/aws-sdk-go/service/cloudwatch"
"github.com/grafana/grafana/pkg/infra/metrics"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/models"
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/models/resources"
)
@@ -14,11 +13,11 @@ import (
// this client wraps the CloudWatch API and handles pagination and the composition of the MetricResponse DTO
type metricsClient struct {
models.CloudWatchMetricsAPIProvider
config *setting.Cfg
listMetricsPageLimit int
}
func NewMetricsClient(api models.CloudWatchMetricsAPIProvider, config *setting.Cfg) *metricsClient {
return &metricsClient{CloudWatchMetricsAPIProvider: api, config: config}
func NewMetricsClient(api models.CloudWatchMetricsAPIProvider, pageLimit int) *metricsClient {
return &metricsClient{CloudWatchMetricsAPIProvider: api, listMetricsPageLimit: pageLimit}
}
func (l *metricsClient) ListMetricsWithPageLimit(ctx context.Context, params *cloudwatch.ListMetricsInput) ([]resources.MetricResponse, error) {
@@ -37,7 +36,7 @@ func (l *metricsClient) ListMetricsWithPageLimit(ctx context.Context, params *cl
cloudWatchMetrics = append(cloudWatchMetrics, metric)
}
}
return !lastPage && pageNum < l.config.AWSListMetricsPageLimit
return !lastPage && pageNum < l.listMetricsPageLimit
})
return cloudWatchMetrics, err

View File

@@ -6,7 +6,6 @@ import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/cloudwatch"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/mocks"
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/models/resources"
"github.com/stretchr/testify/assert"
@@ -31,7 +30,7 @@ func TestMetricsClient(t *testing.T) {
t.Run("List Metrics and page limit is reached", func(t *testing.T) {
pageLimit := 3
fakeApi := &mocks.FakeMetricsAPI{Metrics: metrics, MetricsPerPage: 2}
client := NewMetricsClient(fakeApi, &setting.Cfg{AWSListMetricsPageLimit: pageLimit})
client := NewMetricsClient(fakeApi, pageLimit)
response, err := client.ListMetricsWithPageLimit(ctx, &cloudwatch.ListMetricsInput{})
require.NoError(t, err)
@@ -42,7 +41,7 @@ func TestMetricsClient(t *testing.T) {
t.Run("List Metrics and page limit is not reached", func(t *testing.T) {
pageLimit := 2
fakeApi := &mocks.FakeMetricsAPI{Metrics: metrics}
client := NewMetricsClient(fakeApi, &setting.Cfg{AWSListMetricsPageLimit: pageLimit})
client := NewMetricsClient(fakeApi, pageLimit)
response, err := client.ListMetricsWithPageLimit(ctx, &cloudwatch.ListMetricsInput{})
require.NoError(t, err)
@@ -56,7 +55,7 @@ func TestMetricsClient(t *testing.T) {
{MetricName: aws.String("Test_MetricName2")},
{MetricName: aws.String("Test_MetricName3")},
}, OwningAccounts: []*string{aws.String("1234567890"), aws.String("1234567890"), aws.String("1234567895")}}
client := NewMetricsClient(fakeApi, &setting.Cfg{AWSListMetricsPageLimit: 100})
client := NewMetricsClient(fakeApi, 100)
response, err := client.ListMetricsWithPageLimit(ctx, &cloudwatch.ListMetricsInput{IncludeLinkedAccounts: aws.Bool(true)})
require.NoError(t, err)
@@ -70,7 +69,7 @@ func TestMetricsClient(t *testing.T) {
t.Run("Should not return account id in case IncludeLinkedAccounts is set to false", func(t *testing.T) {
fakeApi := &mocks.FakeMetricsAPI{Metrics: []*cloudwatch.Metric{{MetricName: aws.String("Test_MetricName1")}}, OwningAccounts: []*string{aws.String("1234567890")}}
client := NewMetricsClient(fakeApi, &setting.Cfg{AWSListMetricsPageLimit: 100})
client := NewMetricsClient(fakeApi, 100)
response, err := client.ListMetricsWithPageLimit(ctx, &cloudwatch.ListMetricsInput{IncludeLinkedAccounts: aws.Bool(false)})
require.NoError(t, err)

View File

@@ -24,7 +24,6 @@ import (
"github.com/grafana/grafana-plugin-sdk-go/backend/proxy"
"github.com/grafana/grafana-plugin-sdk-go/backend/resource/httpadapter"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/clients"
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/kinds/dataquery"
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/models"
@@ -64,19 +63,16 @@ const (
var logger = log.New("tsdb.cloudwatch")
func ProvideService(cfg *setting.Cfg, httpClientProvider *httpclient.Provider) *CloudWatchService {
func ProvideService(httpClientProvider *httpclient.Provider) *CloudWatchService {
logger.Debug("Initializing")
executor := newExecutor(datasource.NewInstanceManager(NewInstanceSettings(httpClientProvider)), cfg, awsds.NewSessionCache())
executor := newExecutor(datasource.NewInstanceManager(NewInstanceSettings(httpClientProvider)), awsds.NewSessionCache())
return &CloudWatchService{
Cfg: cfg,
Executor: executor,
}
}
type CloudWatchService struct {
Cfg *setting.Cfg
Executor *cloudWatchExecutor
}
@@ -84,10 +80,9 @@ type SessionCache interface {
GetSession(c awsds.SessionConfig) (*session.Session, error)
}
func newExecutor(im instancemgmt.InstanceManager, cfg *setting.Cfg, sessions SessionCache) *cloudWatchExecutor {
func newExecutor(im instancemgmt.InstanceManager, sessions SessionCache) *cloudWatchExecutor {
e := &cloudWatchExecutor{
im: im,
cfg: cfg,
sessions: sessions,
}
@@ -97,7 +92,7 @@ func newExecutor(im instancemgmt.InstanceManager, cfg *setting.Cfg, sessions Ses
func NewInstanceSettings(httpClientProvider *httpclient.Provider) datasource.InstanceFactoryFunc {
return func(ctx context.Context, settings backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
instanceSettings, err := models.LoadCloudWatchSettings(settings)
instanceSettings, err := models.LoadCloudWatchSettings(ctx, settings)
if err != nil {
return nil, fmt.Errorf("error reading settings: %w", err)
}
@@ -125,7 +120,6 @@ func NewInstanceSettings(httpClientProvider *httpclient.Provider) datasource.Ins
// cloudWatchExecutor executes CloudWatch requests.
type cloudWatchExecutor struct {
im instancemgmt.InstanceManager
cfg *setting.Cfg
sessions SessionCache
regionCache sync.Map
@@ -154,7 +148,7 @@ func (e *cloudWatchExecutor) getRequestContext(ctx context.Context, pluginCtx ba
return models.RequestContext{
OAMAPIProvider: NewOAMAPI(sess),
MetricsClientProvider: clients.NewMetricsClient(NewMetricsAPI(sess), e.cfg),
MetricsClientProvider: clients.NewMetricsClient(NewMetricsAPI(sess), instance.Settings.GrafanaSettings.ListMetricsPageLimit),
LogsAPIProvider: NewLogsAPI(sess),
EC2APIProvider: ec2Client,
Settings: instance.Settings,
@@ -236,7 +230,13 @@ func (e *cloudWatchExecutor) checkHealthMetrics(ctx context.Context, pluginCtx b
if err != nil {
return err
}
metricClient := clients.NewMetricsClient(NewMetricsAPI(session), e.cfg)
instance, err := e.getInstance(ctx, pluginCtx)
if err != nil {
return err
}
metricClient := clients.NewMetricsClient(NewMetricsAPI(session), instance.Settings.GrafanaSettings.ListMetricsPageLimit)
_, err = metricClient.ListMetricsWithPageLimit(ctx, params)
return err
}
@@ -279,13 +279,14 @@ func (e *cloudWatchExecutor) newSession(ctx context.Context, pluginCtx backend.P
SecretKey: instance.Settings.SecretKey,
},
UserAgentName: aws.String("Cloudwatch"),
AuthSettings: &instance.Settings.GrafanaSettings,
})
if err != nil {
return nil, err
}
// work around until https://github.com/grafana/grafana/issues/39089 is implemented
if e.cfg.SecureSocksDSProxy.Enabled && instance.Settings.SecureSocksProxyEnabled {
if instance.Settings.GrafanaSettings.SecureSocksDSProxyEnabled && instance.Settings.SecureSocksProxyEnabled {
// only update the transport to try to avoid the issue mentioned here https://github.com/grafana/grafana/issues/46365
// also, 'sess' is cached and reused, so the first time it might have the transport not set, the following uses it will
if sess.Config.HTTPClient.Transport == nil {

View File

@@ -16,7 +16,6 @@ import (
"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/instancemgmt"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/mocks"
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/models"
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/models/resources"
@@ -54,16 +53,8 @@ func Test_CloudWatch_CallResource_Integration_Test(t *testing.T) {
return &api
}
im := datasource.NewInstanceManager(func(ctx context.Context, s backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
return DataSource{Settings: models.CloudWatchSettings{
AWSDatasourceSettings: awsds.AWSDatasourceSettings{
Region: "us-east-1",
},
}}, nil
})
t.Run("Should handle dimension value request and return values from the api", func(t *testing.T) {
pageLimit := 100
im := testInstanceManager(100)
api = mocks.FakeMetricsAPI{Metrics: []*cloudwatch.Metric{
{MetricName: aws.String("Test_MetricName1"), Dimensions: []*cloudwatch.Dimension{{Name: aws.String("Test_DimensionName1"), Value: aws.String("Value1")}, {Name: aws.String("Test_DimensionName2"), Value: aws.String("Value2")}}},
{MetricName: aws.String("Test_MetricName2"), Dimensions: []*cloudwatch.Dimension{{Name: aws.String("Test_DimensionName1"), Value: aws.String("Value3")}}},
@@ -76,7 +67,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_MetricName9"), Dimensions: []*cloudwatch.Dimension{{Name: aws.String("Test_DimensionName1"), Value: aws.String("Value2")}}},
}, MetricsPerPage: 100}
executor := newExecutor(im, &setting.Cfg{AWSListMetricsPageLimit: pageLimit}, &fakeSessionCache{})
executor := newExecutor(im, &fakeSessionCache{})
req := &backend.CallResourceRequest{
Method: "GET",
@@ -99,7 +90,7 @@ func Test_CloudWatch_CallResource_Integration_Test(t *testing.T) {
})
t.Run("Should handle dimension key filter query and return keys from the api", func(t *testing.T) {
pageLimit := 3
im := testInstanceManager(3)
api = mocks.FakeMetricsAPI{Metrics: []*cloudwatch.Metric{
{MetricName: aws.String("Test_MetricName1"), Dimensions: []*cloudwatch.Dimension{{Name: aws.String("Test_DimensionName1")}, {Name: aws.String("Test_DimensionName2")}}},
{MetricName: aws.String("Test_MetricName2"), Dimensions: []*cloudwatch.Dimension{{Name: aws.String("Test_DimensionName1")}}},
@@ -112,8 +103,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_MetricName9"), Dimensions: []*cloudwatch.Dimension{{Name: aws.String("Test_DimensionName1")}}},
}, MetricsPerPage: 2}
executor := newExecutor(im, &setting.Cfg{AWSListMetricsPageLimit: pageLimit}, &fakeSessionCache{})
executor := newExecutor(im, &fakeSessionCache{})
req := &backend.CallResourceRequest{
Method: "GET",
Path: `/dimension-keys?region=us-east-2&namespace=AWS/EC2&metricName=CPUUtilization&dimensionFilters={"NodeID":["Shared"],"stage":["QueryCommit"]}`,
@@ -135,8 +125,9 @@ 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) {
im := defaultTestInstanceManager()
api = mocks.FakeMetricsAPI{}
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
executor := newExecutor(im, &fakeSessionCache{})
req := &backend.CallResourceRequest{
Method: "GET",
@@ -159,9 +150,9 @@ 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) {
im := defaultTestInstanceManager()
api = mocks.FakeMetricsAPI{}
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
executor := newExecutor(im, &fakeSessionCache{})
req := &backend.CallResourceRequest{
Method: "GET",
Path: `/dimension-keys?region=us-east-2&namespace=AWS/CloudSearch&metricName=CPUUtilization`,
@@ -183,7 +174,7 @@ func Test_CloudWatch_CallResource_Integration_Test(t *testing.T) {
})
t.Run("Should handle custom namespace metrics query and return metrics from api", func(t *testing.T) {
pageLimit := 3
im := testInstanceManager(3)
api = mocks.FakeMetricsAPI{Metrics: []*cloudwatch.Metric{
{MetricName: aws.String("Test_MetricName1"), Namespace: aws.String("AWS/EC2"), Dimensions: []*cloudwatch.Dimension{{Name: aws.String("Test_DimensionName1")}, {Name: aws.String("Test_DimensionName2")}}},
{MetricName: aws.String("Test_MetricName2"), Namespace: aws.String("AWS/EC2"), Dimensions: []*cloudwatch.Dimension{{Name: aws.String("Test_DimensionName1")}}},
@@ -196,7 +187,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_MetricName9"), Namespace: aws.String("AWS/EC2"), Dimensions: []*cloudwatch.Dimension{{Name: aws.String("Test_DimensionName1")}}},
}, MetricsPerPage: 2}
executor := newExecutor(im, &setting.Cfg{AWSListMetricsPageLimit: pageLimit}, &fakeSessionCache{})
executor := newExecutor(im, &fakeSessionCache{})
req := &backend.CallResourceRequest{
Method: "GET",
@@ -219,6 +210,7 @@ func Test_CloudWatch_CallResource_Integration_Test(t *testing.T) {
})
t.Run("Should handle log group fields request", func(t *testing.T) {
im := defaultTestInstanceManager()
logApi = mocks.LogsAPI{}
logApi.On("GetLogGroupFieldsWithContext", mock.Anything).Return(&cloudwatchlogs.GetLogGroupFieldsOutput{
LogGroupFields: []*cloudwatchlogs.LogGroupField{
@@ -232,7 +224,7 @@ func Test_CloudWatch_CallResource_Integration_Test(t *testing.T) {
},
},
}, nil)
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
executor := newExecutor(im, &fakeSessionCache{})
req := &backend.CallResourceRequest{
Method: "GET",
@@ -253,7 +245,8 @@ 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) {
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
im := defaultTestInstanceManager()
executor := newExecutor(im, &fakeSessionCache{})
req := &backend.CallResourceRequest{
Method: "GET",
Path: `/regions`,
@@ -275,10 +268,11 @@ func Test_CloudWatch_CallResource_Integration_Test(t *testing.T) {
imWithoutDefaultRegion := datasource.NewInstanceManager(func(ctx context.Context, s backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
return DataSource{Settings: models.CloudWatchSettings{
AWSDatasourceSettings: awsds.AWSDatasourceSettings{},
GrafanaSettings: awsds.AuthSettings{ListMetricsPageLimit: 1000},
}}, nil
})
executor := newExecutor(imWithoutDefaultRegion, newTestConfig(), &fakeSessionCache{})
executor := newExecutor(imWithoutDefaultRegion, &fakeSessionCache{})
req := &backend.CallResourceRequest{
Method: "GET",
Path: `/regions`,

View File

@@ -4,6 +4,7 @@ import (
"context"
"fmt"
"testing"
"time"
"github.com/aws/aws-sdk-go/aws"
awsclient "github.com/aws/aws-sdk-go/aws/client"
@@ -16,6 +17,7 @@ import (
"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/instancemgmt"
"github.com/grafana/grafana-plugin-sdk-go/backend/proxy"
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/features"
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/mocks"
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/models"
@@ -26,9 +28,11 @@ import (
)
func TestNewInstanceSettings(t *testing.T) {
ctxDuration := 10 * time.Minute
tests := []struct {
name string
settings backend.DataSourceInstanceSettings
settingCtx context.Context
expectedDS DataSource
Err require.ErrorAssertionFunc
}{
@@ -49,6 +53,14 @@ func TestNewInstanceSettings(t *testing.T) {
"secretKey": "secret",
},
},
settingCtx: backend.WithGrafanaConfig(context.Background(), backend.NewGrafanaCfg(map[string]string{
awsds.AllowedAuthProvidersEnvVarKeyName: "foo , bar,baz",
awsds.AssumeRoleEnabledEnvVarKeyName: "false",
awsds.SessionDurationEnvVarKeyName: "10m",
awsds.GrafanaAssumeRoleExternalIdKeyName: "mock_id",
awsds.ListMetricsPageLimitKeyName: "50",
proxy.PluginSecureSocksProxyEnabled: "true",
})),
expectedDS: DataSource{
Settings: models.CloudWatchSettings{
AWSDatasourceSettings: awsds.AWSDatasourceSettings{
@@ -62,6 +74,14 @@ func TestNewInstanceSettings(t *testing.T) {
SecretKey: "secret",
},
Namespace: "ns",
GrafanaSettings: awsds.AuthSettings{
AllowedAuthProviders: []string{"foo", "bar", "baz"},
AssumeRoleEnabled: false,
SessionDuration: &ctxDuration,
ExternalID: "mock_id",
ListMetricsPageLimit: 50,
SecureSocksDSProxyEnabled: true,
},
},
},
Err: require.NoError,
@@ -71,8 +91,9 @@ func TestNewInstanceSettings(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
f := NewInstanceSettings(httpclient.NewProvider())
model, err := f(context.Background(), tt.settings)
model, err := f(tt.settingCtx, tt.settings)
tt.Err(t, err)
assert.Equal(t, tt.expectedDS.Settings.GrafanaSettings, model.(DataSource).Settings.GrafanaSettings)
datasourceComparer := cmp.Comparer(func(d1 DataSource, d2 DataSource) bool {
return d1.Settings.Profile == d2.Settings.Profile &&
d1.Settings.Region == d2.Settings.Region &&
@@ -109,17 +130,11 @@ func Test_CheckHealth(t *testing.T) {
NewLogsAPI = func(sess *session.Session) models.CloudWatchLogsAPIProvider {
return client
}
im := datasource.NewInstanceManager(func(ctx context.Context, s backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
return DataSource{Settings: models.CloudWatchSettings{
AWSDatasourceSettings: awsds.AWSDatasourceSettings{
Region: "us-east-1",
},
}}, nil
})
im := defaultTestInstanceManager()
t.Run("successfully query metrics and logs", func(t *testing.T) {
client = fakeCheckHealthClient{}
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
executor := newExecutor(im, &fakeSessionCache{})
resp, err := executor.CheckHealth(context.Background(), &backend.CheckHealthRequest{
PluginContext: backend.PluginContext{DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}},
@@ -138,7 +153,7 @@ func Test_CheckHealth(t *testing.T) {
return nil, fmt.Errorf("some logs query error")
}}
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
executor := newExecutor(im, &fakeSessionCache{})
resp, err := executor.CheckHealth(context.Background(), &backend.CheckHealthRequest{
PluginContext: backend.PluginContext{DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}},
@@ -157,7 +172,7 @@ func Test_CheckHealth(t *testing.T) {
return fmt.Errorf("some list metrics error")
}}
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
executor := newExecutor(im, &fakeSessionCache{})
resp, err := executor.CheckHealth(context.Background(), &backend.CheckHealthRequest{
PluginContext: backend.PluginContext{DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}},
@@ -173,7 +188,7 @@ func Test_CheckHealth(t *testing.T) {
t.Run("fail to get clients", func(t *testing.T) {
client = fakeCheckHealthClient{}
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{getSession: func(c awsds.SessionConfig) (*session.Session, error) {
executor := newExecutor(im, &fakeSessionCache{getSession: func(c awsds.SessionConfig) (*session.Session, error) {
return nil, fmt.Errorf("some sessions error")
}})
@@ -189,6 +204,37 @@ func Test_CheckHealth(t *testing.T) {
})
}
func TestNewSession_passes_authSettings(t *testing.T) {
ctxDuration := 15 * time.Minute
expectedSettings := awsds.AuthSettings{
AllowedAuthProviders: []string{"foo", "bar", "baz"},
AssumeRoleEnabled: false,
SessionDuration: &ctxDuration,
ExternalID: "mock_id",
ListMetricsPageLimit: 50,
SecureSocksDSProxyEnabled: true,
}
im := datasource.NewInstanceManager((func(ctx context.Context, s backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
return DataSource{Settings: models.CloudWatchSettings{
AWSDatasourceSettings: awsds.AWSDatasourceSettings{
Region: "us-east-1",
},
GrafanaSettings: expectedSettings,
}}, nil
}))
executor := newExecutor(im, &fakeSessionCache{getSession: func(c awsds.SessionConfig) (*session.Session, error) {
assert.NotNil(t, c.AuthSettings)
assert.Equal(t, expectedSettings, *c.AuthSettings)
return &session.Session{
Config: &aws.Config{},
}, nil
}})
_, err := executor.newSession(context.Background(),
backend.PluginContext{DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}}, "us-east-1")
require.NoError(t, err)
}
func TestQuery_ResourceRequest_DescribeLogGroups_with_CrossAccountQuerying(t *testing.T) {
sender := &mockedCallResourceResponseSenderForOauth{}
origNewMetricsAPI := NewMetricsAPI
@@ -210,13 +256,7 @@ func TestQuery_ResourceRequest_DescribeLogGroups_with_CrossAccountQuerying(t *te
return &logsApi
}
im := datasource.NewInstanceManager(func(ctx context.Context, s backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
return DataSource{Settings: models.CloudWatchSettings{
AWSDatasourceSettings: awsds.AWSDatasourceSettings{
Region: "us-east-1",
},
}}, nil
})
im := defaultTestInstanceManager()
t.Run("maps log group api response to resource response of log-groups", func(t *testing.T) {
logsApi = mocks.LogsAPI{}
@@ -234,7 +274,7 @@ func TestQuery_ResourceRequest_DescribeLogGroups_with_CrossAccountQuerying(t *te
},
}
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
executor := newExecutor(im, &fakeSessionCache{})
err := executor.CallResource(contextWithFeaturesEnabled(features.FlagCloudWatchCrossAccountQuerying), req, sender)
assert.NoError(t, err)

View File

@@ -16,7 +16,12 @@ import (
// getDimensionValues gets the actual dimension values for dimensions with a wildcard
func (e *cloudWatchExecutor) getDimensionValuesForWildcards(ctx context.Context, pluginCtx backend.PluginContext, region string,
client models.CloudWatchMetricsAPIProvider, origQueries []*models.CloudWatchQuery, tagValueCache *cache.Cache, logger log.Logger) ([]*models.CloudWatchQuery, error) {
metricsClient := clients.NewMetricsClient(client, e.cfg)
instance, err := e.getInstance(ctx, pluginCtx)
if err != nil {
return nil, err
}
metricsClient := clients.NewMetricsClient(client, instance.Settings.GrafanaSettings.ListMetricsPageLimit)
service := services.NewListMetricsService(metricsClient)
// create copies of the original query. All the fields besides Dimensions are primitives
queries := copyQueries(origQueries)

View File

@@ -17,7 +17,7 @@ import (
func TestGetDimensionValuesForWildcards(t *testing.T) {
logger := &logtest.Fake{}
executor := &cloudWatchExecutor{}
executor := &cloudWatchExecutor{im: defaultTestInstanceManager()}
ctx := context.Background()
pluginCtx := backend.PluginContext{
DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{ID: 1, Updated: time.Now()},

View File

@@ -90,7 +90,7 @@ func TestQuery_handleGetLogEvents_passes_nil_start_and_end_times_to_GetLogEvents
return DataSource{Settings: models.CloudWatchSettings{}}, nil
})
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
executor := newExecutor(im, &fakeSessionCache{})
_, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{
PluginContext: backend.PluginContext{
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) {
return DataSource{Settings: models.CloudWatchSettings{}}, nil
})
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
executor := newExecutor(im, &fakeSessionCache{})
cli = &mocks.MockLogEvents{}
cli.On("GetLogEventsWithContext", mock.Anything, mock.Anything, mock.Anything).Return(&cloudwatchlogs.GetLogEventsOutput{
@@ -208,7 +208,7 @@ func TestQuery_StartQuery(t *testing.T) {
}}, nil
})
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
executor := newExecutor(im, &fakeSessionCache{})
_, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{
PluginContext: backend.PluginContext{
DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{},
@@ -265,7 +265,7 @@ func TestQuery_StartQuery(t *testing.T) {
}}, nil
})
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
executor := newExecutor(im, &fakeSessionCache{})
resp, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{
PluginContext: backend.PluginContext{
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) {
return DataSource{Settings: models.CloudWatchSettings{}}, nil
})
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
executor := newExecutor(im, &fakeSessionCache{})
_, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{
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) {
return DataSource{Settings: models.CloudWatchSettings{}}, nil
})
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
executor := newExecutor(im, &fakeSessionCache{})
_, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{
PluginContext: backend.PluginContext{DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}},
@@ -384,7 +384,7 @@ func Test_executeStartQuery(t *testing.T) {
im := datasource.NewInstanceManager(func(ctx context.Context, s backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
return DataSource{Settings: models.CloudWatchSettings{}}, nil
})
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
executor := newExecutor(im, &fakeSessionCache{})
_, err := executor.QueryData(contextWithFeaturesEnabled(features.FlagCloudWatchCrossAccountQuerying), &backend.QueryDataRequest{
PluginContext: backend.PluginContext{DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}},
@@ -420,7 +420,7 @@ func Test_executeStartQuery(t *testing.T) {
im := datasource.NewInstanceManager(func(ctx context.Context, s backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
return DataSource{Settings: models.CloudWatchSettings{}}, nil
})
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
executor := newExecutor(im, &fakeSessionCache{})
_, err := executor.QueryData(contextWithFeaturesEnabled(features.FlagCloudWatchCrossAccountQuerying), &backend.QueryDataRequest{
PluginContext: backend.PluginContext{DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}},
@@ -456,7 +456,8 @@ func Test_executeStartQuery(t *testing.T) {
im := datasource.NewInstanceManager(func(ctx context.Context, s backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
return DataSource{Settings: models.CloudWatchSettings{}}, nil
})
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
executor := newExecutor(im, &fakeSessionCache{})
_, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{
PluginContext: backend.PluginContext{DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}},
Queries: []backend.DataQuery{
@@ -491,7 +492,7 @@ func Test_executeStartQuery(t *testing.T) {
im := datasource.NewInstanceManager(func(ctx context.Context, s backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
return DataSource{Settings: models.CloudWatchSettings{}}, nil
})
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
executor := newExecutor(im, &fakeSessionCache{})
_, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{
PluginContext: backend.PluginContext{DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}},
Queries: []backend.DataQuery{
@@ -525,7 +526,7 @@ func Test_executeStartQuery(t *testing.T) {
im := datasource.NewInstanceManager(func(ctx context.Context, s backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
return DataSource{Settings: models.CloudWatchSettings{}}, nil
})
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
executor := newExecutor(im, &fakeSessionCache{})
_, err := executor.QueryData(contextWithFeaturesEnabled(features.FlagCloudWatchCrossAccountQuerying), &backend.QueryDataRequest{
PluginContext: backend.PluginContext{DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}},
Queries: []backend.DataQuery{
@@ -596,7 +597,7 @@ func TestQuery_StopQuery(t *testing.T) {
To: time.Unix(1584700643, 0),
}
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
executor := newExecutor(im, &fakeSessionCache{})
resp, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{
PluginContext: backend.PluginContext{
DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{},
@@ -686,7 +687,7 @@ func TestQuery_GetQueryResults(t *testing.T) {
return DataSource{Settings: models.CloudWatchSettings{}}, nil
})
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
executor := newExecutor(im, &fakeSessionCache{})
resp, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{
PluginContext: backend.PluginContext{
DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{},

View File

@@ -40,7 +40,7 @@ func Test_executeSyncLogQuery(t *testing.T) {
return DataSource{Settings: models.CloudWatchSettings{}}, nil
})
sess := fakeSessionCache{}
executor := newExecutor(im, newTestConfig(), &sess)
executor := newExecutor(im, &sess)
_, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{
Headers: map[string]string{headerFromAlert: "some value"},
@@ -67,7 +67,7 @@ func Test_executeSyncLogQuery(t *testing.T) {
})
sess := fakeSessionCache{}
executor := newExecutor(im, newTestConfig(), &sess)
executor := newExecutor(im, &sess)
_, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{
Headers: map[string]string{headerFromAlert: "some value"},
PluginContext: backend.PluginContext{DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}},
@@ -124,7 +124,7 @@ func Test_executeSyncLogQuery(t *testing.T) {
})
sess := fakeSessionCache{}
executor := newExecutor(im, newTestConfig(), &sess)
executor := newExecutor(im, &sess)
_, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{
Headers: tc.headers,
PluginContext: backend.PluginContext{DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}},
@@ -167,7 +167,7 @@ func Test_executeSyncLogQuery(t *testing.T) {
})
sess := fakeSessionCache{}
executor := newExecutor(im, newTestConfig(), &sess)
executor := newExecutor(im, &sess)
_, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{
PluginContext: backend.PluginContext{DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}},
Queries: []backend.DataQuery{
@@ -206,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) {
return DataSource{Settings: models.CloudWatchSettings{}}, nil
})
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
executor := newExecutor(im, &fakeSessionCache{})
res, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{
Headers: map[string]string{headerFromAlert: "some value"},
@@ -235,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) {
return DataSource{Settings: models.CloudWatchSettings{}}, nil
})
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
executor := newExecutor(im, &fakeSessionCache{})
res, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{
Headers: map[string]string{headerFromAlert: "some value"},
@@ -304,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) {
return DataSource{Settings: models.CloudWatchSettings{}}, nil
})
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
executor := newExecutor(im, &fakeSessionCache{})
res, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{
Headers: map[string]string{headerFromAlert: "some value"},
@@ -349,8 +349,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) {
return DataSource{Settings: models.CloudWatchSettings{LogsTimeout: models.Duration{Duration: time.Millisecond}}}, nil
})
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
executor := newExecutor(im, &fakeSessionCache{})
_, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{
Headers: map[string]string{headerFromAlert: "some value"},
@@ -382,7 +381,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) {
return DataSource{Settings: models.CloudWatchSettings{}}, nil
})
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
executor := newExecutor(im, &fakeSessionCache{})
res, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{
Headers: map[string]string{headerFromAlert: "some value"},

View File

@@ -26,7 +26,7 @@ func TestMetricDataInputBuilder(t *testing.T) {
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
executor := newExecutor(nil, newTestConfig(), &fakeSessionCache{})
executor := newExecutor(nil, &fakeSessionCache{})
query := getBaseQuery()
query.TimezoneUTCOffset = tc.timezoneUTCOffset

View File

@@ -12,7 +12,7 @@ import (
func TestMetricDataQueryBuilder(t *testing.T) {
t.Run("buildMetricDataQuery", func(t *testing.T) {
t.Run("should use metric stat", func(t *testing.T) {
executor := newExecutor(nil, newTestConfig(), &fakeSessionCache{})
executor := newExecutor(nil, &fakeSessionCache{})
query := getBaseQuery()
query.MetricEditorMode = models.MetricEditorModeBuilder
query.MetricQueryType = models.MetricQueryTypeSearch
@@ -24,7 +24,7 @@ func TestMetricDataQueryBuilder(t *testing.T) {
})
t.Run("should pass AccountId in metric stat query", func(t *testing.T) {
executor := newExecutor(nil, newTestConfig(), &fakeSessionCache{})
executor := newExecutor(nil, &fakeSessionCache{})
query := getBaseQuery()
query.MetricEditorMode = models.MetricEditorModeBuilder
query.MetricQueryType = models.MetricQueryTypeSearch
@@ -35,7 +35,7 @@ func TestMetricDataQueryBuilder(t *testing.T) {
})
t.Run("should leave AccountId in metric stat query", func(t *testing.T) {
executor := newExecutor(nil, newTestConfig(), &fakeSessionCache{})
executor := newExecutor(nil, &fakeSessionCache{})
query := getBaseQuery()
query.MetricEditorMode = models.MetricEditorModeBuilder
query.MetricQueryType = models.MetricQueryTypeSearch
@@ -45,7 +45,7 @@ func TestMetricDataQueryBuilder(t *testing.T) {
})
t.Run("should use custom built expression", func(t *testing.T) {
executor := newExecutor(nil, newTestConfig(), &fakeSessionCache{})
executor := newExecutor(nil, &fakeSessionCache{})
query := getBaseQuery()
query.MetricEditorMode = models.MetricEditorModeBuilder
query.MetricQueryType = models.MetricQueryTypeSearch
@@ -57,7 +57,7 @@ func TestMetricDataQueryBuilder(t *testing.T) {
})
t.Run("should use sql expression", func(t *testing.T) {
executor := newExecutor(nil, newTestConfig(), &fakeSessionCache{})
executor := newExecutor(nil, &fakeSessionCache{})
query := getBaseQuery()
query.MetricEditorMode = models.MetricEditorModeRaw
query.MetricQueryType = models.MetricQueryTypeQuery
@@ -69,7 +69,7 @@ func TestMetricDataQueryBuilder(t *testing.T) {
})
t.Run("should use user defined math expression", func(t *testing.T) {
executor := newExecutor(nil, newTestConfig(), &fakeSessionCache{})
executor := newExecutor(nil, &fakeSessionCache{})
query := getBaseQuery()
query.MetricEditorMode = models.MetricEditorModeRaw
query.MetricQueryType = models.MetricQueryTypeSearch
@@ -81,7 +81,7 @@ func TestMetricDataQueryBuilder(t *testing.T) {
})
t.Run("should set period in user defined expression", func(t *testing.T) {
executor := newExecutor(nil, newTestConfig(), &fakeSessionCache{})
executor := newExecutor(nil, &fakeSessionCache{})
query := getBaseQuery()
query.MetricEditorMode = models.MetricEditorModeRaw
query.MetricQueryType = models.MetricQueryTypeSearch
@@ -95,7 +95,7 @@ func TestMetricDataQueryBuilder(t *testing.T) {
})
t.Run("should set label", func(t *testing.T) {
executor := newExecutor(nil, newTestConfig(), &fakeSessionCache{})
executor := newExecutor(nil, &fakeSessionCache{})
query := getBaseQuery()
query.Label = "some label"
@@ -107,7 +107,7 @@ func TestMetricDataQueryBuilder(t *testing.T) {
})
t.Run("should not set label for empty string query label", func(t *testing.T) {
executor := newExecutor(nil, newTestConfig(), &fakeSessionCache{})
executor := newExecutor(nil, &fakeSessionCache{})
query := getBaseQuery()
query.Label = ""
@@ -118,7 +118,7 @@ func TestMetricDataQueryBuilder(t *testing.T) {
})
t.Run(`should not specify accountId when it is "all"`, func(t *testing.T) {
executor := newExecutor(nil, newTestConfig(), &fakeSessionCache{})
executor := newExecutor(nil, &fakeSessionCache{})
query := &models.CloudWatchQuery{
Namespace: "AWS/EC2",
MetricName: "CPUUtilization",
@@ -136,7 +136,7 @@ func TestMetricDataQueryBuilder(t *testing.T) {
})
t.Run("should set accountId when it is specified", func(t *testing.T) {
executor := newExecutor(nil, newTestConfig(), &fakeSessionCache{})
executor := newExecutor(nil, &fakeSessionCache{})
query := &models.CloudWatchQuery{
Namespace: "AWS/EC2",
MetricName: "CPUUtilization",

View File

@@ -47,10 +47,13 @@ func TestQuery_Regions(t *testing.T) {
}, nil)
im := datasource.NewInstanceManager(func(ctx context.Context, s backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
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"},
GrafanaSettings: awsds.AuthSettings{ListMetricsPageLimit: 1000},
}}, nil
})
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
executor := newExecutor(im, &fakeSessionCache{})
resp, err := executor.handleGetRegions(
context.Background(),
backend.PluginContext{
@@ -104,12 +107,15 @@ func Test_handleGetRegions_regionCache(t *testing.T) {
return &cli
}
im := datasource.NewInstanceManager(func(ctx context.Context, s backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
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"},
GrafanaSettings: awsds.AuthSettings{ListMetricsPageLimit: 1000},
}}, nil
})
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)
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
executor := newExecutor(im, &fakeSessionCache{})
_, err := executor.handleGetRegions(
context.Background(),
backend.PluginContext{DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}}, nil)
@@ -165,7 +171,7 @@ func TestQuery_InstanceAttributes(t *testing.T) {
filterJson, err := json.Marshal(filterMap)
require.NoError(t, err)
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
executor := newExecutor(im, &fakeSessionCache{})
resp, err := executor.handleGetEc2InstanceAttribute(
context.Background(),
backend.PluginContext{
@@ -243,7 +249,7 @@ func TestQuery_EBSVolumeIDs(t *testing.T) {
return DataSource{Settings: models.CloudWatchSettings{}}, nil
})
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
executor := newExecutor(im, &fakeSessionCache{})
resp, err := executor.handleGetEbsVolumeIds(
context.Background(),
backend.PluginContext{
@@ -310,7 +316,7 @@ func TestQuery_ResourceARNs(t *testing.T) {
tagJson, err := json.Marshal(tagMap)
require.NoError(t, err)
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
executor := newExecutor(im, &fakeSessionCache{})
resp, err := executor.handleGetResourceArns(
context.Background(),
backend.PluginContext{

View File

@@ -1,6 +1,7 @@
package models
import (
"context"
"encoding/json"
"fmt"
"time"
@@ -17,9 +18,12 @@ type CloudWatchSettings struct {
Namespace string `json:"customMetricsNamespaces"`
SecureSocksProxyEnabled bool `json:"enableSecureSocksProxy"` // this can be removed when https://github.com/grafana/grafana/issues/39089 is implemented
LogsTimeout Duration `json:"logsTimeout"`
// GrafanaSettings are fetched from the GrafanaCfg in the context
GrafanaSettings awsds.AuthSettings `json:"-"`
}
func LoadCloudWatchSettings(config backend.DataSourceInstanceSettings) (CloudWatchSettings, error) {
func LoadCloudWatchSettings(ctx context.Context, config backend.DataSourceInstanceSettings) (CloudWatchSettings, error) {
instance := CloudWatchSettings{}
if config.JSONData != nil && len(config.JSONData) > 1 {
if err := json.Unmarshal(config.JSONData, &instance); err != nil {
@@ -43,6 +47,7 @@ func LoadCloudWatchSettings(config backend.DataSourceInstanceSettings) (CloudWat
instance.AccessKey = config.DecryptedSecureJSONData["accessKey"]
instance.SecretKey = config.DecryptedSecureJSONData["secretKey"]
instance.GrafanaSettings = *awsds.ReadAuthSettings(ctx)
return instance, nil
}

View File

@@ -1,16 +1,23 @@
package models
import (
"context"
"testing"
"time"
"github.com/grafana/grafana-aws-sdk/pkg/awsds"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana-plugin-sdk-go/backend/proxy"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func Test_Settings_LoadCloudWatchSettings(t *testing.T) {
settingCtx := backend.WithGrafanaConfig(context.Background(), backend.NewGrafanaCfg(map[string]string{
awsds.AllowedAuthProvidersEnvVarKeyName: "default,keys,credentials",
awsds.AssumeRoleEnabledEnvVarKeyName: "false",
awsds.SessionDurationEnvVarKeyName: "10m",
}))
t.Run("Should return error for invalid json", func(t *testing.T) {
settings := backend.DataSourceInstanceSettings{
ID: 33,
@@ -25,7 +32,7 @@ func Test_Settings_LoadCloudWatchSettings(t *testing.T) {
},
}
_, err := LoadCloudWatchSettings(settings)
_, err := LoadCloudWatchSettings(settingCtx, settings)
assert.Error(t, err)
})
@@ -47,7 +54,7 @@ func Test_Settings_LoadCloudWatchSettings(t *testing.T) {
},
}
s, err := LoadCloudWatchSettings(settings)
s, err := LoadCloudWatchSettings(settingCtx, settings)
require.NoError(t, err)
assert.Equal(t, awsds.AuthTypeKeys, s.AuthType)
assert.Equal(t, "arn:aws:iam::123456789012:role/grafana", s.AssumeRoleARN)
@@ -78,7 +85,7 @@ func Test_Settings_LoadCloudWatchSettings(t *testing.T) {
},
}
s, err := LoadCloudWatchSettings(settings)
s, err := LoadCloudWatchSettings(settingCtx, settings)
require.NoError(t, err)
assert.Equal(t, awsds.AuthTypeDefault, s.AuthType)
assert.Equal(t, "arn:aws:iam::123456789012:role/grafana", s.AssumeRoleARN)
@@ -103,7 +110,7 @@ func Test_Settings_LoadCloudWatchSettings(t *testing.T) {
},
}
s, err := LoadCloudWatchSettings(settings)
s, err := LoadCloudWatchSettings(settingCtx, settings)
require.NoError(t, err)
assert.Equal(t, time.Minute*30, s.LogsTimeout.Duration)
})
@@ -121,7 +128,7 @@ func Test_Settings_LoadCloudWatchSettings(t *testing.T) {
},
}
s, err := LoadCloudWatchSettings(settings)
s, err := LoadCloudWatchSettings(settingCtx, settings)
require.NoError(t, err)
assert.Equal(t, time.Minute*10, s.LogsTimeout.Duration)
})
@@ -139,7 +146,7 @@ func Test_Settings_LoadCloudWatchSettings(t *testing.T) {
},
}
s, err := LoadCloudWatchSettings(settings)
s, err := LoadCloudWatchSettings(settingCtx, settings)
require.NoError(t, err)
assert.Equal(t, time.Duration(1500000000), s.LogsTimeout.Duration)
})
@@ -157,7 +164,7 @@ func Test_Settings_LoadCloudWatchSettings(t *testing.T) {
},
}
s, err := LoadCloudWatchSettings(settings)
s, err := LoadCloudWatchSettings(settingCtx, settings)
require.NoError(t, err)
assert.Equal(t, 1500*time.Millisecond, s.LogsTimeout.Duration)
})
@@ -175,7 +182,7 @@ func Test_Settings_LoadCloudWatchSettings(t *testing.T) {
},
}
_, err := LoadCloudWatchSettings(settings)
_, err := LoadCloudWatchSettings(context.Background(), settings)
require.Error(t, err)
})
t.Run("Should throw error if logsTimeout is an invalid type", func(t *testing.T) {
@@ -192,7 +199,42 @@ func Test_Settings_LoadCloudWatchSettings(t *testing.T) {
},
}
_, err := LoadCloudWatchSettings(settings)
_, err := LoadCloudWatchSettings(settingCtx, settings)
require.Error(t, err)
})
t.Run("Should load settings from context", func(t *testing.T) {
settingCtx := backend.WithGrafanaConfig(context.Background(), backend.NewGrafanaCfg(map[string]string{
awsds.AllowedAuthProvidersEnvVarKeyName: "foo , bar,baz",
awsds.AssumeRoleEnabledEnvVarKeyName: "false",
awsds.SessionDurationEnvVarKeyName: "10m",
awsds.GrafanaAssumeRoleExternalIdKeyName: "mock_id",
awsds.ListMetricsPageLimitKeyName: "50",
proxy.PluginSecureSocksProxyEnabled: "true",
}))
settings := backend.DataSourceInstanceSettings{
ID: 33,
JSONData: []byte(`{
"authType": "arn",
"assumeRoleArn": "arn:aws:iam::123456789012:role/grafana"
}`),
DecryptedSecureJSONData: map[string]string{
"accessKey": "AKIAIOSFODNN7EXAMPLE",
"secretKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
},
}
s, err := LoadCloudWatchSettings(settingCtx, settings)
require.NoError(t, err)
ctxDuration := 10 * time.Minute
expectedGrafanaSettings := awsds.AuthSettings{
AllowedAuthProviders: []string{"foo", "bar", "baz"},
AssumeRoleEnabled: false,
SessionDuration: &ctxDuration,
ExternalID: "mock_id",
ListMetricsPageLimit: 50,
SecureSocksDSProxyEnabled: true,
}
assert.Equal(t, expectedGrafanaSettings, s.GrafanaSettings)
})
}

View File

@@ -17,8 +17,10 @@ import (
"github.com/aws/aws-sdk-go/service/resourcegroupstaggingapi/resourcegroupstaggingapiiface"
"github.com/grafana/grafana-aws-sdk/pkg/awsds"
"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/instancemgmt"
"github.com/grafana/grafana-plugin-sdk-go/experimental/featuretoggles"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/tsdb/cloudwatch/models"
"github.com/stretchr/testify/mock"
)
@@ -214,8 +216,19 @@ func (c fakeCheckHealthClient) GetLogGroupFieldsWithContext(ctx context.Context,
return nil, nil
}
func newTestConfig() *setting.Cfg {
return &setting.Cfg{AWSAllowedAuthProviders: []string{"default"}, AWSAssumeRoleEnabled: true, AWSListMetricsPageLimit: 1000}
func testInstanceManager(pageLimit int) instancemgmt.InstanceManager {
return datasource.NewInstanceManager((func(ctx context.Context, s backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
return DataSource{Settings: models.CloudWatchSettings{
AWSDatasourceSettings: awsds.AWSDatasourceSettings{
Region: "us-east-1",
},
GrafanaSettings: awsds.AuthSettings{ListMetricsPageLimit: pageLimit},
}}, nil
}))
}
func defaultTestInstanceManager() instancemgmt.InstanceManager {
return testInstanceManager(1000)
}
type mockSessionCache struct {

View File

@@ -26,7 +26,7 @@ import (
)
func TestTimeSeriesQuery(t *testing.T) {
executor := newExecutor(nil, newTestConfig(), &fakeSessionCache{})
executor := newExecutor(nil, &fakeSessionCache{})
now := time.Now()
origNewCWClient := NewCWClient
@@ -50,11 +50,9 @@ func TestTimeSeriesQuery(t *testing.T) {
StatusCode: aws.String("Complete"), Id: aws.String("b"), Label: aws.String("NetworkIn"), Values: []*float64{aws.Float64(1.0)}, Timestamps: []*time.Time{&now},
}}}, nil)
im := datasource.NewInstanceManager(func(ctx context.Context, s backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
return DataSource{Settings: models.CloudWatchSettings{}}, nil
})
im := defaultTestInstanceManager()
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
executor := newExecutor(im, &fakeSessionCache{})
resp, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{
PluginContext: backend.PluginContext{
DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{},
@@ -160,7 +158,7 @@ func Test_executeTimeSeriesQuery_getCWClient_is_called_once_per_region_and_GetMe
mockMetricClient = mocks.MetricsAPI{}
mockMetricClient.On("GetMetricDataWithContext", mock.Anything, mock.Anything, mock.Anything).Return(nil, nil)
executor := newExecutor(im, newTestConfig(), mockSessionCache)
executor := newExecutor(im, mockSessionCache)
_, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{
PluginContext: backend.PluginContext{
DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{},
@@ -211,7 +209,7 @@ func Test_executeTimeSeriesQuery_getCWClient_is_called_once_per_region_and_GetMe
mockMetricClient = mocks.MetricsAPI{}
mockMetricClient.On("GetMetricDataWithContext", mock.Anything, mock.Anything, mock.Anything).Return(nil, nil)
executor := newExecutor(im, newTestConfig(), sessionCache)
executor := newExecutor(im, sessionCache)
_, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{
PluginContext: backend.PluginContext{
DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{},
@@ -344,7 +342,7 @@ func Test_QueryData_timeSeriesQuery_GetMetricDataWithContext(t *testing.T) {
t.Run("passes query label as GetMetricData label", func(t *testing.T) {
api = mocks.MetricsAPI{}
api.On("GetMetricDataWithContext", mock.Anything, mock.Anything, mock.Anything).Return(&cloudwatch.GetMetricDataOutput{}, nil)
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
executor := newExecutor(im, &fakeSessionCache{})
query := newTestQuery(t, queryParameters{
Label: aws.String("${PROP('Period')} some words ${PROP('Dim.InstanceId')}"),
})
@@ -383,7 +381,7 @@ func Test_QueryData_timeSeriesQuery_GetMetricDataWithContext(t *testing.T) {
t.Run(name, func(t *testing.T) {
api = mocks.MetricsAPI{}
api.On("GetMetricDataWithContext", mock.Anything, mock.Anything, mock.Anything).Return(&cloudwatch.GetMetricDataOutput{}, nil)
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
executor := newExecutor(im, &fakeSessionCache{})
_, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{
PluginContext: backend.PluginContext{DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{}},
@@ -433,10 +431,8 @@ func Test_QueryData_response_data_frame_name_is_always_response_label(t *testing
Values: []*float64{aws.Float64(1.0)}, Timestamps: []*time.Time{{}}},
}}, nil)
im := datasource.NewInstanceManager(func(ctx context.Context, s backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
return DataSource{Settings: models.CloudWatchSettings{}}, nil
})
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
im := defaultTestInstanceManager()
executor := newExecutor(im, &fakeSessionCache{})
t.Run("where user defines search expression", func(t *testing.T) {
query := newTestQuery(t, queryParameters{
@@ -588,14 +584,12 @@ func TestTimeSeriesQuery_CrossAccountQuerying(t *testing.T) {
NewCWClient = func(sess *session.Session) cloudwatchiface.CloudWatchAPI {
return &api
}
im := datasource.NewInstanceManager(func(ctx context.Context, s backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
return DataSource{Settings: models.CloudWatchSettings{}}, nil
})
im := defaultTestInstanceManager()
t.Run("should call GetMetricDataInput with AccountId nil when no AccountId is provided", func(t *testing.T) {
api = mocks.MetricsAPI{}
api.On("GetMetricDataWithContext", mock.Anything, mock.Anything, mock.Anything).Return(&cloudwatch.GetMetricDataOutput{}, nil)
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
executor := newExecutor(im, &fakeSessionCache{})
_, err := executor.QueryData(contextWithFeaturesEnabled(features.FlagCloudWatchCrossAccountQuerying), &backend.QueryDataRequest{
PluginContext: backend.PluginContext{
@@ -636,7 +630,7 @@ func TestTimeSeriesQuery_CrossAccountQuerying(t *testing.T) {
t.Run("should call GetMetricDataInput with AccountId nil when feature flag is false", func(t *testing.T) {
api = mocks.MetricsAPI{}
api.On("GetMetricDataWithContext", mock.Anything, mock.Anything, mock.Anything).Return(&cloudwatch.GetMetricDataOutput{}, nil)
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
executor := newExecutor(im, &fakeSessionCache{})
_, err := executor.QueryData(context.Background(), &backend.QueryDataRequest{
PluginContext: backend.PluginContext{
DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{},
@@ -677,7 +671,7 @@ func TestTimeSeriesQuery_CrossAccountQuerying(t *testing.T) {
t.Run("should call GetMetricDataInput with AccountId in a MetricStat query", func(t *testing.T) {
api = mocks.MetricsAPI{}
api.On("GetMetricDataWithContext", mock.Anything, mock.Anything, mock.Anything).Return(&cloudwatch.GetMetricDataOutput{}, nil)
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
executor := newExecutor(im, &fakeSessionCache{})
_, err := executor.QueryData(contextWithFeaturesEnabled(features.FlagCloudWatchCrossAccountQuerying), &backend.QueryDataRequest{
PluginContext: backend.PluginContext{
DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{},
@@ -718,7 +712,7 @@ func TestTimeSeriesQuery_CrossAccountQuerying(t *testing.T) {
t.Run("should GetMetricDataInput with AccountId in an inferred search expression query", func(t *testing.T) {
api = mocks.MetricsAPI{}
api.On("GetMetricDataWithContext", mock.Anything, mock.Anything, mock.Anything).Return(&cloudwatch.GetMetricDataOutput{}, nil)
executor := newExecutor(im, newTestConfig(), &fakeSessionCache{})
executor := newExecutor(im, &fakeSessionCache{})
_, err := executor.QueryData(contextWithFeaturesEnabled(features.FlagCloudWatchCrossAccountQuerying), &backend.QueryDataRequest{
PluginContext: backend.PluginContext{
DataSourceInstanceSettings: &backend.DataSourceInstanceSettings{},