diff --git a/BUILD.md b/BUILD.md index 716bd3acf3d..01c53268925 100644 --- a/BUILD.md +++ b/BUILD.md @@ -138,7 +138,10 @@ Follow these instructions if you want to debug the KEDA operator using VS Code. "request": "launch", "mode": "debug", "program": "${workspaceFolder}/main.go", - "env": {"WATCH_NAMESPACE": ""} + "env": { + "WATCH_NAMESPACE": "", + "KEDA_CLUSTER_OBJECT_NAMESPACE": "keda" + } } ] } @@ -171,7 +174,10 @@ Follow these instructions if you want to debug the KEDA metrics server using VS "request": "launch", "mode": "auto", "program": "${workspaceFolder}/adapter/main.go", - "env": {"WATCH_NAMESPACE": ""}, + "env": { + "WATCH_NAMESPACE": "", + "KEDA_CLUSTER_OBJECT_NAMESPACE": "keda" + }, "args": [ "--authentication-kubeconfig=PATH_TO_YOUR_KUBECONFIG", "--authentication-skip-lookup", diff --git a/CHANGELOG.md b/CHANGELOG.md index 08f93217faf..e45e6f6ffcb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -90,6 +90,7 @@ To learn more about active deprecations, we recommend checking [GitHub Discussio - **Azure Blob Scaler** Store forgotten logger ([#3811](https://github.com/kedacore/keda/issues/3811)) - **Datadog Scaler** The last data point of some specific query is always null ([#3906](https://github.com/kedacore/keda/issues/3906)) - **GCP Stackdriver Scalar:** Update Stackdriver client to handle detecting double and int64 value types ([#3777](https://github.com/kedacore/keda/issues/3777)) +- **MongoDB Scaler:** Username/password can contain `:/?#[]@` ([#3992](https://github.com/kedacore/keda/issues/3992)) - **New Relic Scaler** Store forgotten logger ([#3945](https://github.com/kedacore/keda/issues/3945)) - **Prometheus Scaler:** Treat Inf the same as Null result ([#3644](https://github.com/kedacore/keda/issues/3644)) - **NATS Jetstream:** Correctly count messages that should be redelivered (waiting for ack) towards keda value ([#3787](https://github.com/kedacore/keda/issues/3787)) diff --git a/pkg/scalers/couchdb_scaler.go b/pkg/scalers/couchdb_scaler.go index d10d0d1d87d..eb33ea1d46a 100644 --- a/pkg/scalers/couchdb_scaler.go +++ b/pkg/scalers/couchdb_scaler.go @@ -178,8 +178,6 @@ func parseCouchDBMetadata(config *ScalerConfig) (*couchDBMetadata, string, error } else { // Build connection str addr := net.JoinHostPort(meta.host, meta.port) - // addr := fmt.Sprintf("%s:%s", meta.host, meta.port) - // auth := fmt.Sprintf("%s:%s", meta.username, meta.password) connStr = "http://" + addr } if val, ok := config.TriggerMetadata["metricName"]; ok { diff --git a/pkg/scalers/mongo_scaler.go b/pkg/scalers/mongo_scaler.go index e1dfac85e40..4acfa438356 100644 --- a/pkg/scalers/mongo_scaler.go +++ b/pkg/scalers/mongo_scaler.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "net" + "net/url" "strconv" "time" @@ -189,8 +190,7 @@ func parseMongoDBMetadata(config *ScalerConfig) (*mongoDBMetadata, string, error } else { // Build connection str addr := net.JoinHostPort(meta.host, meta.port) - auth := fmt.Sprintf("%s:%s", meta.username, meta.password) - connStr = "mongodb://" + auth + "@" + addr + "/" + meta.dbName + connStr = fmt.Sprintf("mongodb://%s:%s@%s/%s", url.QueryEscape(meta.username), url.QueryEscape(meta.password), addr, meta.dbName) } if val, ok := config.TriggerMetadata["metricName"]; ok { diff --git a/pkg/scalers/mongo_scaler_test.go b/pkg/scalers/mongo_scaler_test.go index 303ccf9a3a6..1550ede6fbb 100644 --- a/pkg/scalers/mongo_scaler_test.go +++ b/pkg/scalers/mongo_scaler_test.go @@ -5,12 +5,13 @@ import ( "testing" "github.com/go-logr/logr" + "github.com/stretchr/testify/assert" "go.mongodb.org/mongo-driver/mongo" ) var testMongoDBResolvedEnv = map[string]string{ - "MongoDB_CONN_STR": "test_conn_str", - "MongoDB_PASSWORD": "test", + "MongoDB_CONN_STR": "mongodb://mongodb0.example.com:27017", + "MongoDB_PASSWORD": "test@password", } type parseMongoDBMetadataTestData struct { @@ -20,6 +21,11 @@ type parseMongoDBMetadataTestData struct { raisesError bool } +type mongoDBConnectionStringTestData struct { + metadataTestData *parseMongoDBMetadataTestData + connectionString string +} + type mongoDBMetricIdentifier struct { metadataTestData *parseMongoDBMetadataTestData scalerIndex int @@ -36,22 +42,29 @@ var testMONGODBMetadata = []parseMongoDBMetadataTestData{ }, // connectionStringFromEnv { - metadata: map[string]string{"query": `{"name":"John"}`, "collection": "demo", "queryValue": "12", "connectionStringFromEnv": "Mongo_CONN_STR", "dbName": "test"}, + metadata: map[string]string{"query": `{"name":"John"}`, "collection": "demo", "queryValue": "12", "connectionStringFromEnv": "MongoDB_CONN_STR", "dbName": "test"}, authParams: map[string]string{}, resolvedEnv: testMongoDBResolvedEnv, raisesError: false, }, // with metric name { - metadata: map[string]string{"query": `{"name":"John"}`, "metricName": "hpa", "collection": "demo", "queryValue": "12", "connectionStringFromEnv": "Mongo_CONN_STR", "dbName": "test"}, + metadata: map[string]string{"query": `{"name":"John"}`, "metricName": "hpa", "collection": "demo", "queryValue": "12", "connectionStringFromEnv": "MongoDB_CONN_STR", "dbName": "test"}, authParams: map[string]string{}, resolvedEnv: testMongoDBResolvedEnv, raisesError: false, }, + // from passwordFromEnv + { + metadata: map[string]string{"query": `{"name":"John"}`, "metricName": "hpa", "collection": "demo", "queryValue": "12", "passwordFromEnv": "MongoDB_PASSWORD"}, + authParams: map[string]string{"dbName": "test", "host": "localshot", "port": "1234", "username": "sample"}, + resolvedEnv: testMongoDBResolvedEnv, + raisesError: false, + }, // from trigger auth { metadata: map[string]string{"query": `{"name":"John"}`, "metricName": "hpa", "collection": "demo", "queryValue": "12"}, - authParams: map[string]string{"dbName": "test", "host": "localshot", "port": "1234", "username": "sample", "password": "secure"}, + authParams: map[string]string{"dbName": "test", "host": "localshot", "port": "1234", "username": "sample", "password": "sec@ure"}, resolvedEnv: testMongoDBResolvedEnv, raisesError: false, }, @@ -64,6 +77,12 @@ var testMONGODBMetadata = []parseMongoDBMetadataTestData{ }, } +var mongoDBConnectionStringTestDatas = []mongoDBConnectionStringTestData{ + {metadataTestData: &testMONGODBMetadata[2], connectionString: "mongodb://mongodb0.example.com:27017"}, + {metadataTestData: &testMONGODBMetadata[3], connectionString: "mongodb://sample:test%40password@localshot:1234/test"}, + {metadataTestData: &testMONGODBMetadata[4], connectionString: "mongodb://sample:sec%40ure@localshot:1234/test"}, +} + var mongoDBMetricIdentifiers = []mongoDBMetricIdentifier{ {metadataTestData: &testMONGODBMetadata[2], scalerIndex: 0, name: "s0-mongodb-hpa"}, {metadataTestData: &testMONGODBMetadata[2], scalerIndex: 1, name: "s1-mongodb-hpa"}, @@ -71,7 +90,7 @@ var mongoDBMetricIdentifiers = []mongoDBMetricIdentifier{ func TestParseMongoDBMetadata(t *testing.T) { for _, testData := range testMONGODBMetadata { - _, _, err := parseMongoDBMetadata(&ScalerConfig{TriggerMetadata: testData.metadata, AuthParams: testData.authParams}) + _, _, err := parseMongoDBMetadata(&ScalerConfig{ResolvedEnv: testData.resolvedEnv, TriggerMetadata: testData.metadata, AuthParams: testData.authParams}) if err != nil && !testData.raisesError { t.Error("Expected success but got error:", err) } @@ -81,6 +100,16 @@ func TestParseMongoDBMetadata(t *testing.T) { } } +func TestParseMongoDBConnectionString(t *testing.T) { + for _, testData := range mongoDBConnectionStringTestDatas { + _, connStr, err := parseMongoDBMetadata(&ScalerConfig{ResolvedEnv: testData.metadataTestData.resolvedEnv, TriggerMetadata: testData.metadataTestData.metadata, AuthParams: testData.metadataTestData.authParams}) + if err != nil { + t.Error("Expected success but got error:", err) + } + assert.Equal(t, testData.connectionString, connStr) + } +} + func TestMongoDBGetMetricSpecForScaling(t *testing.T) { for _, testData := range mongoDBMetricIdentifiers { meta, _, err := parseMongoDBMetadata(&ScalerConfig{ResolvedEnv: testData.metadataTestData.resolvedEnv, AuthParams: testData.metadataTestData.authParams, TriggerMetadata: testData.metadataTestData.metadata, ScalerIndex: testData.scalerIndex})