mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
CloudWatch: Remove dependencies on grafana/pkg/setting (#81208)
This commit is contained in:
@@ -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
|
||||
|
@@ -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
15
go.mod
@@ -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
24
go.sum
@@ -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=
|
||||
|
@@ -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,
|
||||
}
|
||||
}
|
||||
|
@@ -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
|
||||
}
|
||||
|
@@ -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))
|
||||
})
|
||||
}
|
||||
|
@@ -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,
|
||||
|
@@ -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{
|
||||
|
@@ -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)
|
||||
|
@@ -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() {
|
||||
|
@@ -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{},
|
||||
|
@@ -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
|
||||
|
@@ -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)
|
||||
|
@@ -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 {
|
||||
|
@@ -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`,
|
||||
|
@@ -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)
|
||||
|
||||
|
@@ -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)
|
||||
|
@@ -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()},
|
||||
|
@@ -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{},
|
||||
|
@@ -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"},
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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",
|
||||
|
@@ -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{
|
||||
|
@@ -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
|
||||
}
|
||||
|
@@ -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)
|
||||
})
|
||||
}
|
||||
|
@@ -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 {
|
||||
|
@@ -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{},
|
||||
|
Reference in New Issue
Block a user