summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTommaso Tocci <tommaso.tocci@mongodb.com>2020-10-01 13:46:39 +0200
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2020-10-01 12:55:27 +0000
commitf880b32be6c6081ca0eb6599fd14b8fad5a5813c (patch)
tree827fd25908add62d0b11340cb3632da6b57ea918
parentbfd22982681e0af44f52b586b432091174d17945 (diff)
downloadmongo-f880b32be6c6081ca0eb6599fd14b8fad5a5813c.tar.gz
Revert "SERVER-50375 Thoroughly test that mongos forwards API parameters"
This reverts commit e66093f0a8ee3cd95dea9480028a6da814bb1854.
-rw-r--r--buildscripts/resmokeconfig/suites/concurrency_sharded_with_stepdowns.yml3
-rw-r--r--buildscripts/resmokeconfig/suites/sharding_continuous_config_stepdown.yml3
-rw-r--r--jstests/sharding/api_params_nontransaction_sharded.js12
-rw-r--r--jstests/sharding/api_params_nontransaction_unsharded.js12
-rw-r--r--jstests/sharding/api_params_transaction_sharded.js12
-rw-r--r--jstests/sharding/api_params_transaction_unsharded.js12
-rw-r--r--jstests/sharding/libs/mongos_api_params_util.js1496
-rw-r--r--jstests/sharding/mongos_forwards_api_parameters_to_shards.js213
-rw-r--r--src/mongo/db/SConscript1
-rw-r--r--src/mongo/db/api_parameters.cpp14
-rw-r--r--src/mongo/db/api_parameters.h13
-rw-r--r--src/mongo/db/commands/kill_all_sessions_by_pattern_command.cpp11
-rw-r--r--src/mongo/db/commands/kill_sessions_command.cpp6
-rw-r--r--src/mongo/db/kill_sessions.cpp31
-rw-r--r--src/mongo/db/kill_sessions.h33
-rw-r--r--src/mongo/db/s/config/sharding_catalog_manager_shard_operations.cpp3
-rw-r--r--src/mongo/db/session_killer.cpp44
-rw-r--r--src/mongo/s/commands/cluster_kill_op.cpp5
-rw-r--r--src/mongo/s/commands/kill_sessions_remote.cpp8
19 files changed, 264 insertions, 1668 deletions
diff --git a/buildscripts/resmokeconfig/suites/concurrency_sharded_with_stepdowns.yml b/buildscripts/resmokeconfig/suites/concurrency_sharded_with_stepdowns.yml
index acafd931353..ce3749db4bd 100644
--- a/buildscripts/resmokeconfig/suites/concurrency_sharded_with_stepdowns.yml
+++ b/buildscripts/resmokeconfig/suites/concurrency_sharded_with_stepdowns.yml
@@ -169,9 +169,6 @@ selector:
- jstests/concurrency/fsm_workloads/snapshot_read_kill_op_only.js
- jstests/concurrency/fsm_workloads/snapshot_read_kill_operations.js
- # Expects same CSRS primary and shard primary throughout the test
- - jstests/sharding/mongos_forwards_api_parameters_to_shards.js
-
exclude_with_any_tags:
- requires_replication
- requires_non_retryable_writes
diff --git a/buildscripts/resmokeconfig/suites/sharding_continuous_config_stepdown.yml b/buildscripts/resmokeconfig/suites/sharding_continuous_config_stepdown.yml
index 03e804ced4f..d6c78268669 100644
--- a/buildscripts/resmokeconfig/suites/sharding_continuous_config_stepdown.yml
+++ b/buildscripts/resmokeconfig/suites/sharding_continuous_config_stepdown.yml
@@ -221,9 +221,6 @@ selector:
- jstests/sharding/conversion_of_replica_set_to_sharded_cluster.js
- jstests/sharding/move_primary_with_writes.js
- # Expects same CSRS primary and shard primary throughout the test
- - jstests/sharding/mongos_forwards_api_parameters_to_shards.js
-
executor:
config:
shell_options:
diff --git a/jstests/sharding/api_params_nontransaction_sharded.js b/jstests/sharding/api_params_nontransaction_sharded.js
deleted file mode 100644
index 0744f38be96..00000000000
--- a/jstests/sharding/api_params_nontransaction_sharded.js
+++ /dev/null
@@ -1,12 +0,0 @@
-/**
- * When a client calls a mongos command with API parameters, mongos must forward them to shards.
- *
- * @tags: [multiversion_incompatible]
- */
-
-(function() {
-'use strict';
-
-load('jstests/sharding/libs/mongos_api_params_util.js');
-MongosAPIParametersUtil.runTests({inTransaction: false, shardedCollection: true});
-})();
diff --git a/jstests/sharding/api_params_nontransaction_unsharded.js b/jstests/sharding/api_params_nontransaction_unsharded.js
deleted file mode 100644
index d9eb64570cd..00000000000
--- a/jstests/sharding/api_params_nontransaction_unsharded.js
+++ /dev/null
@@ -1,12 +0,0 @@
-/**
- * When a client calls a mongos command with API parameters, mongos must forward them to shards.
- *
- * @tags: [multiversion_incompatible]
- */
-
-(function() {
-'use strict';
-
-load('jstests/sharding/libs/mongos_api_params_util.js');
-MongosAPIParametersUtil.runTests({inTransaction: false, shardedCollection: false});
-})();
diff --git a/jstests/sharding/api_params_transaction_sharded.js b/jstests/sharding/api_params_transaction_sharded.js
deleted file mode 100644
index 24d88079182..00000000000
--- a/jstests/sharding/api_params_transaction_sharded.js
+++ /dev/null
@@ -1,12 +0,0 @@
-/**
- * When a client calls a mongos command with API parameters, mongos must forward them to shards.
- *
- * @tags: [multiversion_incompatible]
- */
-
-(function() {
-'use strict';
-
-load('jstests/sharding/libs/mongos_api_params_util.js');
-MongosAPIParametersUtil.runTests({inTransaction: true, shardedCollection: true});
-})();
diff --git a/jstests/sharding/api_params_transaction_unsharded.js b/jstests/sharding/api_params_transaction_unsharded.js
deleted file mode 100644
index c171c10d920..00000000000
--- a/jstests/sharding/api_params_transaction_unsharded.js
+++ /dev/null
@@ -1,12 +0,0 @@
-/**
- * When a client calls a mongos command with API parameters, mongos must forward them to shards.
- *
- * @tags: [multiversion_incompatible]
- */
-
-(function() {
-'use strict';
-
-load('jstests/sharding/libs/mongos_api_params_util.js');
-MongosAPIParametersUtil.runTests({inTransaction: true, shardedCollection: false});
-})();
diff --git a/jstests/sharding/libs/mongos_api_params_util.js b/jstests/sharding/libs/mongos_api_params_util.js
deleted file mode 100644
index 1da16ff8d52..00000000000
--- a/jstests/sharding/libs/mongos_api_params_util.js
+++ /dev/null
@@ -1,1496 +0,0 @@
-/*
- * Utilities for checking that mongos commands forward their API version parameters to config
- * servers and shards.
- */
-
-let MongosAPIParametersUtil = (function() {
- 'use strict';
-
- load('jstests/replsets/rslib.js');
- load('jstests/sharding/libs/last_lts_mongos_commands.js');
- load('jstests/sharding/libs/sharded_transactions_helpers.js');
-
- function validateTestCase(testCase) {
- assert(testCase.skip || testCase.run,
- "must specify exactly one of 'skip' or 'run' for test case " + tojson(testCase));
-
- if (testCase.skip) {
- for (let key of Object.keys(testCase)) {
- assert(
- key === "commandName" || key === "skip" || key === "conditional",
- `if a test case specifies 'skip', it must not specify any other fields besides` +
- ` 'commandName' and 'conditional': ${key}: ${tojson(testCase)}`);
- }
- return;
- }
-
- validateCommandTestCase(testCase.run);
-
- if (testCase.explain) {
- validateCommandTestCase(testCase.explain);
- }
- }
-
- function validateCommandTestCase(testCase) {
- assert(testCase.command, "must specify 'command' for test case " + tojson(testCase));
-
- // Check that required fields are present.
- assert(testCase.hasOwnProperty("inAPIVersion1"),
- "must specify 'inAPIVersion1' for test case " + tojson(testCase));
-
- // Check that all present fields are of the correct type.
- assert(typeof (testCase.command) === "function");
- assert(typeof (testCase.inAPIVersion1) === "boolean");
-
- for (const [propertyName, defaultValue] of [["runsAgainstAdminDb", false],
- ["permittedInTxn", true],
- ["permittedOnShardedCollection", true],
- ["requiresShardedCollection", false]]) {
- if (testCase.hasOwnProperty(propertyName)) {
- assert(typeof testCase[propertyName] === "boolean",
- `${propertyName} must be a boolean: ${tojson(testCase)}`);
- } else {
- testCase[propertyName] = defaultValue;
- }
- }
-
- assert(testCase.shardCommandName ? typeof (testCase.shardCommandName) === "string" : true);
- assert(testCase.configServerCommandName
- ? typeof (testCase.configServerCommandName) === "string"
- : true);
- assert(testCase.shardCommandName || testCase.configServerCommandName,
- "must specify shardCommandName and/or configServerCommandName: " + tojson(testCase));
- assert(testCase.setUp ? typeof (testCase.setUp) === "function" : true,
- "setUp must be a function: " + tojson(testCase));
- assert(testCase.cleanUp ? typeof (testCase.cleanUp) === "function" : true,
- "cleanUp must be a function: " + tojson(testCase));
- }
-
- function awaitRemoveShard(shardName) {
- assert.commandWorked(st.startBalancer());
- st.waitForBalancer(true, 60000);
- assert.soon(() => {
- const res = st.s.adminCommand({removeShard: shardName});
- jsTestLog(`removeShard result: ${tojson(res)}`);
- if (!res.ok && res.code === ErrorCodes.ShardNotFound) {
- return true;
- }
-
- return 'completed' === res.state;
- }, "removeShard never completed for shard " + shardName, 10 * 60 * 1000, 1000);
- assert.commandWorked(st.stopBalancer());
- }
-
- // Each test case is potentially run with any combination of API parameters, in
- // sharded/unsharded collection, inside or outside of a multi-document transaction. The "db"
- // database is dropped and recreated between test cases, so most tests don't need custom setUp
- // or cleanUp. Test cases are not 1-1 with commands, e.g. "count" has two cases.
- let testCases = [
- {
- commandName: "_hashBSONElement",
- skip: "executes locally on mongos (not sent to any remote node)"
- },
- {commandName: "_isSelf", skip: "executes locally on mongos (not sent to any remote node)"},
- {
- commandName: "_killOperations",
- skip: "executes locally on mongos (not sent to any remote node)"
- },
- {commandName: "_mergeAuthzCollections", skip: "internal API"},
- {commandName: "abortTransaction", skip: "prohibits API parameters"},
- {
- commandName: "addShard",
- run: {
- inAPIVersion1: false,
- runsAgainstAdminDb: true,
- configServerCommandName: "_configsvrAddShard",
- shardCommandName: "_addShard",
- permittedInTxn: false,
- setUp: () => {
- // Remove shard0 so we can add it back.
- assert.commandWorked(st.s0.getDB("db").dropDatabase());
- awaitRemoveShard(st.shard0.shardName);
- },
- command: () => ({addShard: st.rs0.getURL()})
- }
- },
- {
- commandName: "addShardToZone",
- run: {
- inAPIVersion1: false,
- runsAgainstAdminDb: true,
- configServerCommandName: "_configsvrAddShardToZone",
- permittedInTxn: false,
- command: () => ({addShardToZone: st.shard0.shardName, zone: "foo"}),
- cleanUp: () => assert.commandWorked(st.s0.getDB("admin").runCommand(
- {removeShardFromZone: st.shard0.shardName, zone: "foo"}))
- }
- },
- {
- commandName: "aggregate",
- run: {
- inAPIVersion1: true,
- shardCommandName: "aggregate",
- command: () => ({aggregate: "collection", pipeline: [], cursor: {}})
- },
- explain: {
- inAPIVersion1: true,
- shardCommandName: "explain",
- permittedInTxn: false,
- command: () => ({explain: {aggregate: "collection", pipeline: [], cursor: {}}})
- }
- },
- {
- commandName: "authenticate",
- skip: "executes locally on mongos (not sent to any remote node)"
- },
- {
- commandName: "availableQueryOptions",
- skip: "executes locally on mongos (not sent to any remote node)"
- },
- {
- commandName: "balancerCollectionStatus",
- skip: "executes locally on mongos (not sent to any remote node)"
- },
- {
- commandName: "balancerStart",
- skip: "executes locally on mongos (not sent to any remote node)"
- },
- {
- commandName: "balancerStatus",
- skip: "executes locally on mongos (not sent to any remote node)"
- },
- {
- commandName: "balancerStop",
- skip: "executes locally on mongos (not sent to any remote node)"
- },
- {
- commandName: "buildInfo",
- skip: "executes locally on mongos (not sent to any remote node)"
- },
- {
- commandName: "clearJumboFlag",
- skip: "executes locally on mongos (not sent to any remote node)"
- },
- {commandName: "clearLog", skip: "executes locally on mongos (not sent to any remote node)"},
- {
- commandName: "collMod",
- run: {
- inAPIVersion1: true,
- shardCommandName: "collMod",
- permittedInTxn: false,
- command: () => ({collMod: "collection"}),
- }
- },
- {
- commandName: "collStats",
- run: {
- inAPIVersion1: false,
- shardCommandName: "collStats",
- permittedInTxn: false,
- command: () => ({collStats: "collection"}),
- }
- },
- {commandName: "commitTransaction", skip: "prohibits API parameters"},
- {commandName: "compact", skip: "not allowed through mongos"},
- {
- commandName: "configureFailPoint",
- skip: "executes locally on mongos (not sent to any remote node)"
- },
- {
- commandName: "connPoolStats",
- skip: "executes locally on mongos (not sent to any remote node)"
- },
- {
- commandName: "connPoolSync",
- skip: "executes locally on mongos (not sent to any remote node)"
- },
- {
- commandName: "connectionStatus",
- skip: "executes locally on mongos (not sent to any remote node)"
- },
- {
- commandName: "convertToCapped",
- run: {
- inAPIVersion1: false,
- shardCommandName: "convertToCapped",
- permittedOnShardedCollection: false,
- permittedInTxn: false,
- command: () => ({convertToCapped: "collection", size: 8192}),
- }
- },
- // The count command behaves differently if it has a query or no query.
- {
- commandName: "count",
- run: {
- inAPIVersion1: true,
- shardCommandName: "count",
- permittedInTxn: false,
- command: () => ({count: "collection"})
- },
- explain: {
- inAPIVersion1: true,
- shardCommandName: "explain",
- permittedInTxn: false,
- command: () => ({explain: {count: "collection"}})
- }
- },
- {
- commandName: "count",
- run: {
- inAPIVersion1: true,
- shardCommandName: "count",
- permittedInTxn: false,
- command: () => ({count: "collection", query: {x: 1}})
- },
- explain: {
- inAPIVersion1: true,
- shardCommandName: "explain",
- permittedInTxn: false,
- command: () => ({explain: {count: "collection", query: {x: 1}}})
- }
- },
- {
- commandName: "create",
- run: {
- inAPIVersion1: true,
- shardCommandName: "create",
- command: () => ({create: "collection2"})
- }
- },
- {
- commandName: "createIndexes",
- run: {
- inAPIVersion1: true,
- shardCommandName: "createIndexes",
- permittedInTxn: false,
- command: () =>
- ({createIndexes: "collection", indexes: [{key: {a: 1}, name: "index"}]})
- }
- },
- {
- commandName: "createRole",
- run: {
- inAPIVersion1: false,
- configServerCommandName: "createRole",
- permittedInTxn: false,
- command: () => ({createRole: "foo", privileges: [], roles: []}),
- cleanUp: () => assert.commandWorked(st.s0.getDB("db").runCommand({dropRole: "foo"}))
- }
- },
- {
- commandName: "createUser",
- run: {
- inAPIVersion1: false,
- configServerCommandName: "createUser",
- permittedInTxn: false,
- command: () => ({createUser: "foo", pwd: "bar", roles: []}),
- cleanUp: () => assert.commandWorked(st.s0.getDB("db").runCommand({dropUser: "foo"}))
- }
- },
- {
- commandName: "currentOp",
- run: {
- inAPIVersion1: false,
- shardCommandName: "aggregate",
- permittedInTxn: false,
- runsAgainstAdminDb: true,
- command: () => ({currentOp: 1})
- }
- },
- {
- commandName: "dataSize",
- run: {
- inAPIVersion1: false,
- shardCommandName: "dataSize",
- permittedInTxn: false,
- command: () => ({dataSize: "db.collection"}),
- }
- },
- {
- commandName: "dbStats",
- run: {
- inAPIVersion1: false,
- shardCommandName: "dbStats",
- permittedInTxn: false,
- command: () => ({dbStats: 1, scale: 1})
- }
- },
- {
- commandName: "delete",
- run: {
- inAPIVersion1: true,
- shardCommandName: "delete",
- command: () => ({delete: "collection", deletes: [{q: {_id: 1}, limit: 1}]})
- },
- explain: {
- inAPIVersion1: true,
- shardCommandName: "explain",
- permittedInTxn: false,
- command: () =>
- ({explain: {delete: "collection", deletes: [{q: {_id: 1}, limit: 1}]}})
- }
- },
- {
- commandName: "distinct",
- run: {
- inAPIVersion1: false,
- shardCommandName: "distinct",
- permittedInTxn: false,
- command: () => ({distinct: "collection", key: "x"})
- },
- explain: {
- inAPIVersion1: false,
- shardCommandName: "explain",
- permittedInTxn: false,
- command: () => ({explain: {distinct: "collection", key: "x"}})
- },
- },
- {
- commandName: "drop",
- run: {
- inAPIVersion1: true,
- shardCommandName: "drop",
- permittedInTxn: false,
- command: () => ({drop: "collection"})
- }
- },
- {
- commandName: "dropAllRolesFromDatabase",
- run: {
- inAPIVersion1: false,
- configServerCommandName: "dropAllRolesFromDatabase",
- permittedInTxn: false,
- setUp: () => assert.commandWorked(st.s0.getDB("db").runCommand(
- {createRole: "foo", privileges: [], roles: [], writeConcern: {w: 1}})),
- command: () => ({dropAllRolesFromDatabase: 1})
- }
- },
- {
- commandName: "dropAllUsersFromDatabase",
- run: {
- inAPIVersion1: false,
- configServerCommandName: "dropAllUsersFromDatabase",
- permittedInTxn: false,
- setUp: () => assert.commandWorked(st.s0.getDB("db").runCommand(
- {createUser: "foo", pwd: "bar", roles: [], writeConcern: {w: 1}})),
- command: () => ({dropAllUsersFromDatabase: 1})
- }
- },
- {
- commandName: "dropConnections",
- skip: "executes locally on mongos (not sent to any remote node)"
- },
- {
- commandName: "dropDatabase",
- run: {
- inAPIVersion1: true,
- configServerCommandName: "_configsvrDropDatabase",
- shardCommandName: "dropDatabase",
- permittedInTxn: false,
- command: () => ({dropDatabase: 1})
- }
- },
- {
- commandName: "dropIndexes",
- run: {
- inAPIVersion1: true,
- shardCommandName: "dropIndexes",
- permittedInTxn: false,
- command: () => ({dropIndexes: "collection", index: "*"}),
- }
- },
- {
- commandName: "dropRole",
- run: {
- inAPIVersion1: false,
- configServerCommandName: "dropRole",
- permittedInTxn: false,
- setUp: () => assert.commandWorked(st.s0.getDB("db").runCommand(
- {createRole: "foo", privileges: [], roles: [], writeConcern: {w: 1}})),
- command: () => ({dropRole: "foo"})
- }
- },
- {
- commandName: "dropUser",
- run: {
- inAPIVersion1: false,
- configServerCommandName: "dropUser",
- permittedInTxn: false,
- setUp: () => assert.commandWorked(st.s0.getDB("db").runCommand(
- {createUser: "foo", pwd: "bar", roles: [], writeConcern: {w: 1}})),
- command: () => ({dropUser: "foo"})
- }
- },
- {commandName: "echo", skip: "executes locally on mongos (not sent to any remote node)"},
- {
- commandName: "enableSharding",
- skip: "executes locally on mongos (not sent to any remote node)"
- },
- {
- commandName: "endSessions",
- skip: "executes locally on mongos (not sent to any remote node)"
- },
- {commandName: "explain", skip: "tested by other means"},
- {commandName: "features", skip: "executes locally on mongos (not sent to any remote node)"},
- {
- commandName: "filemd5",
- run: {
- inAPIVersion1: false,
- shardCommandName: "filemd5",
- permittedInTxn: false,
- command: () => ({filemd5: ObjectId(), root: "collection"})
- }
- },
- {
- commandName: "find",
- run: {
- inAPIVersion1: true,
- shardCommandName: "find",
- command: () => ({find: "collection", filter: {x: 1}})
- },
- explain: {
- inAPIVersion1: true,
- shardCommandName: "explain",
- permittedInTxn: false,
- command: () => ({explain: {find: "collection", filter: {x: 1}}})
- }
- },
- {
- commandName: "findAndModify",
- run: {
- inAPIVersion1: true,
- shardCommandName: "findAndModify",
- command: () => ({findAndModify: "collection", query: {_id: 0}, remove: true})
- },
- explain: {
- inAPIVersion1: true,
- shardCommandName: "explain",
- permittedInTxn: false,
- command: () =>
- ({explain: {findAndModify: "collection", query: {_id: 0}, remove: true}})
- }
- },
- {
- commandName: "flushRouterConfig",
- skip: "executes locally on mongos (not sent to any remote node)"
- },
- {
- commandName: "fsync",
- run: {
- inAPIVersion1: false,
- shardCommandName: "fsync",
- runsAgainstAdminDb: true,
- permittedInTxn: false,
- command: () => ({fsync: 1})
- }
- },
- {
- commandName: "getCmdLineOpts",
- skip: "executes locally on mongos (not sent to any remote node)"
- },
- {
- commandName: "getDefaultRWConcern",
- run: {
- inAPIVersion1: false,
- configServerCommandName: "getDefaultRWConcern",
- runsAgainstAdminDb: true,
- permittedInTxn: false,
- command: () => ({getDefaultRWConcern: 1})
- }
- },
- {
- commandName: "getDiagnosticData",
- skip: "executes locally on mongos (not sent to any remote node)"
- },
- {
- commandName: "getLastError",
- skip: "executes locally on mongos (not sent to any remote node)"
- },
- {commandName: "getLog", skip: "executes locally on mongos (not sent to any remote node)"},
- {commandName: "getMore", skip: "prohibits API parameters"},
- {
- commandName: "getParameter",
- skip: "executes locally on mongos (not sent to any remote node)"
- },
- {
- commandName: "getShardMap",
- skip: "executes locally on mongos (not sent to any remote node)"
- },
- {
- commandName: "getShardVersion",
- skip: "executes locally on mongos (not sent to any remote node)"
- },
- {commandName: "getnonce", skip: "executes locally on mongos (not sent to any remote node)"},
- {
- commandName: "grantPrivilegesToRole",
- run: {
- inAPIVersion1: false,
- configServerCommandName: "grantPrivilegesToRole",
- permittedInTxn: false,
- setUp: () => assert.commandWorked(st.s0.getDB("db").runCommand(
- {createRole: "foo", privileges: [], roles: [], writeConcern: {w: 1}})),
- command: () => ({
- grantPrivilegesToRole: "foo",
- privileges:
- [{resource: {db: "db", collection: "collection"}, actions: ["find"]}]
- }),
- cleanUp: () =>
- assert.commandWorked(st.s0.getDB("db").runCommand({dropRole: "foo"})),
- }
- },
- {
- commandName: "grantRolesToRole",
- run: {
- inAPIVersion1: false,
- configServerCommandName: "grantRolesToRole",
- permittedInTxn: false,
- setUp: function() {
- assert.commandWorked(st.s0.getDB("db").runCommand(
- {createRole: "foo", privileges: [], roles: [], writeConcern: {w: 1}}));
- assert.commandWorked(st.s0.getDB("db").runCommand(
- {createRole: "bar", privileges: [], roles: [], writeConcern: {w: 1}}));
- },
- command: () => ({grantRolesToRole: "foo", roles: [{role: "bar", db: "db"}]}),
- cleanUp: () => {
- assert.commandWorked(st.s0.getDB("db").runCommand({dropRole: "foo"}));
- assert.commandWorked(st.s0.getDB("db").runCommand({dropRole: "bar"}));
- }
- }
- },
- {
- commandName: "grantRolesToUser",
- run: {
- inAPIVersion1: false,
- configServerCommandName: "grantRolesToUser",
- permittedInTxn: false,
- setUp: () => {
- assert.commandWorked(st.s0.getDB("db").runCommand(
- {createUser: "foo", pwd: "bar", roles: [], writeConcern: {w: 1}}));
- assert.commandWorked(st.s0.getDB("db").runCommand(
- {createRole: "foo", privileges: [], roles: [], writeConcern: {w: 1}}));
- },
- command: () => ({grantRolesToUser: "foo", roles: [{role: "foo", db: "db"}]}),
- cleanUp: () => {
- assert.commandWorked(st.s0.getDB("db").runCommand({dropUser: "foo"}));
- assert.commandWorked(st.s0.getDB("db").runCommand({dropRole: "foo"}));
- }
- }
- },
- {commandName: "hello", skip: "executes locally on mongos (not sent to any remote node)"},
- {commandName: "hostInfo", skip: "executes locally on mongos (not sent to any remote node)"},
- {
- commandName: "insert",
- run: {
- inAPIVersion1: true,
- shardCommandName: "insert",
- command: () => ({insert: "collection", documents: [{_id: 1}]}),
- }
- },
- {
- commandName: "invalidateUserCache",
- skip: "executes locally on mongos (not sent to any remote node)"
- },
- {commandName: "isdbgrid", skip: "executes locally on mongos (not sent to any remote node)"},
- {commandName: "isMaster", skip: "executes locally on mongos (not sent to any remote node)"},
- {
- commandName: "killCursors",
- run:
- {
- inAPIVersion1: true,
- shardCommandName: "killCursors",
- permittedInTxn: false,
- setUp: () => assert.commandWorked(st.s0.getDB("db").runCommand(
- {insert: "collection", documents: [{}, {}, {}]})),
- command:
- () => {
- const res = assert.commandWorked(
- st.s0.getDB("db").runCommand({find: "collection", batchSize: 1}));
- jsTestLog(`res: ${res}`);
- const cursorId = res.cursor.id;
- return {killCursors: "collection", cursors: [cursorId]};
- }
- }
- },
- {
- commandName: "killAllSessions",
- run: {
- inAPIVersion1: false,
- shardCommandName: "killAllSessionsByPattern",
- runsAgainstAdminDb: true,
- permittedInTxn: false,
- command: () => ({killAllSessions: []})
- }
- },
- {
- commandName: "killAllSessionsByPattern",
- run: {
- inAPIVersion1: false,
- shardCommandName: "killAllSessionsByPattern",
- runsAgainstAdminDb: true,
- permittedInTxn: false,
- command: () => ({killAllSessionsByPattern: []})
- }
- },
- {
- commandName: "killOp",
- run: {
- inAPIVersion1: false,
- shardCommandName: "killOp",
- permittedInTxn: false,
- runsAgainstAdminDb: true,
- setUp: (context) => {
- function threadRoutine({connStr}) {
- const client = new Mongo(connStr);
- jsTestLog(`Calling find on "${connStr}" from thread`);
- const res = client.getDB("db").runCommand({
- find: "collection",
- filter: {$where: "sleep(99999999); return true;"},
- comment: "foo"
- });
- jsTestLog(`Called find command: ${tojson(res)}`);
- }
-
- context.thread = new Thread(threadRoutine, {connStr: st.s0.host});
- context.thread.start();
- const adminDb = st.s0.getDB("admin");
-
- assert.soon(() => {
- const inprog = adminDb.currentOp({"command.comment": "foo"}).inprog;
- if (inprog.length === 1) {
- context.findOpId = inprog[0].opid;
- return true;
- }
- });
- },
- command: (context) => ({killOp: 1, op: context.findOpId}),
- cleanUp: (context) => {
- context.thread.join();
- }
- }
- },
- {
- commandName: "killSessions",
- run: {
- inAPIVersion1: false,
- shardCommandName: "killAllSessionsByPattern",
- runsAgainstAdminDb: true,
- permittedInTxn: false,
- setUp: (context) => {
- const session = st.s0.startSession();
- context.lsid = session.getSessionId();
- },
- command: (context) => ({killSessions: [context.lsid]})
- }
- },
- {
- commandName: "listCollections",
- run: {
- inAPIVersion1: true,
- shardCommandName: "listCollections",
- permittedInTxn: false,
- command: () => ({listCollections: 1})
- }
- },
- {
- commandName: "listCommands",
- skip: "executes locally on mongos (not sent to any remote node)"
- },
- {
- commandName: "listDatabases",
- skip: "executes locally on mongos (not sent to any remote node)"
- },
- {
- commandName: "listIndexes",
- run: {
- inAPIVersion1: true,
- shardCommandName: "listIndexes",
- permittedInTxn: false,
- command: () => ({listIndexes: "collection"}),
- }
- },
- {
- commandName: "listShards",
- skip: "executes locally on mongos (not sent to any remote node)"
- },
- {
- commandName: "logApplicationMessage",
- skip: "executes locally on mongos (not sent to any remote node)",
- conditional: true
- },
- {
- commandName: "logMessage",
- skip: "executes locally on mongos (not sent to any remote node)"
- },
- {
- commandName: "logRotate",
- skip: "executes locally on mongos (not sent to any remote node)"
- },
- {commandName: "logout", skip: "executes locally on mongos (not sent to any remote node)"},
- {
- commandName: "mapReduce",
- run: {
- inAPIVersion1: false,
- permittedInTxn: false,
- shardCommandName: "aggregate",
- command: () => ({
- mapReduce: "collection",
- map: function mapFunc() {
- emit(this.x, 1);
- },
- reduce: function reduceFunc(key, values) {
- return Array.sum(values);
- },
- out: "inline"
- }),
- },
- explain: {
- inAPIVersion1: false,
- shardCommandName: "explain",
- permittedInTxn: false,
- command: () => ({
- explain: {
- mapReduce: "collection",
- map: function mapFunc() {
- emit(this.x, 1);
- },
- reduce: function reduceFunc(key, values) {
- return Array.sum(values);
- },
- out: "inline"
- }
- }),
- }
- },
- {
- commandName: "mergeChunks",
- run: {
- inAPIVersion1: false,
- shardCommandName: "mergeChunks",
- configServerCommandName: "_configsvrCommitChunkMerge",
- runsAgainstAdminDb: true,
- permittedInTxn: false,
- requiresShardedCollection: true,
- setUp: () => {
- // Collection is already split into chunks [MinKey, 10], (10, MaxKey].
- assert.commandWorked(
- st.s.adminCommand({split: "db.collection", middle: {_id: -5}}));
- // Now the chunks are: [MinKey, -5], (-5, 10], (10, MaxKey].
- },
- command: () => ({mergeChunks: "db.collection", bounds: [{_id: MinKey}, {_id: 10}]})
- }
- },
- {
- commandName: "moveChunk",
- run: {
- inAPIVersion1: false,
- shardCommandName: "moveChunk",
- configServerCommandName: "_configsvrMoveChunk",
- runsAgainstAdminDb: true,
- permittedInTxn: false,
- requiresShardedCollection: true,
- command: () => ({
- moveChunk: "db.collection",
- find: {_id: 1},
- to: st.shard1.shardName,
- // Don't interfere with the next test case.
- _waitForDelete: true
- })
- }
- },
- {
- commandName: "movePrimary",
- run: {
- inAPIVersion1: false,
- configServerCommandName: "_configsvrMovePrimary",
- shardCommandName: "_shardsvrMovePrimary",
- runsAgainstAdminDb: true,
- permittedInTxn: false,
- command: () => ({movePrimary: "db", to: st.shard1.shardName})
- }
- },
- {
- commandName: "multicast",
- skip: "executes locally on mongos (not sent to any remote node)"
- },
- {commandName: "netstat", skip: "executes locally on mongos (not sent to any remote node)"},
- {commandName: "ping", skip: "executes locally on mongos (not sent to any remote node)"},
- {
- commandName: "planCacheClear",
- run: {
- inAPIVersion1: false,
- shardCommandName: "planCacheClear",
- permittedInTxn: false,
- command: () => ({planCacheClear: "collection"})
- }
- },
- {
- commandName: "planCacheClearFilters",
- run: {
- inAPIVersion1: false,
- shardCommandName: "planCacheClearFilters",
- permittedInTxn: false,
- command: () => ({planCacheClearFilters: "collection"})
- }
- },
- {
- commandName: "planCacheListFilters",
- run: {
- inAPIVersion1: false,
- shardCommandName: "planCacheListFilters",
- permittedInTxn: false,
- setUp: () => assert.commandWorked(st.s0.getDB("db").runCommand(
- {planCacheSetFilter: "collection", query: {_id: 1}, indexes: [{_id: 1}]})),
- command: () => ({planCacheListFilters: "collection"})
- }
- },
- {
- commandName: "planCacheSetFilter",
- run: {
- inAPIVersion1: false,
- shardCommandName: "planCacheSetFilter",
- permittedInTxn: false,
- command: () =>
- ({planCacheSetFilter: "collection", query: {_id: 1}, indexes: [{_id: 1}]}),
- }
- },
- {commandName: "profile", skip: "not supported in mongos"},
- {commandName: "reapLogicalSessionCacheNow", skip: "is a no-op on mongos"},
- {
- commandName: "refineCollectionShardKey",
- run: {
- inAPIVersion1: false,
- configServerCommandName: "_configsvrRefineCollectionShardKey",
- runsAgainstAdminDb: true,
- permittedInTxn: false,
- requiresShardedCollection: true,
- setUp: () => assert.commandWorked(st.s0.getDB("db").runCommand({
- createIndexes: "collection",
- indexes: [{key: {_id: 1, x: 1}, name: "_id-1-x-1"}]
- })),
- command: () => ({refineCollectionShardKey: "db.collection", key: {_id: 1, x: 1}})
- }
- },
- {
- commandName: "refreshLogicalSessionCacheNow",
- skip: "executes locally on mongos (not sent to any remote node)"
- },
- {
- commandName: "refreshSessions",
- skip: "executes locally on mongos (not sent to any remote node)"
- },
- {
- commandName: "removeShard",
- run: {
- inAPIVersion1: false,
- runsAgainstAdminDb: true,
- configServerCommandName: "_configsvrRemoveShard",
- permittedInTxn: false,
- command: () => ({removeShard: st.shard0.shardName}),
- cleanUp: () => {
- // Wait for the shard to be removed completely before re-adding it.
- awaitRemoveShard(st.shard0.shardName);
- assert.commandWorked(st.s0.getDB("admin").runCommand(
- {addShard: st.rs0.getURL(), name: st.shard0.shardName}));
- }
- }
- },
- {
- commandName: "removeShardFromZone",
- run: {
- inAPIVersion1: false,
- runsAgainstAdminDb: true,
- configServerCommandName: "_configsvrRemoveShardFromZone",
- permittedInTxn: false,
- setup: () =>
- assert.commandWorked({addShardToZone: st.shard0.shardName, zone: "foo"}),
- command: () => ({removeShardFromZone: st.shard0.shardName, zone: "foo"})
- }
- },
- {
- commandName: "renameCollection",
- run: {
- inAPIVersion1: false,
- shardCommandName: "renameCollection",
- permittedOnShardedCollection: false,
- permittedInTxn: false,
- runsAgainstAdminDb: true,
- command: () => ({renameCollection: "db.collection", to: "db.collection_renamed"})
- }
- },
- {commandName: "replSetGetStatus", skip: "not supported in mongos"},
- {
- commandName: "resetError",
- skip: "executes locally on mongos (not sent to any remote node)"
- },
- {
- commandName: "reshardCollection",
- run: {
- inAPIVersion1: false,
- permittedInTxn: false,
- configServerCommandName: "_configsvrReshardCollection",
- requiresShardedCollection: true,
- runsAgainstAdminDb: true,
- command: () => ({reshardCollection: "db.collection", key: {_id: 1}})
- }
- },
- {
- commandName: "revokePrivilegesFromRole",
- run: {
- inAPIVersion1: false,
- permittedInTxn: false,
- configServerCommandName: "revokePrivilegesFromRole",
- setUp: () => assert.commandWorked(st.s0.getDB("db").runCommand({
- createRole: "foo",
- privileges:
- [{resource: {db: "db", collection: "collection"}, actions: ["find"]}],
- roles: [],
- writeConcern: {w: 1}
- })),
- command: () => ({
- revokePrivilegesFromRole: "foo",
- privileges:
- [{resource: {db: "db", collection: "collection"}, actions: ["find"]}]
- }),
- cleanUp: () => {
- assert.commandWorked(st.s0.getDB("db").runCommand({dropRole: "foo"}));
- }
- }
- },
- {
- commandName: "revokeRolesFromRole",
- run: {
- inAPIVersion1: false,
- permittedInTxn: false,
- configServerCommandName: "revokeRolesFromRole",
- setUp: () => {
- assert.commandWorked(st.s0.getDB("db").runCommand(
- {createRole: "foo", privileges: [], roles: [], writeConcern: {w: 1}}));
- assert.commandWorked(st.s0.getDB("db").runCommand(
- {createRole: "bar", privileges: [], roles: [], writeConcern: {w: 1}}));
- assert.commandWorked(st.s0.getDB("db").runCommand(
- {grantRolesToRole: "foo", roles: [{role: "bar", db: "db"}]}));
- },
- command: () => ({revokeRolesFromRole: "foo", roles: [{role: "bar", db: "db"}]}),
- cleanUp: () => {
- assert.commandWorked(st.s0.getDB("db").runCommand({dropRole: "foo"}));
- assert.commandWorked(st.s0.getDB("db").runCommand({dropRole: "bar"}));
- }
- }
- },
- {
- commandName: "revokeRolesFromUser",
- run: {
- inAPIVersion1: false,
- configServerCommandName: "revokeRolesFromUser",
- permittedInTxn: false,
- setUp: () => {
- assert.commandWorked(st.s0.getDB("db").runCommand(
- {createUser: "foo", pwd: "bar", roles: [], writeConcern: {w: 1}}));
- assert.commandWorked(st.s0.getDB("db").runCommand(
- {createRole: "foo", privileges: [], roles: [], writeConcern: {w: 1}}));
- assert.commandWorked(st.s0.getDB("db").runCommand(
- {grantRolesToUser: "foo", roles: [{role: "foo", db: "db"}]}));
- },
- command: () => ({revokeRolesFromUser: "foo", roles: [{role: "foo", db: "db"}]}),
- cleanUp: () => {
- assert.commandWorked(st.s0.getDB("db").runCommand({dropUser: "foo"}));
- assert.commandWorked(st.s0.getDB("db").runCommand({dropRole: "foo"}));
- }
- }
- },
- {
- commandName: "rolesInfo",
- run: {
- inAPIVersion1: false,
- configServerCommandName: "rolesInfo",
- permittedInTxn: false,
- command: () => ({rolesInfo: 1})
- }
- },
- {
- commandName: "rotateCertificates",
- skip: "executes locally on mongos (not sent to any remote node)"
- },
- {
- commandName: "saslContinue",
- skip: "executes locally on mongos (not sent to any remote node)"
- },
- {
- commandName: "saslStart",
- skip: "executes locally on mongos (not sent to any remote node)"
- },
- {
- commandName: "serverStatus",
- skip: "executes locally on mongos (not sent to any remote node)"
- },
- {
- commandName: "setDefaultRWConcern",
- run: {
- inAPIVersion1: false,
- configServerCommandName: "setDefaultRWConcern",
- runsAgainstAdminDb: true,
- permittedInTxn: false,
- command: () => ({setDefaultRWConcern: 1, defaultWriteConcern: {w: 1}})
- }
- },
- {
- commandName: "setIndexCommitQuorum",
- run: {
- inAPIVersion1: false,
- shardCommandName: "setIndexCommitQuorum",
- permittedInTxn: false,
- command: () => ({
- setIndexCommitQuorum: "collection",
- indexNames: ["index"],
- commitQuorum: "majority"
- }),
- }
- },
- {
- commandName: "setFeatureCompatibilityVersion",
- run: {
- inAPIVersion1: false,
- configServerCommandName: "setFeatureCompatibilityVersion",
- permittedInTxn: false,
- runsAgainstAdminDb: true,
- command: () => ({setFeatureCompatibilityVersion: latestFCV})
- }
- },
- {
- commandName: "setFreeMonitoring",
- skip: "explicitly fails for mongos, primary mongod only",
- conditional: true
- },
- {
- commandName: "setParameter",
- skip: "executes locally on mongos (not sent to any remote node)"
- },
- {
- commandName: "shardCollection",
- run: {
- inAPIVersion1: false,
- configServerCommandName: "_configsvrShardCollection",
- shardCommandName: "_shardsvrShardCollection",
- runsAgainstAdminDb: true,
- permittedInTxn: false,
- permittedOnShardedCollection: false,
- setUp: () => {
- assert.commandWorked(st.s.adminCommand({enableSharding: "db"}));
- st.ensurePrimaryShard("db", st.shard0.shardName);
- },
- command: () => ({shardCollection: "db.collection", key: {_id: 1}})
- }
- },
- {
- commandName: "shardConnPoolStats",
- skip: "executes locally on mongos (not sent to any remote node)"
- },
- {commandName: "shutdown", skip: "executes locally on mongos (not sent to any remote node)"},
- {
- commandName: "split",
- run: {
- inAPIVersion1: false,
- configServerCommandName: "_configsvrCommitChunkSplit",
- shardCommandName: "splitChunk",
- runsAgainstAdminDb: true,
- permittedInTxn: false,
- requiresShardedCollection: true,
- command: () => ({split: "db.collection", middle: {_id: 5}})
- }
- },
- {
- commandName: "splitVector",
- run: {
- inAPIVersion1: false,
- shardCommandName: "splitVector",
- permittedInTxn: false,
- permittedOnShardedCollection: false,
- command: () => ({
- splitVector: "db.collection",
- keyPattern: {_id: 1},
- min: {_id: 0},
- max: {_id: MaxKey},
- maxChunkSizeBytes: 1024
- })
- }
- },
- {
- commandName: "startRecordingTraffic",
- skip: "executes locally on mongos (not sent to any remote node)"
- },
- {
- commandName: "startSession",
- skip: "executes locally on mongos (not sent to any remote node)"
- },
- {
- commandName: "stopRecordingTraffic",
- skip: "executes locally on mongos (not sent to any remote node)"
- },
- {
- commandName: "testDeprecation",
- skip: "executes locally on mongos (not sent to any remote node)"
- },
- {
- commandName: "testDeprecationInVersion2",
- skip: "executes locally on mongos (not sent to any remote node)"
- },
- {
- commandName: "testRemoval",
- skip: "executes locally on mongos (not sent to any remote node)"
- },
- {
- commandName: "testVersion2",
- skip: "executes locally on mongos (not sent to any remote node)"
- },
- {
- commandName: "testVersions1And2",
- skip: "executes locally on mongos (not sent to any remote node)"
- },
- {
- commandName: "update",
- run: {
- inAPIVersion1: true,
- shardCommandName: "update",
- command: () => ({
- update: "collection",
- updates: [{q: {_id: 2}, u: {_id: 2}, upsert: true, multi: false}]
- }),
- },
- explain: {
- inAPIVersion1: true,
- shardCommandName: "explain",
- permittedInTxn: false,
- command: () => ({
- explain: {
- update: "collection",
- updates: [{q: {_id: 2}, u: {_id: 2}, upsert: true, multi: false}]
- }
- }),
- }
- },
- {
- commandName: "updateRole",
- run: {
- inAPIVersion1: false,
- configServerCommandName: "updateRole",
- permittedInTxn: false,
- setUp: () => assert.commandWorked(st.s0.getDB("db").runCommand(
- {createRole: "foo", privileges: [], roles: [], writeConcern: {w: 1}})),
- command: () => ({updateRole: "foo", authenticationRestrictions: []}),
- cleanUp: () => assert.commandWorked(
- st.s0.getDB("db").runCommand({dropAllRolesFromDatabase: 1}))
- }
- },
- {
- commandName: "updateUser",
- run: {
- inAPIVersion1: false,
- configServerCommandName: "updateUser",
- permittedInTxn: false,
- setUp: () => assert.commandWorked(st.s0.getDB("db").runCommand(
- {createUser: "foo", pwd: "bar", roles: [], writeConcern: {w: 1}})),
- command: () => ({updateUser: "foo", authenticationRestrictions: []}),
- cleanUp: () => assert.commandWorked(
- st.s0.getDB("db").runCommand({dropAllUsersFromDatabase: 1}))
- }
- },
- {
- commandName: "updateZoneKeyRange",
- run: {
- inAPIVersion1: false,
- configServerCommandName: "_configsvrUpdateZoneKeyRange",
- permittedInTxn: false,
- runsAgainstAdminDb: true,
- setUp: () => assert.commandWorked(st.s0.getDB("admin").runCommand(
- {addShardToZone: st.shard0.shardName, zone: "foo"})),
- command: () => ({
- updateZoneKeyRange: "db.collection",
- min: {_id: 1},
- max: {_id: 5},
- zone: "foo"
- }),
- cleanUp: () => {
- // Remove zone key range.
- assert.commandWorked(st.s0.getDB("admin").runCommand({
- updateZoneKeyRange: "db.collection",
- min: {_id: 1},
- max: {_id: 5},
- zone: null
- }));
- assert.commandWorked(st.s0.getDB("admin").runCommand(
- {removeShardFromZone: st.shard0.shardName, zone: "foo"}));
- }
- }
- },
- {
- commandName: "usersInfo",
- run: {
- inAPIVersion1: false,
- configServerCommandName: "usersInfo",
- permittedInTxn: false,
- command: () => ({usersInfo: 1})
- }
- },
- {
- commandName: "validate",
- run: {
- inAPIVersion1: false,
- shardCommandName: "validate",
- permittedInTxn: false,
- command: () => ({validate: "collection"}),
- }
- },
- {
- commandName: "waitForFailPoint",
- skip: "executes locally on mongos (not sent to any remote node)"
- },
- {
- commandName: "whatsmyuri",
- skip: "executes locally on mongos (not sent to any remote node)"
- },
- ];
-
- commandsRemovedFromMongosSinceLastLTS.forEach(function(cmd) {
- testCases[cmd] = {
- skip: "must define test coverage for latest version backwards compatibility"
- };
- });
-
- const st = new ShardingTest({mongos: 1, shards: 2, rs: {nodes: 1}});
- const listCommandsRes = st.s0.adminCommand({listCommands: 1});
- assert.commandWorked(listCommandsRes);
-
- (() => {
- // Validate test cases for all commands. Ensure there is at least one test case for every
- // mongos command, and that the test cases are well formed.
- for (const command of Object.keys(listCommandsRes.commands)) {
- const matchingCases = testCases.filter(elem => elem.commandName === command);
- assert(matchingCases !== [],
- "coverage failure: must define a test case for " + command);
- for (const testCase of matchingCases) {
- validateTestCase(testCase);
- testCase.validated = true;
- }
- }
-
- // After iterating through all the existing commands, ensure there were no additional test
- // cases that did not correspond to any mongos command.
- for (const testCase of testCases) {
- // We have defined real test cases for commands added since the last LTS version so that
- // the test cases are exercised in the regular suites, but because these test cases
- // can't run in the last stable suite, we skip processing them here to avoid failing the
- // below assertion. We have defined "skip" test cases for commands removed since the
- // last LTS version so the test case is defined in last stable suites (in which these
- // commands still exist on the mongos), but these test cases won't be run in regular
- // suites, so we skip processing them below as well.
- if (commandsAddedToMongosSinceLastLTS.includes(testCase.commandName) ||
- commandsRemovedFromMongosSinceLastLTS.includes(testCase.commandName))
- continue;
- assert(testCase.validated || testCase.conditional,
- "you defined a test case for a command '" + testCase.commandName +
- "' that does not exist on mongos: " + tojson(testCase));
- }
- })();
-
- function checkPrimaryLog(conn, commandName, apiVersion, apiStrict, apiDeprecationErrors) {
- const logs = checkLog.getGlobalLog(conn);
- let lastCommandInvocation;
-
- for (let logMsg of logs) {
- const obj = JSON.parse(logMsg);
- // Search for "About to run the command" logs.
- if (obj.id !== 21965)
- continue;
-
- const args = obj.attr.commandArgs;
- if (commandName !== Object.keys(args)[0])
- continue;
-
- lastCommandInvocation = args;
- if (args.apiVersion !== apiVersion || args.apiStrict !== apiStrict ||
- args.apiDeprecationErrors !== apiDeprecationErrors)
- continue;
-
- // Found a match.
- return;
- }
-
- if (lastCommandInvocation === undefined) {
- doassert(`Primary didn't log ${commandName}`);
- return;
- }
-
- doassert(`Primary didn't log ${commandName} with apiVersion ${apiVersion},` +
- ` apiStrict ${apiStrict},` +
- ` apiDeprecationErrors ${apiDeprecationErrors}.` +
- ` Last invocation of ${commandName} was` +
- ` ${tojson(lastCommandInvocation)}`);
- }
-
- function runTests({inTransaction, shardedCollection}) {
- // For each combination of config parameters and test case, create a test instance. Do this
- // before executing the test instances so we can count the number of instances and log
- // progress.
- let testInstances = [];
-
- for (const [apiVersion, apiStrict, apiDeprecationErrors] of [
- [undefined, undefined, undefined],
- ["1", undefined, undefined],
- ["1", undefined, false],
- ["1", undefined, true],
- ["1", false, undefined],
- ["1", false, false],
- ["1", false, true],
- ["1", true, undefined],
- ["1", true, false],
- ["1", true, true],
- ]) {
- for (const testCase of testCases) {
- if (testCase.skip)
- continue;
-
- for (let runOrExplain of [testCase.run, testCase.explain]) {
- if (runOrExplain === undefined)
- continue;
-
- if (inTransaction && !runOrExplain.permittedInTxn)
- continue;
-
- if (shardedCollection && !runOrExplain.permittedOnShardedCollection)
- continue;
-
- if (!shardedCollection && runOrExplain.requiresShardedCollection)
- continue;
-
- if (apiStrict && !runOrExplain.inAPIVersion1)
- continue;
-
- testInstances.push({
- apiVersion: apiVersion,
- apiStrict: apiStrict,
- apiDeprecationErrors: apiDeprecationErrors,
- commandName: testCase.commandName,
- runOrExplain: runOrExplain
- });
- }
- }
- }
-
- for (let i = 0; i < testInstances.length; ++i) {
- const {apiVersion, apiStrict, apiDeprecationErrors, commandName, runOrExplain} =
- testInstances[i];
-
- if (shardedCollection) {
- jsTestLog("Sharded setup");
- assert.commandWorked(st.s.getDB("db")["collection"].insert(
- {_id: 0}, {writeConcern: {w: "majority"}}));
- assert.commandWorked(st.s.getDB("db")["collection"].insert(
- {_id: 20}, {writeConcern: {w: "majority"}}));
-
- assert.commandWorked(st.s.adminCommand({enableSharding: "db"}));
- st.ensurePrimaryShard("db", st.shard0.shardName);
- assert.commandWorked(
- st.s.adminCommand({shardCollection: "db.collection", key: {_id: 1}}));
-
- // The chunk with _id 1 is on shard 0.
- assert.commandWorked(
- st.s.adminCommand({split: "db.collection", middle: {_id: 10}}));
- assert.commandWorked(st.s.adminCommand({
- moveChunk: "db.collection",
- find: {_id: 20},
- to: st.shard1.shardName,
- _waitForDelete: true
- }));
- } else {
- jsTestLog("Unsharded setup");
- assert.commandWorked(st.s.getDB("db")["collection"].insert(
- {_id: 0}, {writeConcern: {w: "majority"}}));
- st.ensurePrimaryShard("db", st.shard0.shardName);
- }
-
- const configPrimary = st.configRS.getPrimary();
- const shardZeroPrimary = st.rs0.getPrimary();
- const context = {};
-
- if (runOrExplain.setUp) {
- jsTestLog(`setUp function for ${commandName}`);
- runOrExplain.setUp(context);
- jsTestLog(`setUp function for ${commandName} completed`);
- }
-
- // Make a copy of the test's command body, and set its API parameters.
- const commandDbName = runOrExplain.runsAgainstAdminDb ? "admin" : "db";
- const commandBody = runOrExplain.command(context);
- const commandWithAPIParams = Object.assign({}, commandBody);
- if (apiVersion !== undefined) {
- commandWithAPIParams.apiVersion = apiVersion;
- }
-
- if (apiStrict !== undefined) {
- commandWithAPIParams.apiStrict = apiStrict;
- }
-
- if (apiDeprecationErrors !== undefined) {
- commandWithAPIParams.apiDeprecationErrors = apiDeprecationErrors;
- }
-
- assert.commandWorked(configPrimary.adminCommand({clearLog: "global"}));
- assert.commandWorked(shardZeroPrimary.adminCommand({clearLog: "global"}));
- const message =
- `[${i + 1} of ${testInstances.length}]: command ${tojson(commandWithAPIParams)}` +
- ` ${shardedCollection ? "sharded" : "unsharded"},` +
- ` ${inTransaction ? "in" : "outside"} transaction` +
- ` on "${commandDbName}" database`;
-
- flushRoutersAndRefreshShardMetadata(st, {ns: "db.collection"});
-
- jsTestLog(`Running ${message}`);
- setLogVerbosity([configPrimary, shardZeroPrimary], {"command": {"verbosity": 2}});
-
- if (inTransaction) {
- const session = st.s0.startSession();
- const sessionDb = session.getDatabase(commandDbName);
- session.startTransaction();
- assert.commandWorked(sessionDb.runCommand(commandWithAPIParams));
- assert.commandWorked(session.commitTransaction_forTesting());
- } else {
- const db = st.s0.getDB(commandDbName);
- assert.commandWorked(db.runCommand(commandWithAPIParams));
- }
-
- setLogVerbosity([configPrimary, shardZeroPrimary], {"command": {"verbosity": 0}});
-
- const configServerCommandName = runOrExplain.configServerCommandName;
- const shardCommandName = runOrExplain.shardCommandName;
-
- if (configServerCommandName) {
- jsTestLog(`Check for ${configServerCommandName} in config server's log`);
- checkPrimaryLog(configPrimary,
- configServerCommandName,
- apiVersion,
- apiStrict,
- apiDeprecationErrors);
- }
-
- if (shardCommandName) {
- jsTestLog(`Check for ${shardCommandName} in shard server's log`);
- checkPrimaryLog(shardZeroPrimary,
- shardCommandName,
- apiVersion,
- apiStrict,
- apiDeprecationErrors);
- }
-
- st.s0.getDB("db").runCommand({dropDatabase: 1});
- if (runOrExplain.cleanUp) {
- jsTestLog(`cleanUp function for ${commandName}`);
- runOrExplain.cleanUp(context);
- jsTestLog(`cleanUp function for ${commandName} completed`);
- }
- }
-
- st.stop();
- }
-
- return {runTests: runTests};
-})();
diff --git a/jstests/sharding/mongos_forwards_api_parameters_to_shards.js b/jstests/sharding/mongos_forwards_api_parameters_to_shards.js
new file mode 100644
index 00000000000..e611f716992
--- /dev/null
+++ b/jstests/sharding/mongos_forwards_api_parameters_to_shards.js
@@ -0,0 +1,213 @@
+/**
+ * When a client calls a mongos command with API parameters, mongos must forward them to shards.
+ *
+ * @tags: [multiversion_incompatible]
+ */
+
+(function() {
+'use strict';
+
+load('jstests/sharding/libs/sharded_transactions_helpers.js');
+
+let st = new ShardingTest({
+ mongos: 1,
+ shards: 2,
+ rs: {nodes: 1, setParameter: {logComponentVerbosity: tojson({command: {verbosity: 2}})}}
+});
+
+class APIParameterTest {
+ constructor(
+ command,
+ {dbName = "db", inAPIVersion1 = true, permittedInTxn = true, shardCommandName} = {}) {
+ this.command = command;
+ this.dbName = dbName;
+ this.inAPIVersion1 = inAPIVersion1;
+ this.permittedInTxn = permittedInTxn;
+ if (shardCommandName === undefined) {
+ this.commandName = Object.keys(command)[0];
+ } else {
+ // mongos executes a different command on the shards, e.g. mapReduce becomes aggregate.
+ this.commandName = shardCommandName;
+ }
+ }
+}
+
+const tests = [
+ // Write commands. Note, these rely on _id 1 residing on shard 0.
+ new APIParameterTest({insert: "collection", documents: [{_id: 1}]}),
+ new APIParameterTest({update: "collection", updates: [{q: {_id: 1}, u: {$set: {x: 1}}}]}),
+ new APIParameterTest({delete: "collection", deletes: [{q: {_id: 1}, limit: 1}]}),
+
+ // Read commands.
+ new APIParameterTest({aggregate: "collection", pipeline: [], cursor: {}}),
+ new APIParameterTest({aggregate: "collection", pipeline: [], cursor: {}, explain: true},
+ {shardCommandName: "explain", permittedInTxn: false}),
+ new APIParameterTest({find: "collection"}),
+ new APIParameterTest({count: "collection"}, {permittedInTxn: false}),
+ new APIParameterTest({count: "collection", query: {_id: {$lt: 0}}},
+ {inAPIVersion1: false, permittedInTxn: false}),
+ new APIParameterTest({distinct: "collection", key: "_id"},
+ {inAPIVersion1: false, permittedInTxn: false}),
+ new APIParameterTest(
+ {
+ mapReduce: "collection",
+ map: function() {
+ emit(1, 1);
+ },
+ reduce: function(key, values) {
+ return {count: values.length};
+ },
+ out: {inline: 1}
+ },
+ {inAPIVersion1: false, permittedInTxn: false, shardCommandName: "aggregate"}),
+
+ // FindAndModify.
+ new APIParameterTest({findAndModify: "collection", query: {_id: 1}, remove: true}),
+
+ // DDL. Order matters: we must create, modify, then drop an index on collection2.
+ new APIParameterTest({createIndexes: "collection2", indexes: [{key: {x: 1}, name: "x_1"}]}),
+ new APIParameterTest({collMod: "collection2", index: {keyPattern: {x: 1}, hidden: true}},
+ {permittedInTxn: false}),
+ new APIParameterTest({dropIndexes: "collection2", index: "x_1"}, {permittedInTxn: false}),
+ // We can create indexes on a non-existent collection in a sharded transaction.
+ new APIParameterTest({create: "newCollection"}),
+ new APIParameterTest({renameCollection: "db.newCollection", to: "db.newerCollection"},
+ {inAPIVersion1: false, permittedInTxn: false, dbName: "admin"}),
+ new APIParameterTest({drop: "collection"}, {permittedInTxn: false}),
+ new APIParameterTest({dropDatabase: 1}, {permittedInTxn: false}),
+];
+
+function checkPrimaryLog(conn, commandName, apiVersion, apiStrict, apiDeprecationErrors, message) {
+ const logs = checkLog.getGlobalLog(conn);
+ let lastCommandInvocation;
+
+ for (let logMsg of logs) {
+ const obj = JSON.parse(logMsg);
+ // Search for "About to run the command" logs.
+ if (obj.id !== 21965) {
+ continue;
+ }
+
+ const args = obj.attr.commandArgs;
+ if (commandName !== Object.keys(args)[0]) {
+ continue;
+ }
+
+ lastCommandInvocation = args;
+ if (args.apiVersion !== apiVersion || args.apiStrict !== apiStrict ||
+ args.apiDeprecationErrors !== apiDeprecationErrors) {
+ continue;
+ }
+
+ // Found a match.
+ return;
+ }
+
+ if (lastCommandInvocation === undefined) {
+ doassert(`Primary didn't log ${commandName}`);
+ return;
+ }
+
+ doassert(`Primary didn't log ${message}, last invocation of ${commandName} was` +
+ ` ${tojson(lastCommandInvocation)}`);
+}
+
+for (const sharded of [false, true]) {
+ for (const [apiVersion, apiStrict, apiDeprecationErrors] of [[undefined, undefined, undefined],
+ ["1", undefined, undefined],
+ ["1", undefined, false],
+ ["1", undefined, true],
+ ["1", false, undefined],
+ ["1", false, false],
+ ["1", false, true],
+ ["1", true, undefined],
+ ["1", true, false],
+ ["1", true, true],
+ ]) {
+ for (let inTransaction of [false, true]) {
+ if (sharded) {
+ jsTestLog("Sharded setup");
+ assert.commandWorked(st.s.getDB("db")["collection"].insert(
+ {_id: 0}, {writeConcern: {w: "majority"}}));
+ assert.commandWorked(st.s.getDB("db")["collection"].insert(
+ {_id: 20}, {writeConcern: {w: "majority"}}));
+
+ assert.commandWorked(st.s.adminCommand({enableSharding: "db"}));
+ st.ensurePrimaryShard("db", st.shard0.shardName);
+ assert.commandWorked(
+ st.s.adminCommand({shardCollection: "db.collection", key: {_id: 1}}));
+
+ // The chunk with _id 1 is on shard 0.
+ assert.commandWorked(
+ st.s.adminCommand({split: "db.collection", middle: {_id: 10}}));
+ assert.commandWorked(st.s.adminCommand(
+ {moveChunk: "db.collection", find: {_id: 20}, to: st.shard1.shardName}));
+ } else {
+ jsTestLog("Unsharded setup");
+ assert.commandWorked(st.s.getDB("db")["collection"].insert(
+ {_id: 0}, {writeConcern: {w: "majority"}}));
+ st.ensurePrimaryShard("db", st.shard0.shardName);
+ }
+
+ // Shard 0's primary.
+ const primary = st.rs0.getPrimary();
+
+ for (const test of tests) {
+ if (inTransaction && !test.permittedInTxn) {
+ continue;
+ }
+
+ if (apiStrict && !test.inAPIVersion1) {
+ continue;
+ }
+
+ // Make a copy of the test's command body, and set its API parameters.
+ const commandWithAPIParams = Object.assign({}, test.command);
+ if (apiVersion !== undefined) {
+ commandWithAPIParams.apiVersion = apiVersion;
+ }
+
+ if (apiStrict !== undefined) {
+ commandWithAPIParams.apiStrict = apiStrict;
+ }
+
+ if (apiDeprecationErrors !== undefined) {
+ commandWithAPIParams.apiDeprecationErrors = apiDeprecationErrors;
+ }
+
+ assert.commandWorked(primary.adminCommand({clearLog: "global"}));
+ const message = `command ${tojson(commandWithAPIParams)}` +
+ ` ${sharded ? "sharded" : "unsharded"},` +
+ ` ${inTransaction ? "in" : "outside"} transaction`;
+
+ flushRoutersAndRefreshShardMetadata(st, {ns: "db.collection"});
+
+ jsTestLog(`Running ${message}`);
+
+ if (inTransaction) {
+ const session = st.s0.startSession();
+ const sessionDb = session.getDatabase(test.dbName);
+ session.startTransaction();
+ assert.commandWorked(sessionDb.runCommand(commandWithAPIParams));
+ assert.commandWorked(session.commitTransaction_forTesting());
+ } else {
+ const db = st.s0.getDB(test.dbName);
+ assert.commandWorked(db.runCommand(commandWithAPIParams));
+ }
+
+ checkPrimaryLog(primary,
+ test.commandName,
+ apiVersion,
+ apiStrict,
+ apiDeprecationErrors,
+ message);
+ }
+
+ jsTestLog("JS test cleanup: Drop database 'db'");
+ st.s0.getDB("db").runCommand({dropDatabase: 1});
+ }
+ }
+}
+
+st.stop();
+})();
diff --git a/src/mongo/db/SConscript b/src/mongo/db/SConscript
index bc8de0aa6c9..e813b2067c5 100644
--- a/src/mongo/db/SConscript
+++ b/src/mongo/db/SConscript
@@ -1524,7 +1524,6 @@ env.Library(
'$BUILD_DIR/mongo/db/auth/auth',
'$BUILD_DIR/mongo/db/auth/authprivilege',
'$BUILD_DIR/mongo/idl/idl_parser',
- 'api_parameters',
],
)
diff --git a/src/mongo/db/api_parameters.cpp b/src/mongo/db/api_parameters.cpp
index 51e424637db..05ffe9c49cb 100644
--- a/src/mongo/db/api_parameters.cpp
+++ b/src/mongo/db/api_parameters.cpp
@@ -76,18 +76,4 @@ void APIParameters::appendInfo(BSONObjBuilder* builder) const {
}
}
-std::size_t APIParameters::Hash::operator()(const APIParameters& params) const {
- size_t seed = 0;
- if (params.getAPIVersion()) {
- boost::hash_combine(seed, *params.getAPIVersion());
- }
- if (params.getAPIStrict()) {
- boost::hash_combine(seed, *params.getAPIStrict());
- }
- if (params.getAPIDeprecationErrors()) {
- boost::hash_combine(seed, *params.getAPIDeprecationErrors());
- }
- return seed;
-}
-
} // namespace mongo
diff --git a/src/mongo/db/api_parameters.h b/src/mongo/db/api_parameters.h
index 34c129bca15..efbebfabfcc 100644
--- a/src/mongo/db/api_parameters.h
+++ b/src/mongo/db/api_parameters.h
@@ -49,11 +49,6 @@ public:
static APIParameters fromClient(const APIParametersFromClient& apiParamsFromClient);
static APIParameters fromBSON(const BSONObj& cmdObj);
- // For use with unordered_map.
- struct Hash {
- std::size_t operator()(const APIParameters& params) const;
- };
-
void appendInfo(BSONObjBuilder* builder) const;
const boost::optional<std::string>& getAPIVersion() const {
@@ -90,14 +85,6 @@ private:
boost::optional<bool> _apiDeprecationErrors;
};
-inline bool operator==(const APIParameters& lhs, const APIParameters& rhs) {
- return lhs.getAPIVersion() == rhs.getAPIVersion() && lhs.getAPIStrict() == rhs.getAPIStrict() &&
- lhs.getAPIDeprecationErrors() == rhs.getAPIDeprecationErrors();
-}
-
-inline bool operator!=(const APIParameters& lhs, const APIParameters& rhs) {
- return !(lhs == rhs);
-}
/**
* Temporarily remove the user's API parameters from an OperationContext.
diff --git a/src/mongo/db/commands/kill_all_sessions_by_pattern_command.cpp b/src/mongo/db/commands/kill_all_sessions_by_pattern_command.cpp
index 220c585ae78..c7687db6782 100644
--- a/src/mongo/db/commands/kill_all_sessions_by_pattern_command.cpp
+++ b/src/mongo/db/commands/kill_all_sessions_by_pattern_command.cpp
@@ -96,10 +96,7 @@ public:
// The empty command kills all
if (ksc.getKillAllSessionsByPattern().empty()) {
- auto item = makeKillAllSessionsByPattern(opCtx);
- std::vector<mongo::KillAllSessionsByPattern> patterns;
- patterns.push_back({std::move(item.pattern)});
- ksc.setKillAllSessionsByPattern(std::move(patterns));
+ ksc.setKillAllSessionsByPattern({makeKillAllSessionsByPattern(opCtx)});
} else {
// If a pattern is passed, you may only pass impersonate data if you have the
// impersonate privilege.
@@ -117,10 +114,8 @@ public:
}
}
- KillAllSessionsByPatternSet patterns;
- for (auto& pattern : ksc.getKillAllSessionsByPattern()) {
- patterns.insert({std::move(pattern), APIParameters::get(opCtx)});
- }
+ KillAllSessionsByPatternSet patterns{ksc.getKillAllSessionsByPattern().begin(),
+ ksc.getKillAllSessionsByPattern().end()};
uassertStatusOK(killSessionsCmdHelper(opCtx, result, patterns));
return true;
diff --git a/src/mongo/db/commands/kill_sessions_command.cpp b/src/mongo/db/commands/kill_sessions_command.cpp
index 1bb9c2e3a08..41e3596938f 100644
--- a/src/mongo/db/commands/kill_sessions_command.cpp
+++ b/src/mongo/db/commands/kill_sessions_command.cpp
@@ -63,9 +63,9 @@ KillAllSessionsByPatternSet patternsForLoggedInUser(OperationContext* opCtx) {
User* user = authzSession->lookupUser(*iter);
invariant(user);
- auto item = makeKillAllSessionsByPattern(opCtx);
- item.pattern.setUid(user->getDigest());
- patterns.emplace(std::move(item));
+ auto pattern = makeKillAllSessionsByPattern(opCtx);
+ pattern.setUid(user->getDigest());
+ patterns.emplace(std::move(pattern));
}
} else {
patterns.emplace(makeKillAllSessionsByPattern(opCtx));
diff --git a/src/mongo/db/kill_sessions.cpp b/src/mongo/db/kill_sessions.cpp
index b167e14c156..41033d23bbb 100644
--- a/src/mongo/db/kill_sessions.cpp
+++ b/src/mongo/db/kill_sessions.cpp
@@ -31,7 +31,6 @@
#include "mongo/db/kill_sessions.h"
-#include "mongo/db/api_parameters.h"
#include "mongo/db/auth/authorization_session.h"
#include "mongo/db/client.h"
#include "mongo/db/operation_context.h"
@@ -97,25 +96,27 @@ std::tuple<std::vector<UserName>, std::vector<RoleName>> getKillAllSessionsByPat
return out;
}
-KillAllSessionsByPatternItem makeKillAllSessionsByPattern(OperationContext* opCtx) {
+KillAllSessionsByPattern makeKillAllSessionsByPattern(OperationContext* opCtx) {
KillAllSessionsByPattern kasbp;
kasbp.setUsers(getKillAllSessionsImpersonateUsers(opCtx));
kasbp.setRoles(getKillAllSessionsImpersonateRoles(opCtx));
- return {kasbp, APIParameters::get(opCtx)};
+
+ return kasbp;
}
-KillAllSessionsByPatternItem makeKillAllSessionsByPattern(OperationContext* opCtx,
- const KillAllSessionsUser& kasu) {
- KillAllSessionsByPatternItem item = makeKillAllSessionsByPattern(opCtx);
+KillAllSessionsByPattern makeKillAllSessionsByPattern(OperationContext* opCtx,
+ const KillAllSessionsUser& kasu) {
+ KillAllSessionsByPattern kasbp = makeKillAllSessionsByPattern(opCtx);
auto authMgr = AuthorizationManager::get(opCtx->getServiceContext());
UserName un(kasu.getUser(), kasu.getDb());
auto user = uassertStatusOK(authMgr->acquireUser(opCtx, un));
- item.pattern.setUid(user->getDigest());
- return item;
+ kasbp.setUid(user->getDigest());
+
+ return kasbp;
}
KillAllSessionsByPatternSet makeSessionFilterForAuthenticatedUsers(OperationContext* opCtx) {
@@ -126,18 +127,18 @@ KillAllSessionsByPatternSet makeSessionFilterForAuthenticatedUsers(OperationCont
if (auto user = authSession->lookupUser(*it)) {
KillAllSessionsByPattern pattern;
pattern.setUid(user->getDigest());
- KillAllSessionsByPatternItem item{std::move(pattern), APIParameters::get(opCtx)};
- patterns.emplace(std::move(item));
+ patterns.emplace(std::move(pattern));
}
}
return patterns;
}
-KillAllSessionsByPatternItem makeKillAllSessionsByPattern(OperationContext* opCtx,
- const LogicalSessionId& lsid) {
- auto item = makeKillAllSessionsByPattern(opCtx);
- item.pattern.setLsid(lsid);
- return item;
+KillAllSessionsByPattern makeKillAllSessionsByPattern(OperationContext* opCtx,
+ const LogicalSessionId& lsid) {
+ KillAllSessionsByPattern kasbp = makeKillAllSessionsByPattern(opCtx);
+ kasbp.setLsid(lsid);
+
+ return kasbp;
}
} // namespace mongo
diff --git a/src/mongo/db/kill_sessions.h b/src/mongo/db/kill_sessions.h
index 31ceeed9375..29909fd49df 100644
--- a/src/mongo/db/kill_sessions.h
+++ b/src/mongo/db/kill_sessions.h
@@ -31,7 +31,6 @@
#include <tuple>
-#include "mongo/db/api_parameters.h"
#include "mongo/db/auth/role_name.h"
#include "mongo/db/auth/user_name.h"
#include "mongo/db/kill_sessions_gen.h"
@@ -42,14 +41,8 @@ namespace mongo {
class OperationContext;
class ServiceContext;
-struct KillAllSessionsByPatternItem {
- KillAllSessionsByPattern pattern;
- APIParameters apiParameters;
-};
-
-struct KillAllSessionsByPatternItemHash {
- std::size_t operator()(const KillAllSessionsByPatternItem& item) const {
- auto& pattern = item.pattern;
+struct KillAllSessionsByPatternHash {
+ std::size_t operator()(const KillAllSessionsByPattern& pattern) const {
if (pattern.getLsid()) {
return lsidHasher(*pattern.getLsid());
} else if (pattern.getUid()) {
@@ -67,22 +60,20 @@ struct KillAllSessionsByPatternItemHash {
/**
* Patterns are specifically equal if they differ only by impersonate data.
*/
-inline bool operator==(const KillAllSessionsByPatternItem& lhs,
- const KillAllSessionsByPatternItem& rhs) {
- auto makeEqualityLens = [](const auto& item) {
- return std::tie(item.pattern.getLsid(), item.pattern.getUid(), item.apiParameters);
+inline bool operator==(const KillAllSessionsByPattern& lhs, const KillAllSessionsByPattern& rhs) {
+ auto makeEqualityLens = [](const auto& pattern) {
+ return std::tie(pattern.getLsid(), pattern.getUid());
};
return makeEqualityLens(lhs) == makeEqualityLens(rhs);
}
-inline bool operator!=(const KillAllSessionsByPatternItem& lhs,
- const KillAllSessionsByPatternItem& rhs) {
+inline bool operator!=(const KillAllSessionsByPattern& lhs, const KillAllSessionsByPattern& rhs) {
return !(lhs == rhs);
}
using KillAllSessionsByPatternSet =
- stdx::unordered_set<KillAllSessionsByPatternItem, KillAllSessionsByPatternItemHash>;
+ stdx::unordered_set<KillAllSessionsByPattern, KillAllSessionsByPatternHash>;
std::tuple<std::vector<UserName>, std::vector<RoleName>> getKillAllSessionsByPatternImpersonateData(
const KillAllSessionsByPattern& pattern);
@@ -95,13 +86,13 @@ std::tuple<std::vector<UserName>, std::vector<RoleName>> getKillAllSessionsByPat
/**
* Constructs a kill sessions pattern which kills all sessions
*/
-KillAllSessionsByPatternItem makeKillAllSessionsByPattern(OperationContext* opCtx);
+KillAllSessionsByPattern makeKillAllSessionsByPattern(OperationContext* opCtx);
/**
* Constructs a kill sessions pattern for a particular user
*/
-KillAllSessionsByPatternItem makeKillAllSessionsByPattern(OperationContext* opCtx,
- const KillAllSessionsUser& user);
+KillAllSessionsByPattern makeKillAllSessionsByPattern(OperationContext* opCtx,
+ const KillAllSessionsUser& user);
/**
* Constructs a KillAllSessionsByPatternSet, each element of which matches the UID of a user that is
@@ -112,7 +103,7 @@ KillAllSessionsByPatternSet makeSessionFilterForAuthenticatedUsers(OperationCont
/**
* Constructs a kill sessions pattern for a particular logical session
*/
-KillAllSessionsByPatternItem makeKillAllSessionsByPattern(OperationContext* opCtx,
- const LogicalSessionId& lsid);
+KillAllSessionsByPattern makeKillAllSessionsByPattern(OperationContext* opCtx,
+ const LogicalSessionId& lsid);
} // namespace mongo
diff --git a/src/mongo/db/s/config/sharding_catalog_manager_shard_operations.cpp b/src/mongo/db/s/config/sharding_catalog_manager_shard_operations.cpp
index b82c0b908e5..d10ba0288d3 100644
--- a/src/mongo/db/s/config/sharding_catalog_manager_shard_operations.cpp
+++ b/src/mongo/db/s/config/sharding_catalog_manager_shard_operations.cpp
@@ -43,7 +43,6 @@
#include "mongo/client/read_preference.h"
#include "mongo/client/remote_command_targeter.h"
#include "mongo/client/replica_set_monitor.h"
-#include "mongo/db/api_parameters.h"
#include "mongo/db/audit.h"
#include "mongo/db/catalog_raii.h"
#include "mongo/db/client.h"
@@ -146,7 +145,7 @@ StatusWith<Shard::CommandResponse> ShardingCatalogManager::_runCommandForAddShar
auto host = std::move(swHost.getValue());
executor::RemoteCommandRequest request(
- host, dbName.toString(), cmdObj, rpc::makeEmptyMetadata(), opCtx, Seconds(30));
+ host, dbName.toString(), cmdObj, rpc::makeEmptyMetadata(), nullptr, Seconds(30));
executor::RemoteCommandResponse response =
Status(ErrorCodes::InternalError, "Internal error running command");
diff --git a/src/mongo/db/session_killer.cpp b/src/mongo/db/session_killer.cpp
index 8ac4764398a..20ba36ac3dd 100644
--- a/src/mongo/db/session_killer.cpp
+++ b/src/mongo/db/session_killer.cpp
@@ -85,19 +85,18 @@ SessionKiller::ReapResult::ReapResult() : result(std::make_shared<boost::optiona
SessionKiller::Matcher::Matcher(KillAllSessionsByPatternSet&& patterns)
: _patterns(std::move(patterns)) {
- for (const auto& item : _patterns) {
- auto& pattern = item.pattern;
+ for (const auto& pattern : _patterns) {
if (pattern.getUid()) {
_uids.emplace(pattern.getUid().get(), &pattern);
} else if (pattern.getLsid()) {
_lsids.emplace(pattern.getLsid().get(), &pattern);
} else {
// If we're killing everything, it's the only pattern we care about.
- decltype(_patterns) onlyKillAll{{item}};
+ decltype(_patterns) onlyKillAll{{pattern}};
using std::swap;
swap(_patterns, onlyKillAll);
- _killAll = &(_patterns.begin()->pattern);
+ _killAll = &(*_patterns.begin());
break;
}
}
@@ -178,38 +177,19 @@ void SessionKiller::_periodicKill(OperationContext* opCtx, stdx::unique_lock<Lat
// Drop the lock and run the killer.
lk.unlock();
- // Group patterns with equal API parameters into sets.
- stdx::unordered_map<APIParameters, KillAllSessionsByPatternSet, APIParameters::Hash> sets;
- for (auto& item : nextToReap) {
- sets[item.apiParameters].insert(std::move(item));
+ Matcher matcher(std::move(nextToReap));
+ boost::optional<Result> results;
+ try {
+ results.emplace(_killFunc(opCtx, matcher, &_urbg));
+ } catch (...) {
+ results.emplace(exceptionToStatus());
}
+ lk.lock();
- // Use the API parameters included in each KillAllSessionsByPattern struct.
- IgnoreAPIParametersBlock ignoreApiParametersBlock(opCtx);
- Result finalResults{std::vector<HostAndPort>{}};
- for (auto& [apiParameters, items] : sets) {
- APIParameters::get(opCtx) = apiParameters;
- Matcher matcher(std::move(items));
- boost::optional<Result> results;
- try {
- results.emplace(_killFunc(opCtx, matcher, &_urbg));
- } catch (...) {
- results.emplace(exceptionToStatus());
- }
- invariant(results);
- if (!results->isOK()) {
- finalResults = *results;
- break;
- }
-
- finalResults.getValue().insert(finalResults.getValue().end(),
- std::make_move_iterator(results->getValue().begin()),
- std::make_move_iterator(results->getValue().end()));
- }
+ invariant(results);
// Expose the results and notify callers
- lk.lock();
- *(reapResults.result) = std::move(finalResults);
+ *(reapResults.result) = std::move(results);
_callerCV.notify_all();
};
diff --git a/src/mongo/s/commands/cluster_kill_op.cpp b/src/mongo/s/commands/cluster_kill_op.cpp
index 2ce1ecf79ef..1d4927b0f79 100644
--- a/src/mongo/s/commands/cluster_kill_op.cpp
+++ b/src/mongo/s/commands/cluster_kill_op.cpp
@@ -38,7 +38,6 @@
#include "mongo/bson/bsonobjbuilder.h"
#include "mongo/bson/util/bson_extract.h"
#include "mongo/client/connpool.h"
-#include "mongo/db/api_parameters.h"
#include "mongo/db/audit.h"
#include "mongo/db/auth/authorization_session.h"
#include "mongo/db/commands.h"
@@ -112,10 +111,8 @@ private:
result.append("shardid", opId);
ScopedDbConnection conn(shard->getConnString());
- BSONObjBuilder bob(BSON("killOp" << 1 << "op" << opId));
- APIParameters::get(opCtx).appendInfo(&bob);
// intentionally ignore return value - that is how legacy killOp worked.
- conn->runCommand(OpMsgRequest::fromDBAndBody("admin", bob.obj()));
+ conn->runCommand(OpMsgRequest::fromDBAndBody("admin", BSON("killOp" << 1 << "op" << opId)));
conn.done();
// The original behavior of killOp on mongos is to always return success, regardless of
diff --git a/src/mongo/s/commands/kill_sessions_remote.cpp b/src/mongo/s/commands/kill_sessions_remote.cpp
index 0102de0d580..d9b5ce26ccf 100644
--- a/src/mongo/s/commands/kill_sessions_remote.cpp
+++ b/src/mongo/s/commands/kill_sessions_remote.cpp
@@ -119,11 +119,9 @@ SessionKiller::Result killSessionsRemote(OperationContext* opCtx,
// Generate the kill command.
KillAllSessionsByPatternCmd cmd;
- std::vector<KillAllSessionsByPattern> patterns{matcher.getPatterns().size()};
- for (auto& item : matcher.getPatterns()) {
- patterns.push_back(std::move(item.pattern));
- }
- cmd.setKillAllSessionsByPattern(std::move(patterns));
+ cmd.setKillAllSessionsByPattern(std::vector<KillAllSessionsByPattern>{
+ matcher.getPatterns().begin(), matcher.getPatterns().end()});
+
return parallelExec(opCtx, cmd.toBSON(), urbg);
}