diff --git a/CHANGES_NEXT_RELEASE b/CHANGES_NEXT_RELEASE index d0952e49b8..f35636fdac 100644 --- a/CHANGES_NEXT_RELEASE +++ b/CHANGES_NEXT_RELEASE @@ -1,3 +1,4 @@ - Add: servicePath field to builtin attributes (#2877) - Fix: logDeprecate not working correctly (`geo:json` wrongly considered as deprecated) - Fix: improve error traces (#4387) +- Add: CLI parameter -dbUri / env var ORION_MONGO_URI (#3794) diff --git a/doc/manuals.jp/admin/cli.md b/doc/manuals.jp/admin/cli.md index 643bdaa263..076b43d4e3 100644 --- a/doc/manuals.jp/admin/cli.md +++ b/doc/manuals.jp/admin/cli.md @@ -32,6 +32,9 @@ broker はデフォルトでバックグラウンドで実行されるため、 - **-ipv6** : broker を IPv6 専用モードで実行します。デフォルトでは、broker は IPv4 と IPv6 の両方で動作します。-ipv4 と同時に使用することはできません。 - **-multiservice** : マルチサービス/マルチテナントモードを有効にします。[マルチ・テナンシーのセクション](../orion-api.md#multi-tenancy)を参照してください - **-db ** : 使用する MogoDB データベース、または (`-multiservice` を使用している場合) サービス単位/テナント単位のデータベースのプレフィックス ([マルチ・テナンシー](../orion-api.md#multi-tenancy)のセクションを参照してください) です。このフィールドは最大10文字までです +- **-dbURI ** : 使用する MongoDB を URI で指定します。 + URI に文字列 `${PWD}` がある場合は `-dbpwd` または環境変数 `ORION_MONGO_PASSWORD` で指定したパスワードで置き換えられます。 + このオプションは `-dbhost`, `-rplSet`, `-dbTimeout`, `-dbuser`, `-dbAuthMech`, `-dbAuthDb`, `-dbSSL`, `-dbDisableRetryWrites` と組み合わせできません。(組み合わせた場合、Orion は起動時にエラーで終了します) - **-dbhost ** : 使用する MongoDB のホストとポートです。たとえば、`-dbhost localhost:12345` です - **-rplSet ** : 指定すれば、Orion CB が MongoDB レプリカセット (スタンドアロン MongoDB インスタンスではなく) に接続されます。使用するレプリカセットの名前は、パラメータの値です。この場合、-dbhost パラメーターは、レプリカ・セットのシードとして使用されるホスト ("," で区切られた) のリストにすることができます - **-dbTimeout ** : レプリカセット (-rplSet) を使用する場合にのみ使用され、それ以外の場合は無視されます。レプリカセットへの接続のタイムアウトをミリ秒単位で指定します @@ -139,6 +142,7 @@ Orion は、環境変数を使用した引数の受け渡しをサポートし | ORION_LOCALIP | localIp | | ORION_PORT | port | | ORION_PID_PATH | pidpath | +| ORION_MONGO_URI | dbURI | | ORION_MONGO_HOST | dbhost | | ORION_MONGO_REPLICA_SET | rplSet | | ORION_MONGO_USER | dbuser | diff --git a/doc/manuals/admin/cli.md b/doc/manuals/admin/cli.md index a133939397..0899b45255 100644 --- a/doc/manuals/admin/cli.md +++ b/doc/manuals/admin/cli.md @@ -46,6 +46,12 @@ The list of available options is the following: [service/tenant database separation](../orion-api.md#multi-tenancy). This field is restricted to 10 characters max length. +- **-dbURI ** : The URI to use the MongoDB. + If the URI contains the string `${PWD}`, it will be replaced with the password + specified in `-dbpwd` or the environment variable `ORION_MONGO_PASSWORD`. + This option cannot be combined with `-dbhost`, `-rplSet`, `-dbTimeout`, `-dbuser`, + `-dbAuthMech`, `-dbAuthDb`, `-dbSSL` and `-dbDisableRetryWrites` (if you attempt to do that + Orion will exit with an error on startup). - **-dbhost **. The MongoDB host and port to use, e.g. `-dbhost localhost:12345`. - **-rplSet **. If used, Orion CB connnects to a @@ -211,6 +217,7 @@ Two facts have to be taken into account: | ORION_LOCALIP | localIp | | ORION_PORT | port | | ORION_PID_PATH | pidpath | +| ORION_MONGO_URI | dbURI | | ORION_MONGO_HOST | dbhost | | ORION_MONGO_REPLICA_SET | rplSet | | ORION_MONGO_USER | dbuser | diff --git a/src/app/contextBroker/contextBroker.cpp b/src/app/contextBroker/contextBroker.cpp index 7e81493ad0..bf81abec8f 100644 --- a/src/app/contextBroker/contextBroker.cpp +++ b/src/app/contextBroker/contextBroker.cpp @@ -148,6 +148,7 @@ char authMech[64]; char authDb[64]; bool dbSSL; bool dbDisableRetryWrites; +char dbURI[1024]; char pidPath[256]; bool harakiri; bool useOnlyIPv4; @@ -276,6 +277,7 @@ bool logDeprecate; #define NGSIV1_AUTOCAST_DESC "automatic cast for number, booleans and dates in NGSIv1 update/create attribute operations" #define MQTT_MAX_AGE_DESC "max time (in minutes) that an unused MQTT connection is kept, default: 60" #define LOG_DEPRECATE_DESC "log deprecation usages as warnings" +#define DBURI_DESC "complete URI for database connection" @@ -295,6 +297,7 @@ PaArgument paArgs[] = { "-port", &port, "PORT", PaInt, PaOpt, 1026, 1, 65535, PORT_DESC }, { "-pidpath", pidPath, "PID_PATH", PaString, PaOpt, PIDPATH, PaNL, PaNL, PIDPATH_DESC }, + { "-dbURI", dbURI, "MONGO_URI", PaString, PaOpt, _i "", PaNL, PaNL, DBURI_DESC }, { "-dbhost", dbHost, "MONGO_HOST", PaString, PaOpt, LOCALHOST, PaNL, PaNL, DBHOST_DESC }, { "-rplSet", rplSet, "MONGO_REPLICA_SET", PaString, PaOpt, _i "", PaNL, PaNL, RPLSET_DESC }, { "-dbuser", user, "MONGO_USER", PaString, PaOpt, _i "", PaNL, PaNL, DBUSER_DESC }, @@ -1213,7 +1216,7 @@ int main(int argC, char* argV[]) alarmMgr.init(relogAlarms); mqttMgr.init(mqttTimeout); orionInit(orionExit, ORION_VERSION, policy, statCounters, statSemWait, statTiming, statNotifQueue, strictIdv1); - mongoInit(dbHost, rplSet, dbName, user, pwd, authMech, authDb, dbSSL, dbDisableRetryWrites, mtenant, dbTimeout, writeConcern, dbPoolSize, statSemWait); + mongoInit(dbURI, dbHost, rplSet, dbName, user, pwd, authMech, authDb, dbSSL, dbDisableRetryWrites, mtenant, dbTimeout, writeConcern, dbPoolSize, statSemWait); metricsMgr.init(!disableMetrics, statSemWait); logSummaryInit(&lsPeriod); diff --git a/src/lib/mongoBackend/MongoGlobal.cpp b/src/lib/mongoBackend/MongoGlobal.cpp index e996aba9e2..599d69af8d 100644 --- a/src/lib/mongoBackend/MongoGlobal.cpp +++ b/src/lib/mongoBackend/MongoGlobal.cpp @@ -104,6 +104,7 @@ bool mongoMultitenant(void) */ void mongoInit ( + const char* dbURI, const char* dbHost, const char* rplSet, std::string dbName, @@ -123,7 +124,8 @@ void mongoInit // Set the global multitenant variable multitenant = mtenant; - if (orion::mongoConnectionPoolInit(dbHost, + if (orion::mongoConnectionPoolInit(dbURI, + dbHost, dbName.c_str(), rplSet, user, diff --git a/src/lib/mongoBackend/MongoGlobal.h b/src/lib/mongoBackend/MongoGlobal.h index 53d86c6194..9b750e01b5 100644 --- a/src/lib/mongoBackend/MongoGlobal.h +++ b/src/lib/mongoBackend/MongoGlobal.h @@ -71,6 +71,7 @@ extern bool mongoMultitenant(void); */ void mongoInit ( + const char* dbURI, const char* dbHost, const char* rplSet, std::string dbName, diff --git a/src/lib/mongoDriver/mongoConnectionPool.cpp b/src/lib/mongoDriver/mongoConnectionPool.cpp index 281b1c472c..ed0d1db07c 100644 --- a/src/lib/mongoDriver/mongoConnectionPool.cpp +++ b/src/lib/mongoDriver/mongoConnectionPool.cpp @@ -316,6 +316,7 @@ static void mongoDriverLogger */ static std::string composeMongoUri ( + const char* dbURI, const char* host, const char* rplSet, const char* username, @@ -329,54 +330,82 @@ static std::string composeMongoUri { // Compose the mongoUri, taking into account all information - std::string uri = "mongodb://"; + std::string uri; - // Add auth parameter if included - if (strlen(username) != 0 && strlen(passwd) != 0) + if (strlen(dbURI) != 0) { - uri += username + std::string(":") + passwd + "@"; - } + if (strlen(username) != 0 || strlen(authDb) != 0 || strlen(rplSet) != 0 || strlen(mechanism) != 0 || dbSSL || dbDisableRetryWrites || timeout > 0) + { + LM_X(1, ("Invalid Command Line Options: -dbURI cannot be combined with -dbhost, -rplSet, -dbTimeout, -dbuser, -dbAuthMech, -dbAuthDb, -dbSSL and -dbDisableRetryWrites")); + } - uri += host + std::string("/"); + const char* pwd = strstr(dbURI, "${PWD}"); + if (pwd != NULL) + { + if (strlen(passwd) == 0) + { + LM_X(1, ("Invalid Command Line Options: -dbURI is used with a password substitution, but no password (-dbpwd) is supplied")); + } - if (strlen(authDb) != 0) - { - uri += authDb; + // +6 is the length of the "${PWD}" + uri = std::string(dbURI, pwd - dbURI) + passwd + (pwd + 6); + } + else + { + uri = dbURI; + } } + else + { + uri = "mongodb://"; - // First option prefix is '?' symbol - std::string optionPrefix = "?"; + // Add auth parameter if included + if (strlen(username) != 0 && strlen(passwd) != 0) + { + uri += username + std::string(":") + passwd + "@"; + } - if (strlen(rplSet) != 0) - { - uri += optionPrefix + "replicaSet=" + rplSet; - optionPrefix = "&"; - } + uri += host + std::string("/"); - if (strlen(mechanism) != 0) - { - uri += optionPrefix + "authMechanism=" + mechanism; - optionPrefix = "&"; - } + if (strlen(authDb) != 0) + { + uri += authDb; + } - if (dbSSL) - { - uri += optionPrefix + "tls=true&tlsAllowInvalidCertificates=true"; - optionPrefix = "&"; - } + // First option prefix is '?' symbol + std::string optionPrefix = "?"; - if (dbDisableRetryWrites) - { - uri += optionPrefix + "retryWrites=false"; - optionPrefix = "&"; - } + if (strlen(rplSet) != 0) + { + uri += optionPrefix + "replicaSet=" + rplSet; + optionPrefix = "&"; + } - if (timeout > 0) - { - char buf[STRING_SIZE_FOR_LONG]; - i2s(timeout, buf, sizeof(buf)); - uri += optionPrefix + "connectTimeoutMS=" + buf; - optionPrefix = "&"; + if (strlen(mechanism) != 0) + { + uri += optionPrefix + "authMechanism=" + mechanism; + optionPrefix = "&"; + } + + if (dbSSL) + { + uri += optionPrefix + "tls=true&tlsAllowInvalidCertificates=true"; + optionPrefix = "&"; + } + + if (dbDisableRetryWrites) + { + uri += optionPrefix + "retryWrites=false"; + optionPrefix = "&"; + } + + if (timeout > 0) + { + char buf[STRING_SIZE_FOR_LONG]; + i2s(timeout, buf, sizeof(buf)); + uri += optionPrefix + "connectTimeoutMS=" + buf; + optionPrefix = "&"; + } } LM_T(LmtMongo, ("MongoDB connection URI: '%s'", offuscatePassword(uri, passwd).c_str())); @@ -392,6 +421,7 @@ static std::string composeMongoUri */ int orion::mongoConnectionPoolInit ( + const char* dbURI, const char* host, const char* db, const char* rplSet, @@ -421,7 +451,7 @@ int orion::mongoConnectionPoolInit atexit(shutdownClient); // Set mongo Uri to connect - std::string uri = composeMongoUri(host, rplSet, username, passwd, mechanism, authDb, dbSSL, dbDisableRetryWrites, timeout); + std::string uri = composeMongoUri(dbURI, host, rplSet, username, passwd, mechanism, authDb, dbSSL, dbDisableRetryWrites, timeout); #ifdef UNIT_TEST /* Basically, we are mocking all the DB pool with a single connection. The getMongoConnection() and mongoReleaseConnection() methods diff --git a/src/lib/mongoDriver/mongoConnectionPool.h b/src/lib/mongoDriver/mongoConnectionPool.h index 79ca14c9e3..0dddc183ae 100644 --- a/src/lib/mongoDriver/mongoConnectionPool.h +++ b/src/lib/mongoDriver/mongoConnectionPool.h @@ -46,6 +46,7 @@ extern void mongoVersionGet(int* mayor, int* minor); */ extern int mongoConnectionPoolInit ( + const char* dbURI, const char* host, const char* db, const char* rplSet, diff --git a/test/functionalTest/cases/0000_cli/bool_option_with_value.test b/test/functionalTest/cases/0000_cli/bool_option_with_value.test index dbdc0d45b7..157a33b97a 100644 --- a/test/functionalTest/cases/0000_cli/bool_option_with_value.test +++ b/test/functionalTest/cases/0000_cli/bool_option_with_value.test @@ -50,6 +50,7 @@ Usage: contextBroker [option '-U' (extended usage)] [option '-localIp' ] [option '-port' ] [option '-pidpath' ] + [option '-dbURI' ] [option '-dbhost' ] [option '-rplSet' ] [option '-dbuser' ] diff --git a/test/functionalTest/cases/0000_cli/command_line_options.test b/test/functionalTest/cases/0000_cli/command_line_options.test index 8e5b9b1ecb..20a639175b 100644 --- a/test/functionalTest/cases/0000_cli/command_line_options.test +++ b/test/functionalTest/cases/0000_cli/command_line_options.test @@ -39,6 +39,7 @@ Usage: contextBroker [option '-U' (extended usage)] [option '-localIp' ] [option '-port' ] [option '-pidpath' ] + [option '-dbURI' ] [option '-dbhost' ] [option '-rplSet' ] [option '-dbuser' ] diff --git a/test/functionalTest/cases/0000_cli/tracelevel_without_logLevel_as_DEBUG.test b/test/functionalTest/cases/0000_cli/tracelevel_without_logLevel_as_DEBUG.test index 2ae2c7ad60..cf566803ce 100644 --- a/test/functionalTest/cases/0000_cli/tracelevel_without_logLevel_as_DEBUG.test +++ b/test/functionalTest/cases/0000_cli/tracelevel_without_logLevel_as_DEBUG.test @@ -40,6 +40,7 @@ Usage: contextBroker [option '-U' (extended usage)] [option '-localIp' ] [option '-port' ] [option '-pidpath' ] + [option '-dbURI' ] [option '-dbhost' ] [option '-rplSet' ] [option '-dbuser' ] diff --git a/test/functionalTest/cases/3658_env_vars/env_vars.test b/test/functionalTest/cases/3658_env_vars/env_vars.test index bd68c35e98..495c359dec 100644 --- a/test/functionalTest/cases/3658_env_vars/env_vars.test +++ b/test/functionalTest/cases/3658_env_vars/env_vars.test @@ -85,6 +85,7 @@ Extended Usage: contextBroker [option '-U' (extended usage)] [option '-localIp' ] ORION_LOCALIP '0.0.0.0' /'0.0.0.0'/ [option '-port' ] ORION_PORT 1 <= 1026 /1026/ <= 65535 [option '-pidpath' ] ORION_PID_PATH '/tmp/contextBroker.pid' /'/tmp/contextBroker/ + [option '-dbURI' ] ORION_MONGO_URI '' /''/ [option '-dbhost' ] ORION_MONGO_HOST 'localhost' /'localhost'/ [option '-rplSet' ] ORION_MONGO_REPLICA_SET '' /''/ [option '-dbuser' ] ORION_MONGO_USER '' /''/ diff --git a/test/unittests/main_UnitTest.cpp b/test/unittests/main_UnitTest.cpp index 420f3493b6..7d7b9bc991 100644 --- a/test/unittests/main_UnitTest.cpp +++ b/test/unittests/main_UnitTest.cpp @@ -80,6 +80,7 @@ unsigned long logLineMaxSize = 32 * 1024; bool logDeprecate = false; +char dbURI[1024]; char dbHost[256]; char rplSet[64]; char dbName[64]; @@ -107,6 +108,7 @@ unsigned long fcMaxInterval = 0; */ PaArgument paArgs[] = { + { "-dbURI", dbURI, "DB_URI", PaString, PaOpt, (int64_t) "", PaNL, PaNL, "" }, { "-dbhost", dbHost, "DB_HOST", PaString, PaOpt, (int64_t) "localhost", PaNL, PaNL, "" }, { "-rplSet", rplSet, "RPL_SET", PaString, PaOpt, (int64_t) "", PaNL, PaNL, "" }, { "-dbuser", user, "DB_USER", PaString, PaOpt, (int64_t) "", PaNL, PaNL, "" }, @@ -158,7 +160,7 @@ int main(int argC, char** argV) LM_M(("Init tests")); orionInit(exitFunction, orionUnitTestVersion, SemReadWriteOp, false, false, false, false, false); // Note that disableRetryTries, multitenancy and mutex time stats are disabled for unit test mongo init - mongoInit(dbHost, rplSet, dbName, user, pwd, authMech, authDb, dbSSL, false, false, dbTimeout, writeConcern, dbPoolSize, false); + mongoInit(dbURI, dbHost, rplSet, dbName, user, pwd, authMech, authDb, dbSSL, false, false, dbTimeout, writeConcern, dbPoolSize, false); alarmMgr.init(false); logSummaryInit(&lsPeriod); // setupDatabase(); FIXME #3775: pending on mongo unit test re-enabling