From eab99be055cff27cab44e76955d8a6611807aaeb Mon Sep 17 00:00:00 2001 From: Ariadna Rouco Date: Tue, 20 Aug 2024 14:15:51 +0200 Subject: [PATCH] added tests for findCredential method. --- metricproviders/datadog/datadogV1_test.go | 199 +++++++--------------- metricproviders/datadog/datadog_test.go | 70 +++++++- metricproviders/datadog/finders_test.go | 11 ++ 3 files changed, 141 insertions(+), 139 deletions(-) diff --git a/metricproviders/datadog/datadogV1_test.go b/metricproviders/datadog/datadogV1_test.go index 80127b9a08..1e10d02137 100644 --- a/metricproviders/datadog/datadogV1_test.go +++ b/metricproviders/datadog/datadogV1_test.go @@ -12,20 +12,41 @@ import ( log "github.com/sirupsen/logrus" "github.com/stretchr/testify/assert" corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" k8sfake "k8s.io/client-go/kubernetes/fake" kubetesting "k8s.io/client-go/testing" ) -const ( - ExpectedApiKey = "0123456789abcdef0123456789abcdef" - ExpectedAppKey = "0123456789abcdef0123456789abcdef01234567" -) - func TestRunSuite(t *testing.T) { + const expectedApiKey = "0123456789abcdef0123456789abcdef" + const expectedAppKey = "0123456789abcdef0123456789abcdef01234567" unixNow = func() int64 { return 1599076435 } + ddProviderIntervalDefault := v1alpha1.MetricProvider{ + Datadog: &v1alpha1.DatadogMetric{ + Query: "avg:kubernetes.cpu.user.total{*}", + }, + } + ddProviderInterval10m := v1alpha1.MetricProvider{ + Datadog: &v1alpha1.DatadogMetric{ + Query: "avg:kubernetes.cpu.user.total{*}", + Interval: "10m", + }, + } + + ddProviderNamespacedSecret := v1alpha1.MetricProvider{ + Datadog: &v1alpha1.DatadogMetric{ + Query: "avg:kubernetes.cpu.user.total{*}", + Interval: "10m", + SecretRef: v1alpha1.SecretRef{ + Name: "secret", + Namespaced: true, + }, + }, + } + // Test Cases tests := []struct { name string @@ -38,8 +59,6 @@ func TestRunSuite(t *testing.T) { expectedPhase v1alpha1.AnalysisPhase expectedErrorMessage string expectedErrorProvider bool - expectedApiKey string - expectedAppKey string useEnvVarForKeys bool }{ // When last value of time series matches condition then succeed. @@ -50,13 +69,11 @@ func TestRunSuite(t *testing.T) { Name: "foo", SuccessCondition: "result < 0.001", FailureCondition: "result >= 0.001", - Provider: ddProviderInterval10m(), + Provider: ddProviderInterval10m, }, expectedIntervalSeconds: 600, expectedValue: "0.0003332881882246533", expectedPhase: v1alpha1.AnalysisPhaseSuccessful, - expectedApiKey: ExpectedApiKey, - expectedAppKey: ExpectedAppKey, useEnvVarForKeys: false, }, // Same test as above, but derive DD keys from env var instead of k8s secret @@ -67,13 +84,11 @@ func TestRunSuite(t *testing.T) { Name: "foo", SuccessCondition: "result < 0.001", FailureCondition: "result >= 0.001", - Provider: ddProviderInterval10m(), + Provider: ddProviderInterval10m, }, expectedIntervalSeconds: 600, expectedValue: "0.0003332881882246533", expectedPhase: v1alpha1.AnalysisPhaseSuccessful, - expectedApiKey: ExpectedApiKey, - expectedAppKey: ExpectedAppKey, useEnvVarForKeys: true, }, // When last value of time series does not match condition then fail. @@ -84,13 +99,11 @@ func TestRunSuite(t *testing.T) { Name: "foo", SuccessCondition: "result < 0.001", FailureCondition: "result >= 0.001", - Provider: ddProviderIntervalDefault(), + Provider: ddProviderIntervalDefault, }, expectedIntervalSeconds: 300, expectedValue: "0.006121378742186943", expectedPhase: v1alpha1.AnalysisPhaseFailed, - expectedApiKey: ExpectedApiKey, - expectedAppKey: ExpectedAppKey, useEnvVarForKeys: false, }, // Error if the request is invalid @@ -101,12 +114,10 @@ func TestRunSuite(t *testing.T) { Name: "foo", SuccessCondition: "result < 0.001", FailureCondition: "result >= 0.001", - Provider: ddProviderIntervalDefault(), + Provider: ddProviderIntervalDefault, }, expectedIntervalSeconds: 300, expectedPhase: v1alpha1.AnalysisPhaseError, - expectedApiKey: ExpectedApiKey, - expectedAppKey: ExpectedAppKey, expectedErrorMessage: "received non 2xx response code: 400 {\"status\":\"error\",\"error\":\"error messsage\"}", useEnvVarForKeys: false, }, @@ -118,98 +129,86 @@ func TestRunSuite(t *testing.T) { Name: "foo", SuccessCondition: "result < 0.001", FailureCondition: "result >= 0.001", - Provider: ddProviderIntervalDefault(), + Provider: ddProviderIntervalDefault, }, expectedIntervalSeconds: 300, expectedPhase: v1alpha1.AnalysisPhaseError, - expectedApiKey: ExpectedApiKey, - expectedAppKey: ExpectedAppKey, expectedErrorMessage: "received authentication error response code: 401 {\"errors\": [\"No authenticated user.\"]}", useEnvVarForKeys: false, }, - // Expect success with default() and data + // Expect success with Default and data { webServerStatus: 200, webServerResponse: `{"status":"ok","series":[{"pointlist":[[1598867910000,0.0020008318672513122],[1598867925000,0.006121378742186943]]}]}`, metric: v1alpha1.Metric{ Name: "foo", SuccessCondition: "default(result, 0) < 0.05", - Provider: ddProviderIntervalDefault(), + Provider: ddProviderIntervalDefault, }, expectedIntervalSeconds: 300, expectedValue: "0.006121378742186943", expectedPhase: v1alpha1.AnalysisPhaseSuccessful, - expectedApiKey: ExpectedApiKey, - expectedAppKey: ExpectedAppKey, useEnvVarForKeys: false, }, - // Expect error with no default() and no data + // Expect error with no Default and no data { webServerStatus: 200, webServerResponse: `{"status":"ok","series":[]}`, metric: v1alpha1.Metric{ Name: "foo", SuccessCondition: "result < 0.05", - Provider: ddProviderIntervalDefault(), + Provider: ddProviderIntervalDefault, }, expectedIntervalSeconds: 300, expectedPhase: v1alpha1.AnalysisPhaseError, - expectedApiKey: ExpectedApiKey, - expectedAppKey: ExpectedAppKey, expectedErrorMessage: `invalid operation: < (mismatched types and float64)`, useEnvVarForKeys: false, }, - // Expect success with default() and no data + // Expect success with Default and no data { webServerStatus: 200, webServerResponse: `{"status":"ok","series":[]}`, metric: v1alpha1.Metric{ Name: "foo", SuccessCondition: "default(result, 0) < 0.05", - Provider: ddProviderIntervalDefault(), + Provider: ddProviderIntervalDefault, }, expectedIntervalSeconds: 300, expectedValue: `[]`, expectedPhase: v1alpha1.AnalysisPhaseSuccessful, - expectedApiKey: ExpectedApiKey, - expectedAppKey: ExpectedAppKey, useEnvVarForKeys: false, }, - // Expect failure with bad default() and no data + // Expect failure with bad Default and no data { webServerStatus: 200, webServerResponse: `{"status":"ok","series":[]}`, metric: v1alpha1.Metric{ Name: "foo", SuccessCondition: "default(result, 1) < 0.05", - Provider: ddProviderIntervalDefault(), + Provider: ddProviderIntervalDefault, }, expectedIntervalSeconds: 300, expectedValue: `[]`, expectedPhase: v1alpha1.AnalysisPhaseFailed, - expectedApiKey: ExpectedApiKey, - expectedAppKey: ExpectedAppKey, useEnvVarForKeys: false, }, - // Expect success with bad default() and good data + // Expect success with bad Default and good data { webServerStatus: 200, webServerResponse: `{"status":"ok","series":[{"pointlist":[[1598867910000,0.0020008318672513122],[1598867925000,0.006121378742186943]]}]}`, metric: v1alpha1.Metric{ Name: "foo", SuccessCondition: "default(result, 1) < 0.05", - Provider: ddProviderIntervalDefault(), + Provider: ddProviderIntervalDefault, }, expectedIntervalSeconds: 300, expectedValue: `0.006121378742186943`, expectedPhase: v1alpha1.AnalysisPhaseSuccessful, - expectedApiKey: ExpectedApiKey, - expectedAppKey: ExpectedAppKey, useEnvVarForKeys: false, }, @@ -221,12 +220,10 @@ func TestRunSuite(t *testing.T) { Name: "foo", SuccessCondition: "result < 0.001", FailureCondition: "result >= 0.001", - Provider: ddProviderIntervalDefault(), + Provider: ddProviderIntervalDefault, }, expectedIntervalSeconds: 300, expectedPhase: v1alpha1.AnalysisPhaseError, - expectedApiKey: ExpectedApiKey, - expectedAppKey: ExpectedAppKey, expectedErrorMessage: "Could not parse JSON body: json: cannot unmarshal string into Go struct field datadogResponseV1.Series of type []struct { Pointlist [][]float64 \"json:\\\"pointlist\\\"\" }", useEnvVarForKeys: false, }, @@ -235,11 +232,9 @@ func TestRunSuite(t *testing.T) { { serverURL: "://wrong.schema", metric: v1alpha1.Metric{ - Provider: ddProviderInterval10m(), + Provider: ddProviderInterval10m, }, expectedPhase: v1alpha1.AnalysisPhaseError, - expectedApiKey: ExpectedApiKey, - expectedAppKey: ExpectedAppKey, expectedErrorMessage: "parse \"://wrong.schema\": missing protocol scheme", useEnvVarForKeys: false, }, @@ -251,40 +246,14 @@ func TestRunSuite(t *testing.T) { Name: "foo", SuccessCondition: "result < 0.001", FailureCondition: "result >= 0.001", - Provider: ddProviderNamespacedSecret(), + Provider: ddProviderNamespacedSecret, }, expectedIntervalSeconds: 600, expectedValue: "0.0003332881882246533", expectedPhase: v1alpha1.AnalysisPhaseSuccessful, - expectedApiKey: ExpectedApiKey, - expectedAppKey: ExpectedAppKey, useEnvVarForKeys: false, expectedErrorProvider: false, }, - // When secretRef is namespaced but no secret is not found, expect failure - { - metric: v1alpha1.Metric{ - Name: "foo", - SuccessCondition: "result < 0.001", - FailureCondition: "result >= 0.001", - Provider: ddProviderNamespacedTrue(), - }, - expectedApiKey: ExpectedApiKey, - expectedAppKey: ExpectedAppKey, - useEnvVarForKeys: false, - expectedErrorProvider: true, - }, - // When secretRef is namespaced but no secret is not found, expect failure --- - { - metric: v1alpha1.Metric{ - Name: "foo", - SuccessCondition: "result < 0.001", - FailureCondition: "result >= 0.001", - Provider: ddProviderNamespacedSecret(), - }, - useEnvVarForKeys: false, - expectedErrorProvider: true, - }, } // Run @@ -320,11 +289,11 @@ func TestRunSuite(t *testing.T) { if req.Header.Get("Content-Type") != "application/json" { t.Errorf("\nContent-Type header expected to be application/json but got %s", req.Header.Get("Content-Type")) } - if req.Header.Get("DD-API-KEY") != ExpectedApiKey { - t.Errorf("\nDD-API-KEY header expected %s but got %s", ExpectedApiKey, req.Header.Get("DD-API-KEY")) + if req.Header.Get("DD-API-KEY") != expectedApiKey { + t.Errorf("\nDD-API-KEY header expected %s but got %s", expectedApiKey, req.Header.Get("DD-API-KEY")) } - if req.Header.Get("DD-APPLICATION-KEY") != ExpectedAppKey { - t.Errorf("\nDD-APPLICATION-KEY header expected %s but got %s", ExpectedAppKey, req.Header.Get("DD-APPLICATION-KEY")) + if req.Header.Get("DD-APPLICATION-KEY") != expectedAppKey { + t.Errorf("\nDD-APPLICATION-KEY header expected %s but got %s", expectedAppKey, req.Header.Get("DD-APPLICATION-KEY")) } // Return mock response @@ -340,11 +309,20 @@ func TestRunSuite(t *testing.T) { serverURL = server.URL } - tokenSecret := newSecret(serverURL, test.expectedApiKey, test.expectedAppKey) + tokenSecret := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: DatadogTokensSecretName, + }, + Data: map[string][]byte{ + "address": []byte(serverURL), + "api-key": []byte(expectedApiKey), + "app-key": []byte(expectedAppKey), + }, + } if test.useEnvVarForKeys { - os.Setenv("DD_API_KEY", ExpectedApiKey) - os.Setenv("DD_APP_KEY", ExpectedAppKey) + os.Setenv("DD_API_KEY", expectedApiKey) + os.Setenv("DD_APP_KEY", expectedAppKey) os.Setenv("DD_ADDRESS", serverURL) } else { os.Unsetenv("DD_API_KEY") @@ -372,11 +350,7 @@ func TestRunSuite(t *testing.T) { } namespace := "namespace" - provider, err := NewDatadogProvider(*logCtx, fakeClient, namespace, test.metric) - assert.Equal(t, err != nil, test.expectedErrorProvider) - if test.expectedErrorProvider { - continue - } + provider, _ := NewDatadogProvider(*logCtx, fakeClient, namespace, test.metric) metricsMetadata := provider.GetMetadata(test.metric) assert.Nil(t, metricsMetadata) @@ -408,54 +382,3 @@ func TestRunSuite(t *testing.T) { func newAnalysisRun() *v1alpha1.AnalysisRun { return &v1alpha1.AnalysisRun{} } - -func ddProviderIntervalDefault() v1alpha1.MetricProvider { - return v1alpha1.MetricProvider{ - Datadog: &v1alpha1.DatadogMetric{ - Query: "avg:kubernetes.cpu.user.total{*}", - }, - } -} - -func ddProviderInterval10m() v1alpha1.MetricProvider { - return v1alpha1.MetricProvider{ - Datadog: &v1alpha1.DatadogMetric{ - Query: "avg:kubernetes.cpu.user.total{*}", - Interval: "10m", - }, - } -} - -func ddProviderNamespacedSecret() v1alpha1.MetricProvider { - return v1alpha1.MetricProvider{ - Datadog: &v1alpha1.DatadogMetric{ - Query: "avg:kubernetes.cpu.user.total{*}", - Interval: "10m", - SecretRef: v1alpha1.SecretRef{ - Name: "secret", - Namespaced: true, - }, - }, - } -} - -func ddProviderNamespacedTrue() v1alpha1.MetricProvider { - - return v1alpha1.MetricProvider{ - Datadog: &v1alpha1.DatadogMetric{ - Query: "avg:kubernetes.cpu.user.total{*}", - Interval: "10m", - SecretRef: v1alpha1.SecretRef{ - Namespaced: true, - }, - }, - } -} -func newSecret(serverURL, expectedApiKey, expectedAppKey string) *corev1.Secret { - return NewSecretBuilder(). - WithName("DatadogTokensSecretName"). - WithData("address", []byte(serverURL)). - WithData("api-key", []byte(expectedApiKey)). - WithData("app-key", []byte(expectedAppKey)). - Build() -} diff --git a/metricproviders/datadog/datadog_test.go b/metricproviders/datadog/datadog_test.go index ed81977296..4d82a24f8d 100644 --- a/metricproviders/datadog/datadog_test.go +++ b/metricproviders/datadog/datadog_test.go @@ -3,14 +3,18 @@ package datadog import ( - "log" "os" "testing" "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1" + log "github.com/sirupsen/logrus" "github.com/stretchr/testify/assert" + corev1 "k8s.io/api/core/v1" apiextv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + "k8s.io/apimachinery/pkg/runtime" + k8sfake "k8s.io/client-go/kubernetes/fake" "k8s.io/client-go/kubernetes/scheme" + kubetesting "k8s.io/client-go/testing" ) func TestDatadogSpecDefaults(t *testing.T) { @@ -179,3 +183,67 @@ func TestValidateIncomingProps(t *testing.T) { }) } } + +func TestFindCredentials(t *testing.T) { + + testCases := []struct { + name string + secret *corev1.Secret + expectsError bool + metric v1alpha1.Metric + }{ + { + name: "when secretRef is set and secret found, should success", + secret: NewSecretBuilderDefaultData().Build(), + metric: newMetric("datadog", true), + }, + { + name: "when secretRef is set but secret not found, should fail", + secret: NewSecretBuilder().Build(), + metric: newMetric("datadog", true), + expectsError: true, + }, + { + name: "when secretRef name is not set but namespaced is true, should fail", + secret: NewSecretBuilder().Build(), + metric: newMetric("", true), + expectsError: true, + }, + } + + for _, testCase := range testCases { + t.Run(testCase.name, func(t *testing.T) { + logCtx := *log.WithField("test", "test") + fakeClient := k8sfake.NewSimpleClientset() + fakeClient.PrependReactor("get", "*", func(action kubetesting.Action) (handled bool, ret runtime.Object, err error) { + return true, testCase.secret, nil + }) + + address, apiKey, appKey, err := findCredentials(logCtx, fakeClient, "namespace", testCase.metric) + assert.Equal(t, err != nil, testCase.expectsError) + if !testCase.expectsError { + assert.Equal(t, string(testCase.secret.Data["address"]), address) + assert.Equal(t, string(testCase.secret.Data["api-key"]), apiKey) + assert.Equal(t, string(testCase.secret.Data["app-key"]), appKey) + } + }) + + } +} + +func newMetric(name string, namespaced bool) v1alpha1.Metric { + return v1alpha1.Metric{ + Provider: v1alpha1.MetricProvider{ + Datadog: &v1alpha1.DatadogMetric{ + Query: "avg:kubernetes.cpu.user.total{*}", + Interval: "5m", + Aggregator: "sum", + ApiVersion: "v2", + SecretRef: v1alpha1.SecretRef{ + Name: name, + Namespaced: namespaced, + }, + }, + }, + } +} diff --git a/metricproviders/datadog/finders_test.go b/metricproviders/datadog/finders_test.go index 5659eab929..62f2a8b2e5 100644 --- a/metricproviders/datadog/finders_test.go +++ b/metricproviders/datadog/finders_test.go @@ -109,3 +109,14 @@ func (b *SecretBuilder) Build() *corev1.Secret { Data: b.data, } } + +// NewSecretBuilderDefaultData creates a new SecretBuilder with default values +func NewSecretBuilderDefaultData() *SecretBuilder { + return &SecretBuilder{ + data: map[string][]byte{ + "address": []byte("datadog.com"), + "api-key": []byte("apiKey"), + "app-key": []byte("appKey"), + }, + } +}