Skip to content

Commit

Permalink
Merge pull request #221 from K-Phoen/cloudwatch-datasource
Browse files Browse the repository at this point in the history
Support defining CloudWatch datasources
  • Loading branch information
K-Phoen committed Apr 10, 2023
2 parents c76eea1 + 8a7600e commit e25e564
Show file tree
Hide file tree
Showing 4 changed files with 232 additions and 0 deletions.
48 changes: 48 additions & 0 deletions datasource/cloudwatch/cloudwatch.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package cloudwatch

import (
"encoding/json"

"github.com/K-Phoen/grabana/datasource"
"github.com/K-Phoen/sdk"
)

var _ datasource.Datasource = CloudWatch{}

type CloudWatch struct {
builder *sdk.Datasource
}

type Option func(datasource *CloudWatch) error

func New(name string, options ...Option) (CloudWatch, error) {
cloudwatch := &CloudWatch{
builder: &sdk.Datasource{
Name: name,
Type: "cloudwatch",
Access: "proxy",
JSONData: map[string]interface{}{},
SecureJSONData: map[string]interface{}{},
},
}

defaults := []Option{
DefaultAuth(),
}

for _, opt := range append(defaults, options...) {
if err := opt(cloudwatch); err != nil {
return *cloudwatch, err
}
}

return *cloudwatch, nil
}

func (datasource CloudWatch) Name() string {
return datasource.builder.Name
}

func (datasource CloudWatch) MarshalJSON() ([]byte, error) {
return json.Marshal(datasource.builder)
}
22 changes: 22 additions & 0 deletions datasource/cloudwatch/cloudwatch_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package cloudwatch

import (
"testing"

"github.com/stretchr/testify/require"
)

func TestNewCloudWatch(t *testing.T) {
req := require.New(t)

datasource, err := New("ds-name")

req.NoError(err)
req.Equal("ds-name", datasource.Name())
req.Equal("cloudwatch", datasource.builder.Type)
req.NotNil(datasource.builder.JSONData)
req.NotNil(datasource.builder.SecureJSONData)

_, err = datasource.MarshalJSON()
req.NoError(err)
}
81 changes: 81 additions & 0 deletions datasource/cloudwatch/options.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package cloudwatch

import (
"strings"
)

// DefaultAuth relies on the AWS SDK default authentication to authenticate to the CloudWatch service.
func DefaultAuth() Option {
return func(datasource *CloudWatch) error {
datasource.builder.JSONData.(map[string]interface{})["authType"] = "default"

return nil
}
}

// AccessSecretAuth relies on an access and secret key to authenticate to the CloudWatch service.
func AccessSecretAuth(accessKey string, secretKey string) Option {
return func(datasource *CloudWatch) error {
datasource.builder.JSONData.(map[string]interface{})["authType"] = "keys"
datasource.builder.SecureJSONData.(map[string]interface{})["accessKey"] = accessKey
datasource.builder.SecureJSONData.(map[string]interface{})["secretKey"] = secretKey

return nil
}
}

// Default configures this datasource to be the default one.
func Default() Option {
return func(datasource *CloudWatch) error {
datasource.builder.IsDefault = true

return nil
}
}

// DefaultRegion sets the default region to use.
// Example: eu-north-1.
func DefaultRegion(region string) Option {
return func(datasource *CloudWatch) error {
datasource.builder.JSONData.(map[string]interface{})["defaultRegion"] = region

return nil
}
}

// AssumeRoleARN specifies the ARN of a role to assume.
// Format: arn:aws:iam:*
func AssumeRoleARN(roleARN string) Option {
return func(datasource *CloudWatch) error {
datasource.builder.JSONData.(map[string]interface{})["assumeRoleArn"] = roleARN

return nil
}
}

// ExternalID specifies the external identifier of a role to assume in another account.
func ExternalID(externalID string) Option {
return func(datasource *CloudWatch) error {
datasource.builder.JSONData.(map[string]interface{})["externalId"] = externalID

return nil
}
}

// Endpoint specifies a custom endpoint for the CloudWatch service.
func Endpoint(endpoint string) Option {
return func(datasource *CloudWatch) error {
datasource.builder.JSONData.(map[string]interface{})["endpoint"] = endpoint

return nil
}
}

// CustomMetricsNamespaces specifies a list of namespaces for custom metrics.
func CustomMetricsNamespaces(namespaces ...string) Option {
return func(datasource *CloudWatch) error {
datasource.builder.JSONData.(map[string]interface{})["customMetricsNamespaces"] = strings.Join(namespaces, ",")

return nil
}
}
81 changes: 81 additions & 0 deletions datasource/cloudwatch/options_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package cloudwatch

import (
"testing"

"github.com/stretchr/testify/require"
)

func TestDefault(t *testing.T) {
req := require.New(t)

datasource, err := New("", Default())

req.NoError(err)
req.True(datasource.builder.IsDefault)
}

func TestDefaultAuth(t *testing.T) {
req := require.New(t)

datasource, err := New("", DefaultAuth())

req.NoError(err)
req.Equal("default", datasource.builder.JSONData.(map[string]interface{})["authType"])
}

func TestAccessSecretAuth(t *testing.T) {
req := require.New(t)

datasource, err := New("", AccessSecretAuth("access", "secret"))

req.NoError(err)
req.Equal("keys", datasource.builder.JSONData.(map[string]interface{})["authType"])
req.Equal("access", datasource.builder.SecureJSONData.(map[string]interface{})["accessKey"])
req.Equal("secret", datasource.builder.SecureJSONData.(map[string]interface{})["secretKey"])
}

func TestDefaultRegion(t *testing.T) {
req := require.New(t)

datasource, err := New("", DefaultRegion("eu-north-1"))

req.NoError(err)
req.Equal("eu-north-1", datasource.builder.JSONData.(map[string]interface{})["defaultRegion"])
}

func TestAssumeRoleARN(t *testing.T) {
req := require.New(t)

datasource, err := New("", AssumeRoleARN("arn:aws:iam:role"))

req.NoError(err)
req.Equal("arn:aws:iam:role", datasource.builder.JSONData.(map[string]interface{})["assumeRoleArn"])
}

func TestExternalID(t *testing.T) {
req := require.New(t)

datasource, err := New("", ExternalID("external-id"))

req.NoError(err)
req.Equal("external-id", datasource.builder.JSONData.(map[string]interface{})["externalId"])
}

func TestEndpoint(t *testing.T) {
req := require.New(t)

datasource, err := New("", Endpoint("endpoint"))

req.NoError(err)
req.Equal("endpoint", datasource.builder.JSONData.(map[string]interface{})["endpoint"])
}

func TestCustomMetricsNamespaces(t *testing.T) {
req := require.New(t)

datasource, err := New("", CustomMetricsNamespaces("ns1", "ns2"))

req.NoError(err)
req.Equal("ns1,ns2", datasource.builder.JSONData.(map[string]interface{})["customMetricsNamespaces"])
}

0 comments on commit e25e564

Please sign in to comment.