cloudwatch: Consolidate client logic (#25555)
* cloudwatch: Consolidate client logic Co-authored-by: Arve Knudsen <arve.knudsen@gmail.com>
This commit is contained in:
@@ -9,11 +9,17 @@ import (
|
||||
|
||||
"github.com/grafana/grafana-plugin-sdk-go/data"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/client"
|
||||
"github.com/aws/aws-sdk-go/aws/request"
|
||||
"github.com/aws/aws-sdk-go/aws/session"
|
||||
"github.com/aws/aws-sdk-go/service/cloudwatch"
|
||||
"github.com/aws/aws-sdk-go/service/cloudwatch/cloudwatchiface"
|
||||
"github.com/aws/aws-sdk-go/service/cloudwatchlogs"
|
||||
"github.com/aws/aws-sdk-go/service/cloudwatchlogs/cloudwatchlogsiface"
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
"github.com/aws/aws-sdk-go/service/ec2/ec2iface"
|
||||
"github.com/aws/aws-sdk-go/service/resourcegroupstaggingapi"
|
||||
"github.com/aws/aws-sdk-go/service/resourcegroupstaggingapi/resourcegroupstaggingapiiface"
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
@@ -45,75 +51,95 @@ var plog = log.New("tsdb.cloudwatch")
|
||||
var aliasFormat = regexp.MustCompile(`\{\{\s*(.+?)\s*\}\}`)
|
||||
|
||||
func init() {
|
||||
tsdb.RegisterTsdbQueryEndpoint("cloudwatch", newcloudWatchExecutor)
|
||||
tsdb.RegisterTsdbQueryEndpoint("cloudwatch", func(ds *models.DataSource) (tsdb.TsdbQueryEndpoint, error) {
|
||||
return newExecutor(), nil
|
||||
})
|
||||
}
|
||||
|
||||
func newcloudWatchExecutor(datasource *models.DataSource) (tsdb.TsdbQueryEndpoint, error) {
|
||||
e := &cloudWatchExecutor{
|
||||
DataSource: datasource,
|
||||
func newExecutor() *cloudWatchExecutor {
|
||||
return &cloudWatchExecutor{
|
||||
logsClientsByRegion: map[string]cloudwatchlogsiface.CloudWatchLogsAPI{},
|
||||
}
|
||||
|
||||
dsInfo := e.getDSInfo(defaultRegion)
|
||||
defaultLogsClient, err := retrieveLogsClient(dsInfo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
e.logsClientsByRegion = map[string]*cloudwatchlogs.CloudWatchLogs{
|
||||
dsInfo.Region: defaultLogsClient,
|
||||
defaultRegion: defaultLogsClient,
|
||||
}
|
||||
|
||||
return e, nil
|
||||
}
|
||||
|
||||
// cloudWatchExecutor executes CloudWatch requests.
|
||||
type cloudWatchExecutor struct {
|
||||
*models.DataSource
|
||||
ec2Svc ec2iface.EC2API
|
||||
rgtaSvc resourcegroupstaggingapiiface.ResourceGroupsTaggingAPIAPI
|
||||
|
||||
logsClientsByRegion map[string](*cloudwatchlogs.CloudWatchLogs)
|
||||
mux sync.Mutex
|
||||
ec2Client ec2iface.EC2API
|
||||
rgtaClient resourcegroupstaggingapiiface.ResourceGroupsTaggingAPIAPI
|
||||
logsClientsByRegion map[string]cloudwatchlogsiface.CloudWatchLogsAPI
|
||||
mtx sync.Mutex
|
||||
}
|
||||
|
||||
func (e *cloudWatchExecutor) getCWClient(region string) (*cloudwatch.CloudWatch, error) {
|
||||
datasourceInfo := e.getDSInfo(region)
|
||||
cfg, err := getAwsConfig(datasourceInfo)
|
||||
func (e *cloudWatchExecutor) newSession(region string) (*session.Session, error) {
|
||||
dsInfo := e.getDSInfo(region)
|
||||
creds, err := getCredentials(dsInfo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sess, err := newSession(cfg)
|
||||
cfg := &aws.Config{
|
||||
Region: aws.String(dsInfo.Region),
|
||||
Credentials: creds,
|
||||
}
|
||||
return newSession(cfg)
|
||||
}
|
||||
|
||||
func (e *cloudWatchExecutor) getCWClient(region string) (cloudwatchiface.CloudWatchAPI, error) {
|
||||
sess, err := e.newSession(region)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
client := cloudwatch.New(sess, cfg)
|
||||
|
||||
client.Handlers.Send.PushFront(func(r *request.Request) {
|
||||
r.HTTPRequest.Header.Set("User-Agent", fmt.Sprintf("Grafana/%s", setting.BuildVersion))
|
||||
})
|
||||
|
||||
return client, nil
|
||||
return newCWClient(sess), nil
|
||||
}
|
||||
|
||||
func (e *cloudWatchExecutor) getCWLogsClient(region string) (*cloudwatchlogs.CloudWatchLogs, error) {
|
||||
e.mux.Lock()
|
||||
defer e.mux.Unlock()
|
||||
func (e *cloudWatchExecutor) getCWLogsClient(region string) (cloudwatchlogsiface.CloudWatchLogsAPI, error) {
|
||||
e.mtx.Lock()
|
||||
defer e.mtx.Unlock()
|
||||
|
||||
if logsClient, ok := e.logsClientsByRegion[region]; ok {
|
||||
return logsClient, nil
|
||||
}
|
||||
|
||||
dsInfo := e.getDSInfo(region)
|
||||
newLogsClient, err := retrieveLogsClient(dsInfo)
|
||||
sess, err := e.newSession(region)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
e.logsClientsByRegion[region] = newLogsClient
|
||||
logsClient := newCWLogsClient(sess)
|
||||
e.logsClientsByRegion[region] = logsClient
|
||||
|
||||
return newLogsClient, nil
|
||||
return logsClient, nil
|
||||
}
|
||||
|
||||
func (e *cloudWatchExecutor) getEC2Client(region string) (ec2iface.EC2API, error) {
|
||||
if e.ec2Client != nil {
|
||||
return e.ec2Client, nil
|
||||
}
|
||||
|
||||
sess, err := e.newSession(region)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
e.ec2Client = newEC2Client(sess)
|
||||
|
||||
return e.ec2Client, nil
|
||||
}
|
||||
|
||||
func (e *cloudWatchExecutor) getRGTAClient(region string) (resourcegroupstaggingapiiface.ResourceGroupsTaggingAPIAPI,
|
||||
error) {
|
||||
if e.rgtaClient != nil {
|
||||
return e.rgtaClient, nil
|
||||
}
|
||||
|
||||
sess, err := e.newSession(region)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
e.rgtaClient = newRGTAClient(sess)
|
||||
|
||||
return e.rgtaClient, nil
|
||||
}
|
||||
|
||||
func (e *cloudWatchExecutor) alertQuery(ctx context.Context, logsClient cloudwatchlogsiface.CloudWatchLogsAPI,
|
||||
@@ -279,26 +305,44 @@ func (e *cloudWatchExecutor) getDSInfo(region string) *datasourceInfo {
|
||||
}
|
||||
}
|
||||
|
||||
func retrieveLogsClient(dsInfo *datasourceInfo) (*cloudwatchlogs.CloudWatchLogs, error) {
|
||||
cfg, err := getAwsConfig(dsInfo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sess, err := newSession(cfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
client := cloudwatchlogs.New(sess, cfg)
|
||||
func isTerminated(queryStatus string) bool {
|
||||
return queryStatus == "Complete" || queryStatus == "Cancelled" || queryStatus == "Failed" || queryStatus == "Timeout"
|
||||
}
|
||||
|
||||
// CloudWatch client factory.
|
||||
//
|
||||
// Stubbable by tests.
|
||||
var newCWClient = func(sess *session.Session) cloudwatchiface.CloudWatchAPI {
|
||||
client := cloudwatch.New(sess)
|
||||
client.Handlers.Send.PushFront(func(r *request.Request) {
|
||||
r.HTTPRequest.Header.Set("User-Agent", fmt.Sprintf("Grafana/%s", setting.BuildVersion))
|
||||
})
|
||||
|
||||
return client, nil
|
||||
return client
|
||||
}
|
||||
|
||||
func isTerminated(queryStatus string) bool {
|
||||
return queryStatus == "Complete" || queryStatus == "Cancelled" || queryStatus == "Failed" || queryStatus == "Timeout"
|
||||
// CloudWatch logs client factory.
|
||||
//
|
||||
// Stubbable by tests.
|
||||
var newCWLogsClient = func(sess *session.Session) cloudwatchlogsiface.CloudWatchLogsAPI {
|
||||
client := cloudwatchlogs.New(sess)
|
||||
client.Handlers.Send.PushFront(func(r *request.Request) {
|
||||
r.HTTPRequest.Header.Set("User-Agent", fmt.Sprintf("Grafana/%s", setting.BuildVersion))
|
||||
})
|
||||
|
||||
return client
|
||||
}
|
||||
|
||||
// EC2 client factory.
|
||||
//
|
||||
// Stubbable by tests.
|
||||
var newEC2Client = func(provider client.ConfigProvider) ec2iface.EC2API {
|
||||
return ec2.New(provider)
|
||||
}
|
||||
|
||||
// RGTA client factory.
|
||||
//
|
||||
// Stubbable by tests.
|
||||
var newRGTAClient = func(provider client.ConfigProvider) resourcegroupstaggingapiiface.ResourceGroupsTaggingAPIAPI {
|
||||
return resourcegroupstaggingapi.New(provider)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user