diff --git a/artifacts/flagger/crd.yaml b/artifacts/flagger/crd.yaml index dcf0ae85..0c37ebc3 100644 --- a/artifacts/flagger/crd.yaml +++ b/artifacts/flagger/crd.yaml @@ -733,7 +733,6 @@ spec: type: object required: - type - - address properties: type: description: Type of this provider @@ -755,6 +754,9 @@ spec: name: description: Name of the Kubernetes secret type: string + region: + description: Region of the provider + type: string query: description: Query of this metric template type: string diff --git a/charts/flagger/crds/crd.yaml b/charts/flagger/crds/crd.yaml index dcf0ae85..0c37ebc3 100644 --- a/charts/flagger/crds/crd.yaml +++ b/charts/flagger/crds/crd.yaml @@ -733,7 +733,6 @@ spec: type: object required: - type - - address properties: type: description: Type of this provider @@ -755,6 +754,9 @@ spec: name: description: Name of the Kubernetes secret type: string + region: + description: Region of the provider + type: string query: description: Query of this metric template type: string diff --git a/kustomize/base/flagger/crd.yaml b/kustomize/base/flagger/crd.yaml index dcf0ae85..0c37ebc3 100644 --- a/kustomize/base/flagger/crd.yaml +++ b/kustomize/base/flagger/crd.yaml @@ -733,7 +733,6 @@ spec: type: object required: - type - - address properties: type: description: Type of this provider @@ -755,6 +754,9 @@ spec: name: description: Name of the Kubernetes secret type: string + region: + description: Region of the provider + type: string query: description: Query of this metric template type: string diff --git a/pkg/apis/flagger/v1beta1/metric.go b/pkg/apis/flagger/v1beta1/metric.go index a2bbdb32..549fcfb3 100644 --- a/pkg/apis/flagger/v1beta1/metric.go +++ b/pkg/apis/flagger/v1beta1/metric.go @@ -64,11 +64,16 @@ type MetricTemplateProvider struct { Type string `json:"type,omitempty"` // HTTP(S) address of this provider + // +optional Address string `json:"address,omitempty"` // Secret reference containing the provider credentials // +optional SecretRef *corev1.LocalObjectReference `json:"secretRef,omitempty"` + + // Region of the provider + // +optional + Region string `json:"region,omitempty"` } // MetricTemplateModel is the query template model diff --git a/pkg/metrics/providers/cloudwatch.go b/pkg/metrics/providers/cloudwatch.go index 0fba546b..f5c3acbd 100644 --- a/pkg/metrics/providers/cloudwatch.go +++ b/pkg/metrics/providers/cloudwatch.go @@ -4,7 +4,6 @@ import ( "encoding/json" "fmt" "net/http" - "strings" "time" "github.com/aws/aws-sdk-go/aws" @@ -33,14 +32,16 @@ type cloudWatchClient interface { // NewCloudWatchProvider takes a metricInterval, a provider spec and the credentials map, and // returns a cloudWatchProvider ready to execute queries against the AWS CloudWatch metrics func NewCloudWatchProvider(metricInterval string, provider flaggerv1.MetricTemplateProvider) (*CloudWatchProvider, error) { - region := strings.TrimLeft(provider.Address, "monitoring.") - region = strings.TrimRight(region, ".amazonaws.com") - sess, err := session.NewSession( - aws.NewConfig(). - WithRegion(region). - WithMaxRetries(cloudWatchMaxRetries). - WithEndpoint(provider.Address), - ) + if provider.Region == "" { + return nil, fmt.Errorf("region not specified") + } + + sess, err := session.NewSession(aws.NewConfig(). + WithRegion(provider.Region).WithMaxRetries(cloudWatchMaxRetries)) + + if err != nil { + return nil, fmt.Errorf("error creating aws session: %s", err.Error()) + } md, err := time.ParseDuration(metricInterval) if err != nil { diff --git a/pkg/metrics/providers/cloudwatch_test.go b/pkg/metrics/providers/cloudwatch_test.go index 4952dc44..58cfb3e2 100644 --- a/pkg/metrics/providers/cloudwatch_test.go +++ b/pkg/metrics/providers/cloudwatch_test.go @@ -9,6 +9,7 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/service/cloudwatch" + "github.com/aws/aws-sdk-go/service/costandusagereportservice" flaggerv1 "github.com/weaveworks/flagger/pkg/apis/flagger/v1beta1" ) @@ -23,19 +24,28 @@ func (c cloudWatchClientMock) GetMetricData(_ *cloudwatch.GetMetricDataInput) (* } func TestNewCloudWatchProvider(t *testing.T) { - p, err := NewCloudWatchProvider( - "5m", - flaggerv1.MetricTemplateProvider{ - Address: "monitoring.ap-northeast-1.amazonaws.com", - }) + t.Run("ok", func(t *testing.T) { + p, err := NewCloudWatchProvider( + "5m", + flaggerv1.MetricTemplateProvider{ + Region: costandusagereportservice.AWSRegionApEast1, + }) - if err != nil { - t.Fatal(err) - } + if err != nil { + t.Fatal(err) + } - if exp := 5 * 60 * time.Second * cloudWatchStartDeltaMultiplierOnMetricInterval; p.startDelta != exp { - t.Fatalf("expected %d but got %d", exp, p.startDelta) - } + if exp := 5 * 60 * time.Second * cloudWatchStartDeltaMultiplierOnMetricInterval; p.startDelta != exp { + t.Fatalf("expected %d but got %d", exp, p.startDelta) + } + }) + + t.Run("ng", func(t *testing.T) { + _, err := NewCloudWatchProvider("5m", flaggerv1.MetricTemplateProvider{}) + if err == nil { + t.Fatal("error expected since region was not specified") + } + }) } func TestCloudWatchProvider_IsOnline(t *testing.T) { diff --git a/pkg/metrics/providers/prometheus.go b/pkg/metrics/providers/prometheus.go index 8fe215d8..bd781529 100644 --- a/pkg/metrics/providers/prometheus.go +++ b/pkg/metrics/providers/prometheus.go @@ -39,7 +39,7 @@ type prometheusResponse struct { // returns a Prometheus client ready to execute queries against the API func NewPrometheusProvider(provider flaggerv1.MetricTemplateProvider, credentials map[string][]byte) (*PrometheusProvider, error) { promURL, err := url.Parse(provider.Address) - if err != nil { + if provider.Address == "" || err != nil { return nil, fmt.Errorf("%s address %s is not a valid URL", provider.Type, provider.Address) }