diff --git a/metrics-operator/controllers/common/providers/dynatrace/common.go b/metrics-operator/controllers/common/providers/dynatrace/common.go index bded16027c..2f3aacb8aa 100644 --- a/metrics-operator/controllers/common/providers/dynatrace/common.go +++ b/metrics-operator/controllers/common/providers/dynatrace/common.go @@ -4,6 +4,8 @@ import ( "context" "errors" "fmt" + "net/url" + "strings" metricsapi "github.com/keptn/lifecycle-toolkit/metrics-operator/api/v1alpha3" corev1 "k8s.io/api/core/v1" @@ -37,3 +39,22 @@ func getDTSecret(ctx context.Context, provider metricsapi.KeptnMetricsProvider, } return string(token), nil } + +func urlEncodeQuery(query string) string { + params := strings.Split(query, "&") + + result := "" + + for i, param := range params { + keyAndValue := strings.Split(param, "=") + if len(keyAndValue) == 2 { + encodedKeyAndValue := keyAndValue[0] + "=" + url.QueryEscape(keyAndValue[1]) + if i > 0 { + result += "&" + } + result += encodedKeyAndValue + } + } + + return result +} diff --git a/metrics-operator/controllers/common/providers/dynatrace/common_test.go b/metrics-operator/controllers/common/providers/dynatrace/common_test.go index 4a5d9b4006..04fa73f910 100644 --- a/metrics-operator/controllers/common/providers/dynatrace/common_test.go +++ b/metrics-operator/controllers/common/providers/dynatrace/common_test.go @@ -67,3 +67,42 @@ func TestGetSecret_NoTokenData(t *testing.T) { require.ErrorIs(t, e, ErrSecretKeyRefNotDefined) require.Empty(t, r) } + +func Test_urlEncodeQuery(t *testing.T) { + type args struct { + query string + } + tests := []struct { + name string + args args + want string + }{ + { + name: "encode single parameter", + args: args{ + query: "metricSelector=my:metric-selector", + }, + want: "metricSelector=my%3Ametric-selector", + }, + { + name: "encode multiple parameters", + args: args{ + query: "metricSelector=my:metric-selector&from=now-2h", + }, + want: "metricSelector=my%3Ametric-selector&from=now-2h", + }, + { + name: "omit wrongly formatted input", + args: args{ + query: "metricSelector=my:metric-selector&from", + }, + want: "metricSelector=my%3Ametric-selector", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := urlEncodeQuery(tt.args.query) + require.Equal(t, tt.want, got) + }) + } +} diff --git a/metrics-operator/controllers/common/providers/dynatrace/dynatrace.go b/metrics-operator/controllers/common/providers/dynatrace/dynatrace.go index f03a5bdac6..886d031369 100644 --- a/metrics-operator/controllers/common/providers/dynatrace/dynatrace.go +++ b/metrics-operator/controllers/common/providers/dynatrace/dynatrace.go @@ -6,7 +6,6 @@ import ( "fmt" "io" "net/http" - "net/url" "reflect" "strings" "time" @@ -42,14 +41,17 @@ type DynatraceData struct { // EvaluateQuery fetches the SLI values from dynatrace provider func (d *KeptnDynatraceProvider) EvaluateQuery(ctx context.Context, metric metricsapi.KeptnMetric, provider metricsapi.KeptnMetricsProvider) (string, []byte, error) { baseURL := d.normalizeAPIURL(provider.Spec.TargetServer) - query := url.QueryEscape(metric.Spec.Query) + var qURL string if metric.Spec.Range != nil { - qURL = baseURL + "v2/metrics/query?metricSelector=" + query + "&from=now-" + metric.Spec.Range.Interval + qURL = "metricSelector=" + metric.Spec.Query + "&from=now-" + metric.Spec.Range.Interval } else { - qURL = baseURL + "v2/metrics/query?metricSelector=" + query + qURL = "metricSelector=" + metric.Spec.Query } + qURL = urlEncodeQuery(qURL) + qURL = baseURL + "v2/metrics/query?" + qURL + d.Log.Info("Running query: " + qURL) ctx, cancel := context.WithTimeout(ctx, 20*time.Second) defer cancel() @@ -66,8 +68,10 @@ func (d *KeptnDynatraceProvider) EvaluateQueryForStep(ctx context.Context, metri return nil, nil, fmt.Errorf("spec.range is not defined!") } baseURL := d.normalizeAPIURL(provider.Spec.TargetServer) - query := url.QueryEscape(metric.Spec.Query) - qURL := baseURL + "v2/metrics/query?metricSelector=" + query + "&from=now-" + metric.Spec.Range.Interval + "&resolution=" + metric.Spec.Range.Step + qURL := "metricSelector=" + metric.Spec.Query + "&from=now-" + metric.Spec.Range.Interval + "&resolution=" + metric.Spec.Range.Step + + qURL = urlEncodeQuery(qURL) + qURL = baseURL + "v2/metrics/query?" + qURL d.Log.Info("Running query: " + qURL) ctx, cancel := context.WithTimeout(ctx, 20*time.Second) @@ -161,7 +165,7 @@ func (d *KeptnDynatraceProvider) getResultSlice(result *DynatraceResponse) []str for _, points := range r.Data { for _, v := range points.Values { if v != nil { - totalValues = totalValues + 1 + totalValues++ } } } diff --git a/metrics-operator/controllers/common/providers/dynatrace/dynatrace_test.go b/metrics-operator/controllers/common/providers/dynatrace/dynatrace_test.go index a32c356993..2477445cb6 100644 --- a/metrics-operator/controllers/common/providers/dynatrace/dynatrace_test.go +++ b/metrics-operator/controllers/common/providers/dynatrace/dynatrace_test.go @@ -2,7 +2,6 @@ package dynatrace import ( "context" - "fmt" "net/http" "net/http/httptest" "strings" @@ -223,18 +222,28 @@ func TestNormalizeURL(t *testing.T) { } } -func TestEvaluateQuery_CorrectHTTP(t *testing.T) { - const query = "my-query" +func TestEvaluateQuery_MetricWithoutRange(t *testing.T) { svr := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { _, err := w.Write([]byte(dtpayload)) require.Nil(t, err) require.Equal(t, "GET", r.Method) require.Equal(t, "/api/v2/metrics/query", r.URL.Path) - require.True(t, strings.HasSuffix(r.RequestURI, query)) + require.Equal(t, "my-query", r.URL.Query().Get("metricSelector")) + require.Equal(t, "now-2h", r.URL.Query().Get("from")) require.Equal(t, 1, len(r.Header["Authorization"])) })) defer svr.Close() - kdp, objects := setupTest() + + apiTokenSecret := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "myapitoken", + Namespace: "", + }, + Data: map[string][]byte{ + "mykey": []byte("secret-value"), + }, + } + p := metricsapi.KeptnMetricsProvider{ Spec: metricsapi.KeptnMetricsProviderSpec{ SecretKeyRef: v1.SecretKeySelector{ @@ -246,12 +255,82 @@ func TestEvaluateQuery_CorrectHTTP(t *testing.T) { TargetServer: svr.URL, }, } - for _, obj := range objects { - r, raw, e := kdp.EvaluateQuery(context.TODO(), obj, p) - require.True(t, errors.IsNotFound(e)) - require.Equal(t, []byte(nil), raw) - require.Equal(t, "", r) + + keptnMetric := metricsapi.KeptnMetric{ + Spec: metricsapi.KeptnMetricSpec{ + Query: "my-query&from=now-2h", + }, } + + fakeClient := fake.NewClient(apiTokenSecret) + + kdp := KeptnDynatraceProvider{ + HttpClient: http.Client{}, + Log: ctrl.Log.WithName("testytest"), + K8sClient: fakeClient, + } + + r, raw, err := kdp.EvaluateQuery(context.TODO(), keptnMetric, p) + require.Nil(t, err) + require.Equal(t, []byte(dtpayload), raw) + require.Equal(t, "50.000000", r) +} + +func TestEvaluateQuery_MetricWithRange(t *testing.T) { + svr := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + _, err := w.Write([]byte(dtpayload)) + require.Nil(t, err) + require.Equal(t, "GET", r.Method) + require.Equal(t, "/api/v2/metrics/query", r.URL.Path) + require.Equal(t, "my-query", r.URL.Query().Get("metricSelector")) + require.Equal(t, "now-5m", r.URL.Query().Get("from")) + require.Equal(t, 1, len(r.Header["Authorization"])) + })) + defer svr.Close() + + apiTokenSecret := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "myapitoken", + Namespace: "", + }, + Data: map[string][]byte{ + "mykey": []byte("secret-value"), + }, + } + + p := metricsapi.KeptnMetricsProvider{ + Spec: metricsapi.KeptnMetricsProviderSpec{ + SecretKeyRef: v1.SecretKeySelector{ + LocalObjectReference: v1.LocalObjectReference{ + Name: "myapitoken", + }, + Key: "mykey", + }, + TargetServer: svr.URL, + }, + } + + keptnMetric := metricsapi.KeptnMetric{ + Spec: metricsapi.KeptnMetricSpec{ + Query: "my-query", + Range: &metricsapi.RangeSpec{ + Interval: "5m", + }, + }, + } + + fakeClient := fake.NewClient(apiTokenSecret) + + kdp := KeptnDynatraceProvider{ + HttpClient: http.Client{}, + Log: ctrl.Log.WithName("testytest"), + K8sClient: fakeClient, + } + + r, raw, err := kdp.EvaluateQuery(context.TODO(), keptnMetric, p) + require.Nil(t, err) + require.Equal(t, []byte(dtpayload), raw) + require.Equal(t, "50.000000", r) } func TestEvaluateQuery_APIError(t *testing.T) { @@ -271,7 +350,14 @@ func TestEvaluateQuery_APIError(t *testing.T) { secretKey: []byte(secretValue), }, } - kdp, objects := setupTest(apiToken) + kdp := setupTest(apiToken) + + keptnMetric := metricsapi.KeptnMetric{ + Spec: metricsapi.KeptnMetricSpec{ + Query: "my-query&from=now-2h", + }, + } + p := metricsapi.KeptnMetricsProvider{ Spec: metricsapi.KeptnMetricsProviderSpec{ SecretKeyRef: v1.SecretKeySelector{ @@ -283,14 +369,13 @@ func TestEvaluateQuery_APIError(t *testing.T) { TargetServer: svr.URL, }, } - for _, obj := range objects { - r, raw, e := kdp.EvaluateQuery(context.TODO(), obj, p) - require.Equal(t, "", r) - t.Log(string(raw)) - require.Equal(t, errorResponse, raw) //we still return the raw answer to help user debug - require.NotNil(t, e) - require.Contains(t, e.Error(), "Token is missing required scope.") - } + r, raw, e := kdp.EvaluateQuery(context.TODO(), keptnMetric, p) + require.NotNil(t, e) + require.Contains(t, e.Error(), "Token is missing required scope.") + require.Equal(t, "", r) + t.Log(string(raw)) + require.Equal(t, errorResponse, raw) //we still return the raw answer to help user debug + } func TestEvaluateQuery_WrongPayloadHandling(t *testing.T) { @@ -310,7 +395,14 @@ func TestEvaluateQuery_WrongPayloadHandling(t *testing.T) { }, } - kdp, objects := setupTest(apiToken) + kdp := setupTest(apiToken) + + keptnMetric := metricsapi.KeptnMetric{ + Spec: metricsapi.KeptnMetricSpec{ + Query: "my-query&from=now-2h", + }, + } + p := metricsapi.KeptnMetricsProvider{ Spec: metricsapi.KeptnMetricsProviderSpec{ SecretKeyRef: v1.SecretKeySelector{ @@ -322,13 +414,12 @@ func TestEvaluateQuery_WrongPayloadHandling(t *testing.T) { TargetServer: svr.URL, }, } - for _, obj := range objects { - r, raw, e := kdp.EvaluateQuery(context.TODO(), obj, p) - require.Equal(t, "", r) - t.Log(string(raw), e) - require.Equal(t, []byte("garbage"), raw) //we still return the raw answer to help user debug - require.NotNil(t, e) - } + + r, raw, e := kdp.EvaluateQuery(context.TODO(), keptnMetric, p) + require.Equal(t, "", r) + t.Log(string(raw), e) + require.Equal(t, []byte("garbage"), raw) //we still return the raw answer to help user debug + require.NotNil(t, e) } func TestEvaluateQuery_MissingSecret(t *testing.T) { @@ -337,18 +428,24 @@ func TestEvaluateQuery_MissingSecret(t *testing.T) { require.Nil(t, err) })) defer svr.Close() - kdp, objects := setupTest() + kdp := setupTest() + + keptnMetric := metricsapi.KeptnMetric{ + Spec: metricsapi.KeptnMetricSpec{ + Query: "my-query&from=now-2h", + }, + } p := metricsapi.KeptnMetricsProvider{ Spec: metricsapi.KeptnMetricsProviderSpec{ TargetServer: svr.URL, }, } - for _, obj := range objects { - _, _, e := kdp.EvaluateQuery(context.TODO(), obj, p) - require.NotNil(t, e) - require.ErrorIs(t, e, ErrSecretKeyRefNotDefined) - } + + _, _, e := kdp.EvaluateQuery(context.TODO(), keptnMetric, p) + require.NotNil(t, e) + require.ErrorIs(t, e, ErrSecretKeyRefNotDefined) + } func TestEvaluateQuery_SecretNotFound(t *testing.T) { @@ -357,7 +454,13 @@ func TestEvaluateQuery_SecretNotFound(t *testing.T) { require.Nil(t, err) })) defer svr.Close() - kdp, objects := setupTest() + kdp := setupTest() + + keptnMetric := metricsapi.KeptnMetric{ + Spec: metricsapi.KeptnMetricSpec{ + Query: "my-query&from=now-2h", + }, + } p := metricsapi.KeptnMetricsProvider{ Spec: metricsapi.KeptnMetricsProviderSpec{ @@ -370,11 +473,10 @@ func TestEvaluateQuery_SecretNotFound(t *testing.T) { TargetServer: svr.URL, }, } - for _, obj := range objects { - _, _, e := kdp.EvaluateQuery(context.TODO(), obj, p) - require.NotNil(t, e) - require.True(t, errors.IsNotFound(e)) - } + + _, _, e := kdp.EvaluateQuery(context.TODO(), keptnMetric, p) + require.NotNil(t, e) + require.True(t, errors.IsNotFound(e)) } func TestEvaluateQuery_RefNotExistingKey(t *testing.T) { @@ -393,113 +495,69 @@ func TestEvaluateQuery_RefNotExistingKey(t *testing.T) { secretKey: []byte(secretValue), }, } - kdp, objects := setupTest(apiToken) + kdp := setupTest(apiToken) - missingKey := "key_not_found" - p := metricsapi.KeptnMetricsProvider{ - Spec: metricsapi.KeptnMetricsProviderSpec{ - SecretKeyRef: v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: secretName, - }, - Key: missingKey, - }, - TargetServer: svr.URL, - }, - } - for _, obj := range objects { - _, _, e := kdp.EvaluateQuery(context.TODO(), obj, p) - require.NotNil(t, e) - require.True(t, strings.Contains(e.Error(), "invalid key "+missingKey)) - } -} - -func TestEvaluateQuery_HappyPath(t *testing.T) { - svr := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - _, err := w.Write([]byte(dtpayload)) - require.Nil(t, err) - })) - defer svr.Close() - secretName, secretKey, secretValue := "secretName", "secretKey", "secretValue" - apiToken := &corev1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: secretName, - Namespace: "", - }, - Data: map[string][]byte{ - secretKey: []byte(secretValue), + keptnMetric := metricsapi.KeptnMetric{ + Spec: metricsapi.KeptnMetricSpec{ + Query: "my-query&from=now-2h", }, } - kdp, objects := setupTest(apiToken) + missingKey := "key_not_found" p := metricsapi.KeptnMetricsProvider{ Spec: metricsapi.KeptnMetricsProviderSpec{ SecretKeyRef: v1.SecretKeySelector{ LocalObjectReference: v1.LocalObjectReference{ Name: secretName, }, - Key: secretKey, + Key: missingKey, }, TargetServer: svr.URL, }, } - for _, obj := range objects { - r, raw, e := kdp.EvaluateQuery(context.TODO(), obj, p) - require.Nil(t, e) - require.Equal(t, []byte(dtpayload), raw) - require.Equal(t, fmt.Sprintf("%f", 50.0), r) - } + + _, _, e := kdp.EvaluateQuery(context.TODO(), keptnMetric, p) + require.NotNil(t, e) + require.True(t, strings.Contains(e.Error(), "invalid key "+missingKey)) } -func TestEvaluateQuery_HappyPathForTimerange(t *testing.T) { +func TestEvaluateQueryForStep(t *testing.T) { svr := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { _, err := w.Write([]byte(dtpayload)) - p := r.URL.Query().Get("from") - require.NotNil(t, p) require.Nil(t, err) + require.Equal(t, "GET", r.Method) + require.Equal(t, "/api/v2/metrics/query", r.URL.Path) + require.Equal(t, "GET", r.Method) + require.Equal(t, "/api/v2/metrics/query", r.URL.Path) + require.Equal(t, "my-query", r.URL.Query().Get("metricSelector")) + require.Equal(t, "now-5m", r.URL.Query().Get("from")) + require.Equal(t, "1m", r.URL.Query().Get("resolution")) + require.Equal(t, 1, len(r.Header["Authorization"])) })) defer svr.Close() - secretName, secretKey, secretValue := "secretName", "secretKey", "secretValue" - apiToken := &corev1.Secret{ + + apiTokenSecret := &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ - Name: secretName, + Name: "myapitoken", Namespace: "", }, Data: map[string][]byte{ - secretKey: []byte(secretValue), + "mykey": []byte("secret-value"), }, } - kdp, obj := setupTestForTimerange(apiToken) - p := metricsapi.KeptnMetricsProvider{ - Spec: metricsapi.KeptnMetricsProviderSpec{ - SecretKeyRef: v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: secretName, - }, - Key: secretKey, + kdp := setupTest(apiTokenSecret) + + keptnMetric := metricsapi.KeptnMetric{ + Spec: metricsapi.KeptnMetricSpec{ + Query: "my-query", + Range: &metricsapi.RangeSpec{ + Interval: "5m", + Step: "1m", + Aggregation: "max", }, - TargetServer: svr.URL, }, } - r, raw, e := kdp.EvaluateQuery(context.TODO(), obj, p) - require.Nil(t, e) - require.Equal(t, []byte(dtpayload), raw) - require.Equal(t, fmt.Sprintf("%f", 50.0), r) -} - -func TestEvaluateQueryForStep_CorrectHTTP(t *testing.T) { - const query = "my-query" - svr := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - _, err := w.Write([]byte(dtpayload)) - require.Nil(t, err) - require.Equal(t, "GET", r.Method) - require.Equal(t, "/api/v2/metrics/query", r.URL.Path) - require.True(t, strings.HasSuffix(r.RequestURI, query)) - require.Equal(t, 1, len(r.Header["Authorization"])) - })) - defer svr.Close() - kdp, obj := setupTestForTimerangeWithStep() p := metricsapi.KeptnMetricsProvider{ Spec: metricsapi.KeptnMetricsProviderSpec{ SecretKeyRef: v1.SecretKeySelector{ @@ -511,10 +569,10 @@ func TestEvaluateQueryForStep_CorrectHTTP(t *testing.T) { TargetServer: svr.URL, }, } - r, raw, e := kdp.EvaluateQueryForStep(context.TODO(), obj, p) - require.True(t, errors.IsNotFound(e)) - require.Equal(t, []byte(nil), raw) - require.Equal(t, []string(nil), r) + r, raw, err := kdp.EvaluateQueryForStep(context.TODO(), keptnMetric, p) + require.Nil(t, err) + require.Equal(t, []byte(dtpayload), raw) + require.Equal(t, []string{"50.000000", "50.000000", "50.000000", "50.000000", "50.000000", "50.000000", "50.000000", "50.000000"}, r) } func TestEvaluateQueryForStep_APIError(t *testing.T) { @@ -534,7 +592,19 @@ func TestEvaluateQueryForStep_APIError(t *testing.T) { secretKey: []byte(secretValue), }, } - kdp, obj := setupTestForTimerangeWithStep(apiToken) + kdp := setupTest(apiToken) + + keptnMetric := metricsapi.KeptnMetric{ + Spec: metricsapi.KeptnMetricSpec{ + Query: "my-query", + Range: &metricsapi.RangeSpec{ + Interval: "5m", + Step: "1m", + Aggregation: "max", + }, + }, + } + p := metricsapi.KeptnMetricsProvider{ Spec: metricsapi.KeptnMetricsProviderSpec{ SecretKeyRef: v1.SecretKeySelector{ @@ -546,7 +616,7 @@ func TestEvaluateQueryForStep_APIError(t *testing.T) { TargetServer: svr.URL, }, } - r, raw, e := kdp.EvaluateQueryForStep(context.TODO(), obj, p) + r, raw, e := kdp.EvaluateQueryForStep(context.TODO(), keptnMetric, p) require.Equal(t, []string(nil), r) t.Log(string(raw)) require.Equal(t, errorResponse, raw) //we still return the raw answer to help user debug @@ -571,7 +641,18 @@ func TestEvaluateQueryForStep_WrongPayloadHandling(t *testing.T) { }, } - kdp, obj := setupTestForTimerangeWithStep(apiToken) + kdp := setupTest(apiToken) + + keptnMetric := metricsapi.KeptnMetric{ + Spec: metricsapi.KeptnMetricSpec{ + Query: "my-query", + Range: &metricsapi.RangeSpec{ + Interval: "5m", + Step: "1m", + Aggregation: "max", + }, + }, + } p := metricsapi.KeptnMetricsProvider{ Spec: metricsapi.KeptnMetricsProviderSpec{ SecretKeyRef: v1.SecretKeySelector{ @@ -583,7 +664,7 @@ func TestEvaluateQueryForStep_WrongPayloadHandling(t *testing.T) { TargetServer: svr.URL, }, } - r, raw, e := kdp.EvaluateQueryForStep(context.TODO(), obj, p) + r, raw, e := kdp.EvaluateQueryForStep(context.TODO(), keptnMetric, p) require.Equal(t, []string(nil), r) t.Log(string(raw), e) require.Equal(t, []byte("garbage"), raw) //we still return the raw answer to help user debug @@ -596,14 +677,25 @@ func TestEvaluateQueryForStep_MissingSecret(t *testing.T) { require.Nil(t, err) })) defer svr.Close() - kdp, obj := setupTestForTimerangeWithStep() + kdp := setupTest() + + keptnMetric := metricsapi.KeptnMetric{ + Spec: metricsapi.KeptnMetricSpec{ + Query: "my-query", + Range: &metricsapi.RangeSpec{ + Interval: "5m", + Step: "1m", + Aggregation: "max", + }, + }, + } p := metricsapi.KeptnMetricsProvider{ Spec: metricsapi.KeptnMetricsProviderSpec{ TargetServer: svr.URL, }, } - _, _, e := kdp.EvaluateQueryForStep(context.TODO(), obj, p) + _, _, e := kdp.EvaluateQueryForStep(context.TODO(), keptnMetric, p) require.NotNil(t, e) require.ErrorIs(t, e, ErrSecretKeyRefNotDefined) } @@ -614,7 +706,18 @@ func TestEvaluateQueryForStep_SecretNotFound(t *testing.T) { require.Nil(t, err) })) defer svr.Close() - kdp, obj := setupTestForTimerangeWithStep() + kdp := setupTest() + + keptnMetric := metricsapi.KeptnMetric{ + Spec: metricsapi.KeptnMetricSpec{ + Query: "my-query", + Range: &metricsapi.RangeSpec{ + Interval: "5m", + Step: "1m", + Aggregation: "max", + }, + }, + } p := metricsapi.KeptnMetricsProvider{ Spec: metricsapi.KeptnMetricsProviderSpec{ @@ -627,7 +730,7 @@ func TestEvaluateQueryForStep_SecretNotFound(t *testing.T) { TargetServer: svr.URL, }, } - _, _, e := kdp.EvaluateQueryForStep(context.TODO(), obj, p) + _, _, e := kdp.EvaluateQueryForStep(context.TODO(), keptnMetric, p) require.NotNil(t, e) require.True(t, errors.IsNotFound(e)) } @@ -648,88 +751,37 @@ func TestEvaluateQueryForStep_RefNotExistingKey(t *testing.T) { secretKey: []byte(secretValue), }, } - kdp, obj := setupTestForTimerangeWithStep(apiToken) + kdp := setupTest(apiToken) - missingKey := "key_not_found" - p := metricsapi.KeptnMetricsProvider{ - Spec: metricsapi.KeptnMetricsProviderSpec{ - SecretKeyRef: v1.SecretKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: secretName, - }, - Key: missingKey, + keptnMetric := metricsapi.KeptnMetric{ + Spec: metricsapi.KeptnMetricSpec{ + Query: "my-query", + Range: &metricsapi.RangeSpec{ + Interval: "5m", + Step: "1m", + Aggregation: "max", }, - TargetServer: svr.URL, - }, - } - _, _, e := kdp.EvaluateQueryForStep(context.TODO(), obj, p) - require.NotNil(t, e) - require.True(t, strings.Contains(e.Error(), "invalid key "+missingKey)) -} - -func TestEvaluateQuery_HappyPathForTimerangeWithStep(t *testing.T) { - svr := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - _, err := w.Write([]byte(dtpayload)) - p := r.URL.Query().Get("from") - require.NotNil(t, p) - require.Nil(t, err) - })) - defer svr.Close() - secretName, secretKey, secretValue := "secretName", "secretKey", "secretValue" - apiToken := &corev1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: secretName, - Namespace: "", - }, - Data: map[string][]byte{ - secretKey: []byte(secretValue), }, } - kdp, obj := setupTestForTimerangeWithStep(apiToken) + missingKey := "key_not_found" p := metricsapi.KeptnMetricsProvider{ Spec: metricsapi.KeptnMetricsProviderSpec{ SecretKeyRef: v1.SecretKeySelector{ LocalObjectReference: v1.LocalObjectReference{ Name: secretName, }, - Key: secretKey, + Key: missingKey, }, TargetServer: svr.URL, }, } - r, raw, e := kdp.EvaluateQueryForStep(context.TODO(), obj, p) - require.Nil(t, e) - require.Equal(t, []byte(dtpayload), raw) - require.Equal(t, []string{"50.000000", "50.000000", "50.000000", "50.000000", "50.000000", "50.000000", "50.000000", "50.000000"}, r) -} - -func setupTest(objs ...client.Object) (KeptnDynatraceProvider, []metricsapi.KeptnMetric) { - - fakeClient := fake.NewClient(objs...) - - kdp := KeptnDynatraceProvider{ - HttpClient: http.Client{}, - Log: ctrl.Log.WithName("testytest"), - K8sClient: fakeClient, - } - objects := []metricsapi.KeptnMetric{ - { - Spec: metricsapi.KeptnMetricSpec{ - Query: "my-query", - }, - }, - { - Spec: metricsapi.KeptnMetricSpec{ - Query: "my-query", - Range: &metricsapi.RangeSpec{Interval: "5m"}, - }, - }, - } - return kdp, objects + _, _, e := kdp.EvaluateQueryForStep(context.TODO(), keptnMetric, p) + require.NotNil(t, e) + require.True(t, strings.Contains(e.Error(), "invalid key "+missingKey)) } -func setupTestForTimerange(objs ...client.Object) (KeptnDynatraceProvider, metricsapi.KeptnMetric) { +func setupTest(objs ...client.Object) KeptnDynatraceProvider { fakeClient := fake.NewClient(objs...) @@ -738,33 +790,6 @@ func setupTestForTimerange(objs ...client.Object) (KeptnDynatraceProvider, metri Log: ctrl.Log.WithName("testytest"), K8sClient: fakeClient, } - obj := metricsapi.KeptnMetric{ - Spec: metricsapi.KeptnMetricSpec{ - Query: "my-query", - Range: &metricsapi.RangeSpec{Interval: "5m"}, - }, - } - return kdp, obj -} - -func setupTestForTimerangeWithStep(objs ...client.Object) (KeptnDynatraceProvider, metricsapi.KeptnMetric) { - fakeClient := fake.NewClient(objs...) - - kdp := KeptnDynatraceProvider{ - HttpClient: http.Client{}, - Log: ctrl.Log.WithName("testytest"), - K8sClient: fakeClient, - } - obj := metricsapi.KeptnMetric{ - Spec: metricsapi.KeptnMetricSpec{ - Query: "my-query", - Range: &metricsapi.RangeSpec{ - Interval: "5m", - Step: "1m", - Aggregation: "max", - }, - }, - } - return kdp, obj + return kdp }