diff options
author | George Wangensteen <george.wangensteen@mongodb.com> | 2022-01-26 16:15:16 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2022-01-26 16:55:16 +0000 |
commit | aae909d4cfba1621ccaf5d6168b89a0577d4e0ca (patch) | |
tree | d141f4ec2fee63d5ababbc2bca4363da0bbb37e0 | |
parent | 5ff2fd561d48c390a03e0d27239e3e378203634b (diff) | |
download | mongo-aae909d4cfba1621ccaf5d6168b89a0577d4e0ca.tar.gz |
SERVER-58506 Expose Server-Parameter Settability
-rw-r--r-- | etc/backports_required_for_multiversion_tests.yml | 4 | ||||
-rw-r--r-- | jstests/noPassthrough/getParameterWithDetails.js | 119 | ||||
-rw-r--r-- | src/mongo/db/commands/parameters.cpp | 44 | ||||
-rw-r--r-- | src/mongo/idl/SConscript | 2 | ||||
-rw-r--r-- | src/mongo/idl/server_parameter.idl | 49 |
5 files changed, 210 insertions, 8 deletions
diff --git a/etc/backports_required_for_multiversion_tests.yml b/etc/backports_required_for_multiversion_tests.yml index a6ab07267b6..da2cbbb6aa2 100644 --- a/etc/backports_required_for_multiversion_tests.yml +++ b/etc/backports_required_for_multiversion_tests.yml @@ -124,6 +124,8 @@ last-continuous: test_file: jstests/sharding/coordinate_txn_commit_with_tickets_exhausted.js - ticket: SERVER-60685 test_file: jstests/sharding/cancel_coordinate_txn_commit_with_tickets_exhausted.js + - ticket: SERVER-58506 + test_file: jstests/noPassthrough/getParameterWithDetails.js - ticket: SERVER-57766 test_file: jstests/sharding/resharding_metrics.js - ticket: SERVER-61757 @@ -411,6 +413,8 @@ last-lts: test_file: jstests/sharding/coordinate_txn_commit_with_tickets_exhausted.js - ticket: SERVER-60685 test_file: jstests/sharding/cancel_coordinate_txn_commit_with_tickets_exhausted.js + - ticket: SERVER-58506 + test_file: jstests/noPassthrough/getParameterWithDetails.js - ticket: SERVER-57766 test_file: jstests/sharding/resharding_metrics.js - ticket: SERVER-61757 diff --git a/jstests/noPassthrough/getParameterWithDetails.js b/jstests/noPassthrough/getParameterWithDetails.js new file mode 100644 index 00000000000..519970e9030 --- /dev/null +++ b/jstests/noPassthrough/getParameterWithDetails.js @@ -0,0 +1,119 @@ +// Test getParameter on mongod and mongos, including the with-detail syntax. +// +// @tags: [requires_replication, requires_sharding] + +(() => { + 'use strict'; + const st = new ShardingTest({shards: 1, mongos: 1}); + const mongosDB = st.s0.getDB("admin"); + const shardDB = st.shard0.getDB("admin"); + + function checkSpecificParameters(dbConn, parameters) { + const plainCommand = {getParameter: 1}; + const detailCommand = {getParameter: {showDetails: true}}; + + // Append requests to retrieve specific parameters. + parameters.forEach((parameter) => { + plainCommand[parameter["name"]] = 1; + detailCommand[parameter["name"]] = 1; + }); + + // Fetch results + const resultsPlain = assert.commandWorked(dbConn.adminCommand(plainCommand)); + const resultsWithDetail = assert.commandWorked(dbConn.adminCommand(detailCommand)); + + // Ensure requested parameters had expected values and detail information. + parameters.forEach((parameter) => { + const expectedDetailedResultObj = parameter["result"]; + const expectedValue = expectedDetailedResultObj["value"]; + const plainErrMsg = "Expecting plain result to contain: " + tojson(parameter) + + "but found: " + tojson(resultsPlain); + const detailErrMsg = "Expecting detail result to contain: " + tojson(parameter) + + "but found: " + tojson(resultsWithDetail); + + assert.eq(resultsPlain[parameter["name"]], expectedValue, plainErrMsg); + assert.docEq( + resultsWithDetail[parameter["name"]], expectedDetailedResultObj, detailErrMsg); + }); + } + + function checkAllParameters(dbConn) { + const plainCommand = {getParameter: '*'}; + const detailCommand = {getParameter: {showDetails: true, allParameters: true}}; + + // Fetch results + let resultsPlain = assert.commandWorked(dbConn.adminCommand(plainCommand)); + let resultsWithDetail = assert.commandWorked(dbConn.adminCommand(detailCommand)); + + // Ensure results are consistent between syntaxes. We don't check for explicit expected + // values here to avoid the need to specify them for every parameter and update this file + // every time one is added or changes in value. + Object.keys(resultsWithDetail).forEach((k) => { + if (resultsWithDetail[k].hasOwnProperty("value")) { + assert.eq(resultsWithDetail[k]["value"], + resultsPlain[k], + "In all parameters, mismatch for parameter " + k + ":" + + tojson(resultsWithDetail[k]) + " vs " + tojson(resultsPlain[k])); + } + }); + Object.keys(resultsPlain).forEach((k) => { + assert(resultsWithDetail.hasOwnProperty(k)); + if (resultsWithDetail[k].hasOwnProperty("value")) { + assert.eq(resultsPlain[k], resultsWithDetail[k]["value"]); + } + }); + } + + // Each of the entries in the following array is an object with two keys, "name" and "result". + // "name" is the name of a server parameter, and "result" is the expected object + // getParameter should return for that parameter, when details are requested. + const specificParametersBothProcesses = [ + { + name: "ShardingTaskExecutorPoolMinSize", + result: {value: 1, settableAtRuntime: true, settableAtStartup: true} + }, + { + name: "maxLogSizeKB", + result: {value: 10, settableAtRuntime: true, settableAtStartup: true} + }, + { + name: "cursorTimeoutMillis", + result: {value: NumberLong(600000), settableAtRuntime: true, settableAtStartup: true} + } + ]; + const specificParametersMongodOnly = [ + { + name: "ttlMonitorEnabled", + result: {value: true, settableAtRuntime: true, settableAtStartup: true} + }, + { + name: "wiredTigerMaxCacheOverflowSizeGB", + result: {value: 0, settableAtRuntime: true, settableAtStartup: false} + }, + { + name: "shardedIndexConsistencyCheckIntervalMS", + result: {value: 600000, settableAtRuntime: false, settableAtStartup: true} + }, + ]; + const specificParametersMongosOnly = [ + { + name: "taskExecutorPoolSize", + result: {value: 1, settableAtRuntime: true, settableAtStartup: true} + }, + { + name: "userCacheInvalidationIntervalSecs", + result: {value: 30, settableAtRuntime: true, settableAtStartup: true} + }, + ]; + + checkSpecificParameters(mongosDB, specificParametersBothProcesses); + checkSpecificParameters(shardDB, specificParametersBothProcesses); + + checkSpecificParameters(shardDB, specificParametersMongodOnly); + checkSpecificParameters(mongosDB, specificParametersMongosOnly); + + checkAllParameters(mongosDB); + checkAllParameters(shardDB); + + st.stop(); +})(); diff --git a/src/mongo/db/commands/parameters.cpp b/src/mongo/db/commands/parameters.cpp index b08a9ec2003..ea32db50df2 100644 --- a/src/mongo/db/commands/parameters.cpp +++ b/src/mongo/db/commands/parameters.cpp @@ -33,6 +33,7 @@ #include <set> +#include "mongo/bson/bsontypes.h" #include "mongo/bson/json.h" #include "mongo/bson/mutable/document.h" #include "mongo/client/replica_set_monitor.h" @@ -44,6 +45,7 @@ #include "mongo/db/storage/kv/kv_engine.h" #include "mongo/db/storage/storage_options.h" #include "mongo/idl/command_generic_argument.h" +#include "mongo/idl/server_parameter_gen.h" #include "mongo/logv2/log.h" #include "mongo/util/str.h" @@ -186,6 +188,19 @@ Status setLogComponentVerbosity(const BSONObj& bsonSettings) { return Status::OK(); } + +GetParameterOptions parseGetParameterOptions(BSONElement elem) { + if (elem.type() == BSONType::Object) { + return GetParameterOptions::parse({"getParameter"}, elem.Obj()); + } + if ((elem.type() == BSONType::String) && (elem.valueStringDataSafe() == "*"_sd)) { + GetParameterOptions ret; + ret.setAllParameters(true); + return ret; + } + return GetParameterOptions{}; +} + // for automationServiceDescription Mutex autoServiceDescriptorMutex; std::string autoServiceDescriptorValue; @@ -213,26 +228,39 @@ public: std::string help() const override { std::string h = "get administrative option(s)\nexample:\n" - "{ getParameter:1, notablescan:1 }\n"; + "{ getParameter:1, notablescan:1 }\n" + "pass a document as the value for getParameter to request options\nexample:\n" + "{ getParameter:{showDetails: true}, notablescan:1}\n"; appendParameterNames(&h); - h += "{ getParameter:'*' } to get everything\n"; + h += "{ getParameter:'*' } or { getParameter:{allParameters: true} } to get everything\n"; return h; } bool errmsgRun(OperationContext* opCtx, const string& dbname, const BSONObj& cmdObj, string& errmsg, - BSONObjBuilder& result) { - bool all = cmdObj.firstElement().str() == "*"; + BSONObjBuilder& result) override { + const auto options = parseGetParameterOptions(cmdObj.firstElement()); + const bool all = options.getAllParameters(); int before = result.len(); - for (const auto& param : ServerParameterSet::getNodeParameterSet()->getMap()) { - if (all || cmdObj.hasElement(param.first.c_str())) { - param.second->append(opCtx, result, param.second->name()); + const ServerParameter::Map& m = ServerParameterSet::getNodeParameterSet()->getMap(); + for (ServerParameter::Map::const_iterator i = m.begin(); i != m.end(); ++i) { + if (all || cmdObj.hasElement(i->first.c_str())) { + if (options.getShowDetails()) { + BSONObjBuilder detailBob(result.subobjStart(i->second->name())); + i->second->append(opCtx, detailBob, "value"); + detailBob.appendBool("settableAtRuntime", + i->second->allowedToChangeAtRuntime()); + detailBob.appendBool("settableAtStartup", + i->second->allowedToChangeAtStartup()); + detailBob.doneFast(); + } else { + i->second->append(opCtx, result, i->second->name()); + } } } - if (before == result.len()) { errmsg = "no option found to get"; return false; diff --git a/src/mongo/idl/SConscript b/src/mongo/idl/SConscript index 32815fc5a26..9f05ee0f7f0 100644 --- a/src/mongo/idl/SConscript +++ b/src/mongo/idl/SConscript @@ -37,10 +37,12 @@ env.Library( target='server_parameter', source=[ 'server_parameter.cpp', + 'server_parameter.idl', 'server_parameter_with_storage.cpp', ], LIBDEPS=[ '$BUILD_DIR/mongo/base', + 'idl_parser', ], LIBDEPS_PRIVATE=[ '$BUILD_DIR/mongo/util/options_parser/options_parser', diff --git a/src/mongo/idl/server_parameter.idl b/src/mongo/idl/server_parameter.idl new file mode 100644 index 00000000000..2fb39ad0815 --- /dev/null +++ b/src/mongo/idl/server_parameter.idl @@ -0,0 +1,49 @@ +# Copyright (C) 2022-present MongoDB, Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the Server Side Public License, version 1, +# as published by MongoDB, Inc. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# Server Side Public License for more details. +# +# You should have received a copy of the Server Side Public License +# along with this program. If not, see +# <http://www.mongodb.com/licensing/server-side-public-license>. +# +# As a special exception, the copyright holders give permission to link the +# code of portions of this program with the OpenSSL library under certain +# conditions as described in each individual source file and distribute +# linked combinations including the program with the OpenSSL library. You +# must comply with the Server Side Public License in all respects for +# all of the code used other than as permitted herein. If you modify file(s) +# with this exception, you may extend this exception to your version of the +# file(s), but you are not obligated to do so. If you do not wish to do so, +# delete this exception statement from your version. If you delete this +# exception statement from all source files in the program, then also delete +# it in the license file. +# +# IDL constructs useful for all server parameters. + +global: + cpp_namespace: "mongo" + +imports: + - "mongo/idl/basic_types.idl" + +# Options for the getParameter command. Describes the object "options" when the command is run as +# {getParameter: <options>} +structs: + GetParameterOptions: + description: 'Optional flags to pass to {getParameter: options, ...}' + fields: + showDetails: + description: 'Return metadata about the server parameter along with its current value' + type: safeBool + default: false + allParameters: + description: 'Return all server parameters, not just the ones specified' + type: safeBool + default: false |