summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPV99 <pridhvi.vegesna@mongodb.com>2020-07-15 23:13:33 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2020-07-28 23:56:02 +0000
commit4e0f81726fc11becd9c22d701e80ba2c8d988bb0 (patch)
tree620edb4e906caa933c4f6cd1d04bce42b290be98
parent165dfb50f7693cadb80e988d08222700b1cc6b5c (diff)
downloadmongo-4e0f81726fc11becd9c22d701e80ba2c8d988bb0.tar.gz
SERVER-49065 Mark API Version 1 commands
-rw-r--r--jstests/core/version_api_field_parsing.js21
-rw-r--r--jstests/core/version_api_v1_command_coverage.js81
-rw-r--r--jstests/core/views/views_all_commands.js1
-rw-r--r--jstests/replsets/db_reads_while_recovering_all_commands.js1
-rw-r--r--jstests/sharding/database_versioning_all_commands.js1
-rw-r--r--jstests/sharding/libs/last_lts_mongos_commands.js3
-rw-r--r--jstests/sharding/read_write_concern_defaults_application.js1
-rw-r--r--jstests/sharding/safe_secondary_reads_drop_recreate.js1
-rw-r--r--jstests/sharding/safe_secondary_reads_single_migration_suspend_range_deletion.js1
-rw-r--r--jstests/sharding/safe_secondary_reads_single_migration_waitForDelete.js1
-rw-r--r--src/mongo/db/auth/sasl_commands.cpp7
-rw-r--r--src/mongo/db/command_generic_argument.cpp5
-rw-r--r--src/mongo/db/commands.h4
-rw-r--r--src/mongo/db/commands/SConscript2
-rw-r--r--src/mongo/db/commands/authentication_commands.cpp4
-rw-r--r--src/mongo/db/commands/count_cmd.cpp4
-rw-r--r--src/mongo/db/commands/create_indexes.cpp4
-rw-r--r--src/mongo/db/commands/dbcommands.cpp17
-rw-r--r--src/mongo/db/commands/drop_indexes.cpp5
-rw-r--r--src/mongo/db/commands/end_sessions_command.cpp4
-rw-r--r--src/mongo/db/commands/explain_cmd.cpp4
-rw-r--r--src/mongo/db/commands/find_and_modify.cpp4
-rw-r--r--src/mongo/db/commands/find_cmd.cpp4
-rw-r--r--src/mongo/db/commands/generic.cpp4
-rw-r--r--src/mongo/db/commands/getmore_cmd.cpp6
-rw-r--r--src/mongo/db/commands/killcursors_cmd.cpp4
-rw-r--r--src/mongo/db/commands/list_collections.cpp3
-rw-r--r--src/mongo/db/commands/list_databases.cpp4
-rw-r--r--src/mongo/db/commands/list_indexes.cpp4
-rw-r--r--src/mongo/db/commands/pipeline_command.cpp4
-rw-r--r--src/mongo/db/commands/refresh_sessions_command.cpp4
-rw-r--r--src/mongo/db/commands/test_deprecation_command.cpp85
-rw-r--r--src/mongo/db/commands/txn_cmds.cpp8
-rw-r--r--src/mongo/db/commands/write_commands/write_commands.cpp13
-rw-r--r--src/mongo/db/initialize_api_parameters.cpp21
-rw-r--r--src/mongo/db/initialize_api_parameters.h3
-rw-r--r--src/mongo/db/repl/replication_info.cpp4
-rw-r--r--src/mongo/db/s/config/configsvr_drop_collection_command.cpp4
-rw-r--r--src/mongo/db/s/config/configsvr_drop_database_command.cpp4
-rw-r--r--src/mongo/db/service_entry_point_common.cpp2
-rw-r--r--src/mongo/embedded/mongo_embedded/mongo_embedded_test.cpp1
-rw-r--r--src/mongo/s/commands/cluster_abort_transaction_cmd.cpp4
-rw-r--r--src/mongo/s/commands/cluster_collection_mod_cmd.cpp4
-rw-r--r--src/mongo/s/commands/cluster_commit_transaction_cmd.cpp4
-rw-r--r--src/mongo/s/commands/cluster_count_cmd.cpp4
-rw-r--r--src/mongo/s/commands/cluster_create_cmd.cpp4
-rw-r--r--src/mongo/s/commands/cluster_create_indexes_cmd.cpp4
-rw-r--r--src/mongo/s/commands/cluster_drop_cmd.cpp4
-rw-r--r--src/mongo/s/commands/cluster_drop_database_cmd.cpp4
-rw-r--r--src/mongo/s/commands/cluster_drop_indexes_cmd.cpp4
-rw-r--r--src/mongo/s/commands/cluster_explain_cmd.cpp4
-rw-r--r--src/mongo/s/commands/cluster_find_and_modify_cmd.cpp4
-rw-r--r--src/mongo/s/commands/cluster_find_cmd.cpp4
-rw-r--r--src/mongo/s/commands/cluster_getmore_cmd.cpp6
-rw-r--r--src/mongo/s/commands/cluster_is_master_cmd.cpp4
-rw-r--r--src/mongo/s/commands/cluster_killcursors_cmd.cpp4
-rw-r--r--src/mongo/s/commands/cluster_list_collections_cmd.cpp4
-rw-r--r--src/mongo/s/commands/cluster_list_databases_cmd.cpp4
-rw-r--r--src/mongo/s/commands/cluster_list_indexes_cmd.cpp4
-rw-r--r--src/mongo/s/commands/cluster_pipeline_cmd.cpp4
-rw-r--r--src/mongo/s/commands/cluster_write_cmd.cpp12
-rw-r--r--src/mongo/s/commands/strategy.cpp2
62 files changed, 442 insertions, 8 deletions
diff --git a/jstests/core/version_api_field_parsing.js b/jstests/core/version_api_field_parsing.js
index 524c4749338..69505698559 100644
--- a/jstests/core/version_api_field_parsing.js
+++ b/jstests/core/version_api_field_parsing.js
@@ -7,6 +7,7 @@
(function() {
"use strict";
+// Test parsing logic on command included in API V1.
// If the client passed apiStrict, they must also pass apiVersion.
assert.commandFailedWithCode(db.runCommand({ping: 1, apiStrict: true}),
4886600,
@@ -44,4 +45,24 @@ assert.commandWorked(
assert.commandWorked(
db.runCommand({ping: 1, apiVersion: "1", apiStrict: false, apiDeprecationErrors: false}));
assert.commandWorked(db.runCommand({ping: 1, apiVersion: "1"}));
+
+// Test parsing logic on command not included in API V1.
+assert.commandWorked(db.runCommand({listCommands: 1, apiVersion: "1"}));
+// If the client passed apiStrict: true, but the command is not in V1, reply with
+// APIStrictError.
+assert.commandFailedWithCode(
+ db.runCommand({listCommands: 1, apiVersion: "1", apiStrict: true}),
+ ErrorCodes.APIStrictError,
+ "Provided apiStrict: true, but the invoked command's apiVersions() does not include \"1\"");
+assert.commandWorked(db.runCommand({listCommands: 1, apiVersion: "1", apiDeprecationErrors: true}));
+
+// Test parsing logic of command deprecated in API V1.
+assert.commandWorked(db.runCommand({testDeprecation: 1, apiVersion: "1"}));
+assert.commandWorked(db.runCommand({testDeprecation: 1, apiVersion: "1", apiStrict: true}));
+// If the client passed apiDeprecationErrors: true, but the command is
+// deprecated in API Version 1, reply with APIDeprecationError.
+assert.commandFailedWithCode(
+ db.runCommand({testDeprecation: 1, apiVersion: "1", apiDeprecationErrors: true}),
+ ErrorCodes.APIDeprecationError,
+ "Provided apiDeprecationErrors: true, but the invoked command's deprecatedApiVersions() does not include \"1\"");
})(); \ No newline at end of file
diff --git a/jstests/core/version_api_v1_command_coverage.js b/jstests/core/version_api_v1_command_coverage.js
new file mode 100644
index 00000000000..7364990f48e
--- /dev/null
+++ b/jstests/core/version_api_v1_command_coverage.js
@@ -0,0 +1,81 @@
+/**
+ * Checks that commands included/omitted in API V1 behave correctly with various combinations of API
+ * parameters.
+ *
+ * @tags: [requires_fcv_46, requires_non_retryable_commands]
+ */
+
+(function() {
+"use strict";
+
+let counter = 0;
+const counter_fun = function() {
+ return `APIV1-${counter}`;
+};
+
+const testDB = db.getSiblingDB(jsTestName());
+const testColl = testDB.getCollection("test");
+
+function runTest({cmd, apiVersion1, apiStrict, apiDeprecationErrors}) {
+ // Instantiate "cmd" so we can modify it.
+ let copy = cmd();
+ jsTestLog(
+ `Test ${tojson(copy)}, which is ${apiVersion1 ? "in" : "not in"} API V1, with apiStrict = ${
+ apiStrict} and apiDeprecationErrors = ${apiDeprecationErrors}`);
+ copy.apiVersion = "1";
+ copy.apiStrict = apiStrict;
+ copy.apiDeprecationErrors = apiDeprecationErrors;
+ if (!apiVersion1 && apiStrict) {
+ assert.commandFailedWithCode(
+ testDB.runCommand(copy),
+ ErrorCodes.APIStrictError,
+ "Provided apiStrict: true, but the invoked command's apiVersions() does not include \"1\"");
+ } else {
+ assert.commandWorked(testDB.runCommand(copy));
+ }
+}
+
+const commands = [
+ {cmd: () => ({buildInfo: 1}), apiVersion1: false},
+ {cmd: () => ({createUser: counter_fun(), pwd: "pwd", roles: []}), apiVersion1: false},
+ {cmd: () => ({dropUser: counter_fun()}), apiVersion1: false},
+ {cmd: () => ({getLastError: 1}), apiVersion1: false},
+ {cmd: () => ({serverStatus: 1}), apiVersion1: false},
+ {cmd: () => ({usersInfo: 1}), apiVersion1: false},
+ {cmd: () => ({aggregate: testColl.getName(), pipeline: [], cursor: {}}), apiVersion1: true},
+ {cmd: () => ({count: "system.js"}), apiVersion1: true},
+ {cmd: () => ({create: counter_fun()}), apiVersion1: true},
+ {cmd: () => ({find: counter_fun()}), apiVersion1: true},
+ {
+ cmd: () => ({insert: "APIV1-0", documents: [{_id: counter_fun(), cast: "jonSnow"}]}),
+ apiVersion1: true
+ },
+ {
+ cmd: () => ({
+ update: "APIV1-0",
+ updates: [{q: {_id: counter_fun()}, u: {$set: {cast: "aryaStark"}}}]
+ }),
+ apiVersion1: true,
+ },
+ {
+ cmd: () => ({delete: "APIV1-0", deletes: [{q: {_id: counter_fun()}, limit: 1}]}),
+ apiVersion1: true
+ },
+ {cmd: () => ({drop: counter_fun()}), apiVersion1: true}
+];
+
+for (let {cmd, apiVersion1} of commands) {
+ counter = 0;
+ for (let apiStrict of [false, true]) {
+ for (let apiDeprecationErrors of [false, true]) {
+ runTest({
+ cmd: cmd,
+ apiVersion1: apiVersion1,
+ apiStrict: apiStrict,
+ apiDeprecationErrors: apiDeprecationErrors
+ });
+ counter += 1;
+ }
+ }
+}
+})(); \ No newline at end of file
diff --git a/jstests/core/views/views_all_commands.js b/jstests/core/views/views_all_commands.js
index 672cdd38f97..1f87251c9fb 100644
--- a/jstests/core/views/views_all_commands.js
+++ b/jstests/core/views/views_all_commands.js
@@ -546,6 +546,7 @@ let viewsCommandTests = {
startRecordingTraffic: {skip: isUnrelated},
startSession: {skip: isAnInternalCommand},
stopRecordingTraffic: {skip: isUnrelated},
+ testDeprecation: {skip: isAnInternalCommand},
top: {skip: "tested in views/views_stats.js"},
touch: {skip: wasRemovedInBinaryVersion44},
unsetSharding: {skip: isAnInternalCommand},
diff --git a/jstests/replsets/db_reads_while_recovering_all_commands.js b/jstests/replsets/db_reads_while_recovering_all_commands.js
index 1d7c13742df..467b06c1363 100644
--- a/jstests/replsets/db_reads_while_recovering_all_commands.js
+++ b/jstests/replsets/db_reads_while_recovering_all_commands.js
@@ -290,6 +290,7 @@ const allCommands = {
startRecordingTraffic: {skip: isNotAUserDataRead},
startSession: {skip: isNotAUserDataRead},
stopRecordingTraffic: {skip: isNotAUserDataRead},
+ testDeprecation: {skip: isNotAUserDataRead},
top: {skip: isNotAUserDataRead},
unsetSharding: {skip: isNotAUserDataRead},
update: {skip: isPrimaryOnly},
diff --git a/jstests/sharding/database_versioning_all_commands.js b/jstests/sharding/database_versioning_all_commands.js
index f0db7782f84..f5bac9df015 100644
--- a/jstests/sharding/database_versioning_all_commands.js
+++ b/jstests/sharding/database_versioning_all_commands.js
@@ -626,6 +626,7 @@ let testCases = {
startRecordingTraffic: {skip: "executes locally on mongos (not sent to any remote node)"},
startSession: {skip: "executes locally on mongos (not sent to any remote node)"},
stopRecordingTraffic: {skip: "executes locally on mongos (not sent to any remote node)"},
+ testDeprecation: {skip: "executes locally on mongos (not sent to any remote node)"},
update: {
run: {
sendsDbVersion: true,
diff --git a/jstests/sharding/libs/last_lts_mongos_commands.js b/jstests/sharding/libs/last_lts_mongos_commands.js
index 0eda44d4ad7..d8e2c6cc4ff 100644
--- a/jstests/sharding/libs/last_lts_mongos_commands.js
+++ b/jstests/sharding/libs/last_lts_mongos_commands.js
@@ -7,4 +7,5 @@ const commandsRemovedFromMongosSinceLastLTS = [];
// These commands were added in mongos since the last LTS version, so will not appear in the
// listCommands output of a last LTS version mongos. We will allow these commands to have a test
// defined without always existing on the mongos being used.
-const commandsAddedToMongosSinceLastLTS = ["reshardCollection", "rotateCertificates"];
+const commandsAddedToMongosSinceLastLTS =
+ ["reshardCollection", "rotateCertificates", "testDeprecation"];
diff --git a/jstests/sharding/read_write_concern_defaults_application.js b/jstests/sharding/read_write_concern_defaults_application.js
index d95cdd6eec7..40b76f35a48 100644
--- a/jstests/sharding/read_write_concern_defaults_application.js
+++ b/jstests/sharding/read_write_concern_defaults_application.js
@@ -615,6 +615,7 @@ let testCases = {
startRecordingTraffic: {skip: "does not accept read or write concern"},
startSession: {skip: "does not accept read or write concern"},
stopRecordingTraffic: {skip: "does not accept read or write concern"},
+ testDeprecation: {skip: "does not accept read or write concern"},
top: {skip: "does not accept read or write concern"},
unsetSharding: {skip: "internal command"},
update: {
diff --git a/jstests/sharding/safe_secondary_reads_drop_recreate.js b/jstests/sharding/safe_secondary_reads_drop_recreate.js
index e783c2098ec..6a03af25df7 100644
--- a/jstests/sharding/safe_secondary_reads_drop_recreate.js
+++ b/jstests/sharding/safe_secondary_reads_drop_recreate.js
@@ -297,6 +297,7 @@ let testCases = {
startRecordingTraffic: {skip: "does not return user data"},
startSession: {skip: "does not return user data"},
stopRecordingTraffic: {skip: "does not return user data"},
+ testDeprecation: {skip: "does not return user data"},
top: {skip: "does not return user data"},
unsetSharding: {skip: "does not return user data"},
update: {skip: "primary only"},
diff --git a/jstests/sharding/safe_secondary_reads_single_migration_suspend_range_deletion.js b/jstests/sharding/safe_secondary_reads_single_migration_suspend_range_deletion.js
index 5792fcec8b8..260de634468 100644
--- a/jstests/sharding/safe_secondary_reads_single_migration_suspend_range_deletion.js
+++ b/jstests/sharding/safe_secondary_reads_single_migration_suspend_range_deletion.js
@@ -369,6 +369,7 @@ let testCases = {
startRecordingTraffic: {skip: "does not return user data"},
startSession: {skip: "does not return user data"},
stopRecordingTraffic: {skip: "does not return user data"},
+ testDeprecation: {skip: "does not return user data"},
top: {skip: "does not return user data"},
unsetSharding: {skip: "does not return user data"},
update: {skip: "primary only"},
diff --git a/jstests/sharding/safe_secondary_reads_single_migration_waitForDelete.js b/jstests/sharding/safe_secondary_reads_single_migration_waitForDelete.js
index 0dbd9b93ca9..c502137fc03 100644
--- a/jstests/sharding/safe_secondary_reads_single_migration_waitForDelete.js
+++ b/jstests/sharding/safe_secondary_reads_single_migration_waitForDelete.js
@@ -304,6 +304,7 @@ let testCases = {
startRecordingTraffic: {skip: "does not return user data"},
startSession: {skip: "does not return user data"},
stopRecordingTraffic: {skip: "does not return user data"},
+ testDeprecation: {skip: "does not return user data"},
top: {skip: "does not return user data"},
unsetSharding: {skip: "does not return user data"},
update: {skip: "primary only"},
diff --git a/src/mongo/db/auth/sasl_commands.cpp b/src/mongo/db/auth/sasl_commands.cpp
index 3e2b9e26f42..7f4b1010462 100644
--- a/src/mongo/db/auth/sasl_commands.cpp
+++ b/src/mongo/db/auth/sasl_commands.cpp
@@ -70,6 +70,10 @@ public:
CmdSaslStart();
virtual ~CmdSaslStart();
+ const std::set<std::string>& apiVersions() const {
+ return kApiVersions1;
+ }
+
virtual void addRequiredPrivileges(const std::string&,
const BSONObj&,
std::vector<Privilege>*) const {}
@@ -100,6 +104,9 @@ public:
CmdSaslContinue();
virtual ~CmdSaslContinue();
+ const std::set<std::string>& apiVersions() const {
+ return kApiVersions1;
+ }
virtual void addRequiredPrivileges(const std::string&,
const BSONObj&,
std::vector<Privilege>*) const {}
diff --git a/src/mongo/db/command_generic_argument.cpp b/src/mongo/db/command_generic_argument.cpp
index 37ff2323e9f..86e6f6c0196 100644
--- a/src/mongo/db/command_generic_argument.cpp
+++ b/src/mongo/db/command_generic_argument.cpp
@@ -52,10 +52,13 @@ struct SpecialArgRecord {
// If that changes, it should be added. When you add to this list, consider whether you
// should also change the filterCommandRequestForPassthrough() function.
// clang-format off
-static constexpr std::array<SpecialArgRecord, 31> specials{{
+static constexpr std::array<SpecialArgRecord, 34> specials{{
// /-isGeneric
// | /-stripFromRequest
// | | /-stripFromReply
+ {"apiVersion"_sd, 1, 0, 0},
+ {"apiStrict"_sd, 1, 0, 0},
+ {"apiDeprecationErrors"_sd, 1, 0, 0},
{"$audit"_sd, 1, 1, 0},
{"$client"_sd, 1, 1, 0},
{"$configServerState"_sd, 1, 1, 1},
diff --git a/src/mongo/db/commands.h b/src/mongo/db/commands.h
index c029cf9febe..6a07d0404be 100644
--- a/src/mongo/db/commands.h
+++ b/src/mongo/db/commands.h
@@ -358,12 +358,12 @@ public:
// List of API versions that include this command.
virtual const std::set<std::string>& apiVersions() const {
return kNoApiVersions;
- };
+ }
// API versions in which this command is deprecated.
virtual const std::set<std::string>& deprecatedApiVersions() const {
return kNoApiVersions;
- };
+ }
/**
* Like adminOnly, but even stricter: we must either be authenticated for admin db,
diff --git a/src/mongo/db/commands/SConscript b/src/mongo/db/commands/SConscript
index 910b0d7b88c..a4a1ebdc4ca 100644
--- a/src/mongo/db/commands/SConscript
+++ b/src/mongo/db/commands/SConscript
@@ -148,6 +148,7 @@ env.Library(
'logical_session_server_status_section.cpp',
'mr_common.cpp',
'reap_logical_session_cache_now.cpp',
+ 'test_deprecation_command.cpp',
'traffic_recording_cmds.cpp',
'user_management_commands_common.cpp',
env.Idlc('drop_connections.idl')[0],
@@ -171,6 +172,7 @@ env.Library(
'$BUILD_DIR/mongo/db/repl/isself',
'$BUILD_DIR/mongo/db/repl/repl_coordinator_interface',
'$BUILD_DIR/mongo/db/session_catalog',
+ '$BUILD_DIR/mongo/db/shared_request_handling',
'$BUILD_DIR/mongo/db/traffic_recorder',
'$BUILD_DIR/mongo/executor/egress_tag_closer_manager',
'$BUILD_DIR/mongo/executor/task_executor_pool',
diff --git a/src/mongo/db/commands/authentication_commands.cpp b/src/mongo/db/commands/authentication_commands.cpp
index f146e0c8742..77f014207fb 100644
--- a/src/mongo/db/commands/authentication_commands.cpp
+++ b/src/mongo/db/commands/authentication_commands.cpp
@@ -144,6 +144,10 @@ Status _authenticateX509(OperationContext* opCtx, const UserName& user, const BS
class CmdAuthenticate : public BasicCommand {
public:
+ const std::set<std::string>& apiVersions() const {
+ return kApiVersions1;
+ }
+
AllowedOnSecondary secondaryAllowed(ServiceContext*) const override {
return AllowedOnSecondary::kAlways;
}
diff --git a/src/mongo/db/commands/count_cmd.cpp b/src/mongo/db/commands/count_cmd.cpp
index 6165ef9cdb5..fe8c4af8198 100644
--- a/src/mongo/db/commands/count_cmd.cpp
+++ b/src/mongo/db/commands/count_cmd.cpp
@@ -63,6 +63,10 @@ class CmdCount : public BasicCommand {
public:
CmdCount() : BasicCommand("count") {}
+ const std::set<std::string>& apiVersions() const {
+ return kApiVersions1;
+ }
+
std::string help() const override {
return "count objects in collection";
}
diff --git a/src/mongo/db/commands/create_indexes.cpp b/src/mongo/db/commands/create_indexes.cpp
index 5794fb26436..0a9e6c50e56 100644
--- a/src/mongo/db/commands/create_indexes.cpp
+++ b/src/mongo/db/commands/create_indexes.cpp
@@ -711,6 +711,10 @@ class CmdCreateIndex : public ErrmsgCommandDeprecated {
public:
CmdCreateIndex() : ErrmsgCommandDeprecated(kCommandName) {}
+ const std::set<std::string>& apiVersions() const {
+ return kApiVersions1;
+ }
+
bool supportsWriteConcern(const BSONObj& cmd) const override {
return true;
}
diff --git a/src/mongo/db/commands/dbcommands.cpp b/src/mongo/db/commands/dbcommands.cpp
index 1fc8ae226a7..d1addd57762 100644
--- a/src/mongo/db/commands/dbcommands.cpp
+++ b/src/mongo/db/commands/dbcommands.cpp
@@ -105,6 +105,10 @@ namespace {
class CmdDropDatabase : public BasicCommand {
public:
+ const std::set<std::string>& apiVersions() const {
+ return kApiVersions1;
+ }
+
std::string help() const override {
return "drop (delete) this database";
}
@@ -204,6 +208,11 @@ public:
class CmdDrop : public ErrmsgCommandDeprecated {
public:
CmdDrop() : ErrmsgCommandDeprecated("drop") {}
+
+ virtual const std::set<std::string>& apiVersions() const {
+ return kApiVersions1;
+ }
+
AllowedOnSecondary secondaryAllowed(ServiceContext*) const override {
return AllowedOnSecondary::kNever;
}
@@ -266,6 +275,10 @@ class CmdCreate : public BasicCommand {
public:
CmdCreate() : BasicCommand("create") {}
+ virtual const std::set<std::string>& apiVersions() const {
+ return kApiVersions1;
+ }
+
AllowedOnSecondary secondaryAllowed(ServiceContext*) const override {
return AllowedOnSecondary::kNever;
}
@@ -635,6 +648,10 @@ class CollectionModCommand : public BasicCommand {
public:
CollectionModCommand() : BasicCommand("collMod") {}
+ virtual const std::set<std::string>& apiVersions() const {
+ return kApiVersions1;
+ }
+
AllowedOnSecondary secondaryAllowed(ServiceContext*) const override {
return AllowedOnSecondary::kNever;
}
diff --git a/src/mongo/db/commands/drop_indexes.cpp b/src/mongo/db/commands/drop_indexes.cpp
index 19eb43b32fa..cb6cc68f5f5 100644
--- a/src/mongo/db/commands/drop_indexes.cpp
+++ b/src/mongo/db/commands/drop_indexes.cpp
@@ -68,9 +68,14 @@ MONGO_FAIL_POINT_DEFINE(reIndexCrashAfterDrop);
/* "dropIndexes" is now the preferred form - "deleteIndexes" deprecated */
class CmdDropIndexes : public BasicCommand {
public:
+ const std::set<std::string>& apiVersions() const {
+ return kApiVersions1;
+ }
+
AllowedOnSecondary secondaryAllowed(ServiceContext*) const override {
return AllowedOnSecondary::kNever;
}
+
virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
return true;
}
diff --git a/src/mongo/db/commands/end_sessions_command.cpp b/src/mongo/db/commands/end_sessions_command.cpp
index 15c19f907d8..d081c6d9874 100644
--- a/src/mongo/db/commands/end_sessions_command.cpp
+++ b/src/mongo/db/commands/end_sessions_command.cpp
@@ -48,6 +48,10 @@ class EndSessionsCommand final : public BasicCommand {
public:
EndSessionsCommand() : BasicCommand("endSessions") {}
+ const std::set<std::string>& apiVersions() const {
+ return kApiVersions1;
+ }
+
AllowedOnSecondary secondaryAllowed(ServiceContext*) const override {
return AllowedOnSecondary::kAlways;
}
diff --git a/src/mongo/db/commands/explain_cmd.cpp b/src/mongo/db/commands/explain_cmd.cpp
index 5cc8bc330c8..c3e1dff02e4 100644
--- a/src/mongo/db/commands/explain_cmd.cpp
+++ b/src/mongo/db/commands/explain_cmd.cpp
@@ -53,6 +53,10 @@ class CmdExplain final : public Command {
public:
CmdExplain() : Command("explain") {}
+ const std::set<std::string>& apiVersions() const {
+ return kApiVersions1;
+ }
+
std::unique_ptr<CommandInvocation> parse(OperationContext* opCtx,
const OpMsgRequest& request) override;
diff --git a/src/mongo/db/commands/find_and_modify.cpp b/src/mongo/db/commands/find_and_modify.cpp
index 143a0d4f593..9785b5b51e2 100644
--- a/src/mongo/db/commands/find_and_modify.cpp
+++ b/src/mongo/db/commands/find_and_modify.cpp
@@ -216,6 +216,10 @@ public:
CmdFindAndModify()
: BasicCommand("findAndModify", "findandmodify"), _updateMetrics{"findAndModify"} {}
+ const std::set<std::string>& apiVersions() const {
+ return kApiVersions1;
+ }
+
std::string help() const override {
return "{ findAndModify: \"collection\", query: {processed:false}, update: {$set: "
"{processed:true}}, new: true}\n"
diff --git a/src/mongo/db/commands/find_cmd.cpp b/src/mongo/db/commands/find_cmd.cpp
index 84501a9cbb7..517fb24bd54 100644
--- a/src/mongo/db/commands/find_cmd.cpp
+++ b/src/mongo/db/commands/find_cmd.cpp
@@ -128,6 +128,10 @@ class FindCmd final : public Command {
public:
FindCmd() : Command("find") {}
+ const std::set<std::string>& apiVersions() const {
+ return kApiVersions1;
+ }
+
std::unique_ptr<CommandInvocation> parse(OperationContext* opCtx,
const OpMsgRequest& opMsgRequest) override {
// TODO: Parse into a QueryRequest here.
diff --git a/src/mongo/db/commands/generic.cpp b/src/mongo/db/commands/generic.cpp
index 0296b180f05..1a52d0f7bfa 100644
--- a/src/mongo/db/commands/generic.cpp
+++ b/src/mongo/db/commands/generic.cpp
@@ -52,6 +52,10 @@ class PingCommand : public BasicCommand {
public:
PingCommand() : BasicCommand("ping") {}
+ const std::set<std::string>& apiVersions() const {
+ return kApiVersions1;
+ }
+
AllowedOnSecondary secondaryAllowed(ServiceContext*) const override {
return AllowedOnSecondary::kAlways;
}
diff --git a/src/mongo/db/commands/getmore_cmd.cpp b/src/mongo/db/commands/getmore_cmd.cpp
index 33f731e7cde..ba9947b3e7e 100644
--- a/src/mongo/db/commands/getmore_cmd.cpp
+++ b/src/mongo/db/commands/getmore_cmd.cpp
@@ -241,6 +241,12 @@ class GetMoreCmd final : public Command {
public:
GetMoreCmd() : Command("getMore") {}
+ // Do not currently use apiVersions because clients are prohibited from calling
+ // getMore with apiVersion.
+ const std::set<std::string>& apiVersions() const {
+ return kApiVersions1;
+ }
+
std::unique_ptr<CommandInvocation> parse(OperationContext* opCtx,
const OpMsgRequest& opMsgRequest) override {
return std::make_unique<Invocation>(this, opMsgRequest);
diff --git a/src/mongo/db/commands/killcursors_cmd.cpp b/src/mongo/db/commands/killcursors_cmd.cpp
index 4604a83cfa2..9acf3b85b31 100644
--- a/src/mongo/db/commands/killcursors_cmd.cpp
+++ b/src/mongo/db/commands/killcursors_cmd.cpp
@@ -48,6 +48,10 @@ class KillCursorsCmd final : public KillCursorsCmdBase {
public:
KillCursorsCmd() = default;
+ const std::set<std::string>& apiVersions() const {
+ return kApiVersions1;
+ }
+
bool run(OperationContext* opCtx,
const std::string& dbname,
const BSONObj& cmdObj,
diff --git a/src/mongo/db/commands/list_collections.cpp b/src/mongo/db/commands/list_collections.cpp
index ffe9956f205..e90b0eeed4d 100644
--- a/src/mongo/db/commands/list_collections.cpp
+++ b/src/mongo/db/commands/list_collections.cpp
@@ -212,6 +212,9 @@ BSONObj buildCollectionBson(OperationContext* opCtx,
class CmdListCollections : public BasicCommand {
public:
+ const std::set<std::string>& apiVersions() const {
+ return kApiVersions1;
+ }
AllowedOnSecondary secondaryAllowed(ServiceContext*) const final {
return AllowedOnSecondary::kOptIn;
}
diff --git a/src/mongo/db/commands/list_databases.cpp b/src/mongo/db/commands/list_databases.cpp
index c656355ec06..9da849e8cae 100644
--- a/src/mongo/db/commands/list_databases.cpp
+++ b/src/mongo/db/commands/list_databases.cpp
@@ -62,6 +62,10 @@ intmax_t dbSize(const string& database);
class CmdListDatabases : public BasicCommand {
public:
+ const std::set<std::string>& apiVersions() const {
+ return kApiVersions1;
+ }
+
AllowedOnSecondary secondaryAllowed(ServiceContext*) const final {
return AllowedOnSecondary::kOptIn;
}
diff --git a/src/mongo/db/commands/list_indexes.cpp b/src/mongo/db/commands/list_indexes.cpp
index 219cd2926f6..15e8bb52420 100644
--- a/src/mongo/db/commands/list_indexes.cpp
+++ b/src/mongo/db/commands/list_indexes.cpp
@@ -93,6 +93,10 @@ class CmdListIndexes : public BasicCommand {
public:
CmdListIndexes() : BasicCommand("listIndexes") {}
+ const std::set<std::string>& apiVersions() const {
+ return kApiVersions1;
+ }
+
AllowedOnSecondary secondaryAllowed(ServiceContext*) const override {
return AllowedOnSecondary::kOptIn;
}
diff --git a/src/mongo/db/commands/pipeline_command.cpp b/src/mongo/db/commands/pipeline_command.cpp
index 915457281fe..6b542b421ae 100644
--- a/src/mongo/db/commands/pipeline_command.cpp
+++ b/src/mongo/db/commands/pipeline_command.cpp
@@ -43,6 +43,10 @@ class PipelineCommand final : public Command {
public:
PipelineCommand() : Command("aggregate") {}
+ const std::set<std::string>& apiVersions() const {
+ return kApiVersions1;
+ }
+
/**
* It's not known until after parsing whether or not an aggregation command is an explain
* request, because it might include the `explain: true` field (ie. aggregation explains do not
diff --git a/src/mongo/db/commands/refresh_sessions_command.cpp b/src/mongo/db/commands/refresh_sessions_command.cpp
index 6c177f743f1..0d8a96d4358 100644
--- a/src/mongo/db/commands/refresh_sessions_command.cpp
+++ b/src/mongo/db/commands/refresh_sessions_command.cpp
@@ -45,6 +45,10 @@ class RefreshSessionsCommand final : public BasicCommand {
public:
RefreshSessionsCommand() : BasicCommand("refreshSessions") {}
+ const std::set<std::string>& apiVersions() const {
+ return kApiVersions1;
+ }
+
AllowedOnSecondary secondaryAllowed(ServiceContext*) const override {
return AllowedOnSecondary::kAlways;
}
diff --git a/src/mongo/db/commands/test_deprecation_command.cpp b/src/mongo/db/commands/test_deprecation_command.cpp
new file mode 100644
index 00000000000..2ec6060bbe3
--- /dev/null
+++ b/src/mongo/db/commands/test_deprecation_command.cpp
@@ -0,0 +1,85 @@
+/**
+ * Copyright (C) 2020-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.
+ */
+
+#include "mongo/db/commands.h"
+#include "mongo/db/initialize_api_parameters.h"
+
+namespace mongo {
+
+/**
+ * Command for testing API Version deprecation logic. The command replies with the values of the
+ * OperationContext's API parameters.
+ */
+class TestDeprecationCmd : public BasicCommand {
+public:
+ TestDeprecationCmd() : BasicCommand("testDeprecation") {}
+
+ const std::set<std::string>& apiVersions() const {
+ return kApiVersions1;
+ }
+
+ const std::set<std::string>& deprecatedApiVersions() const {
+ return kApiVersions1;
+ }
+
+ AllowedOnSecondary secondaryAllowed(ServiceContext*) const override {
+ return AllowedOnSecondary::kAlways;
+ }
+
+ bool supportsWriteConcern(const BSONObj& cmd) const override {
+ return false;
+ }
+
+ bool requiresAuth() const override {
+ return false;
+ }
+
+ void addRequiredPrivileges(const std::string& dbname,
+ const BSONObj& cmdObj,
+ std::vector<Privilege>* out) const override {}
+
+ std::string help() const override {
+ return "replies with the values of the OperationContext's API parameters";
+ }
+
+ bool run(OperationContext* opCtx,
+ const std::string& dbname,
+ const BSONObj& cmdObj,
+ BSONObjBuilder& result) override {
+ result.append("apiVersion", APIParameters::get(opCtx).getAPIVersion());
+ result.append("apiStrict", APIParameters::get(opCtx).getAPIStrict());
+ result.append("apiDeprecationErrors", APIParameters::get(opCtx).getAPIDeprecationErrors());
+ return true;
+ }
+};
+
+MONGO_REGISTER_TEST_COMMAND(TestDeprecationCmd);
+
+
+} // namespace mongo \ No newline at end of file
diff --git a/src/mongo/db/commands/txn_cmds.cpp b/src/mongo/db/commands/txn_cmds.cpp
index 29e76b6ffce..df7aa9787dc 100644
--- a/src/mongo/db/commands/txn_cmds.cpp
+++ b/src/mongo/db/commands/txn_cmds.cpp
@@ -61,6 +61,10 @@ class CmdCommitTxn : public BasicCommand {
public:
CmdCommitTxn() : BasicCommand("commitTransaction") {}
+ const std::set<std::string>& apiVersions() const {
+ return kApiVersions1;
+ }
+
AllowedOnSecondary secondaryAllowed(ServiceContext*) const override {
return AllowedOnSecondary::kNever;
}
@@ -161,6 +165,10 @@ class CmdAbortTxn : public BasicCommand {
public:
CmdAbortTxn() : BasicCommand("abortTransaction") {}
+ virtual const std::set<std::string>& apiVersions() const {
+ return kApiVersions1;
+ };
+
AllowedOnSecondary secondaryAllowed(ServiceContext*) const override {
return AllowedOnSecondary::kNever;
}
diff --git a/src/mongo/db/commands/write_commands/write_commands.cpp b/src/mongo/db/commands/write_commands/write_commands.cpp
index a78a7318f60..8c0d4e0549d 100644
--- a/src/mongo/db/commands/write_commands/write_commands.cpp
+++ b/src/mongo/db/commands/write_commands/write_commands.cpp
@@ -286,6 +286,10 @@ class CmdInsert final : public WriteCommand {
public:
CmdInsert() : WriteCommand("insert") {}
+ const std::set<std::string>& apiVersions() const {
+ return kApiVersions1;
+ }
+
private:
class Invocation final : public InvocationBase {
public:
@@ -332,6 +336,10 @@ class CmdUpdate final : public WriteCommand {
public:
CmdUpdate() : WriteCommand("update"), _updateMetrics{"update"} {}
+ const std::set<std::string>& apiVersions() const {
+ return kApiVersions1;
+ }
+
private:
class Invocation final : public InvocationBase {
public:
@@ -486,12 +494,17 @@ class CmdDelete final : public WriteCommand {
public:
CmdDelete() : WriteCommand("delete") {}
+ const std::set<std::string>& apiVersions() const {
+ return kApiVersions1;
+ }
+
private:
class Invocation final : public InvocationBase {
public:
Invocation(const WriteCommand* cmd, const OpMsgRequest& request)
: InvocationBase(cmd, request), _batch(DeleteOp::parse(request)) {}
+
private:
NamespaceString ns() const override {
return _batch.getNamespace();
diff --git a/src/mongo/db/initialize_api_parameters.cpp b/src/mongo/db/initialize_api_parameters.cpp
index c78f1d130f4..ed7245d7d41 100644
--- a/src/mongo/db/initialize_api_parameters.cpp
+++ b/src/mongo/db/initialize_api_parameters.cpp
@@ -31,7 +31,8 @@
namespace mongo {
-const APIParametersFromClient initializeAPIParameters(const BSONObj& requestBody) {
+const APIParametersFromClient initializeAPIParameters(const BSONObj& requestBody,
+ Command* command) {
auto apiParamsFromClient =
APIParametersFromClient::parse("APIParametersFromClient"_sd, requestBody);
@@ -48,6 +49,24 @@ const APIParametersFromClient initializeAPIParameters(const BSONObj& requestBody
"1" == apiParamsFromClient.getApiVersion().value());
}
+ if (apiParamsFromClient.getApiStrict().get_value_or(false)) {
+ auto cmdApiVersions = command->apiVersions();
+ bool strictAssert = (cmdApiVersions.find("1") != cmdApiVersions.end());
+ uassert(ErrorCodes::APIStrictError,
+ str::stream() << "Provided apiStrict:true, but the command " << command->getName()
+ << " is not in API Version \"1\"",
+ strictAssert);
+ }
+
+ if (apiParamsFromClient.getApiDeprecationErrors().get_value_or(false)) {
+ auto cmdDepApiVersions = command->deprecatedApiVersions();
+ bool deprecationAssert = (cmdDepApiVersions.find("1") == cmdDepApiVersions.end());
+ uassert(ErrorCodes::APIDeprecationError,
+ str::stream() << "Provided apiDeprecationErrors:true, but the command "
+ << command->getName() << " is deprecated in API Version \"1\"",
+ deprecationAssert);
+ }
+
return apiParamsFromClient;
}
diff --git a/src/mongo/db/initialize_api_parameters.h b/src/mongo/db/initialize_api_parameters.h
index a8c1ee141e4..9e6aac0c31a 100644
--- a/src/mongo/db/initialize_api_parameters.h
+++ b/src/mongo/db/initialize_api_parameters.h
@@ -29,6 +29,7 @@
#pragma once
+#include "mongo/db/commands.h"
#include "mongo/db/initialize_api_parameters_gen.h"
#include "mongo/db/operation_context.h"
@@ -38,7 +39,7 @@ namespace mongo {
* Parses a command's API Version parameters from a request and stores the apiVersion, apiStrict,
* and apiDeprecationErrors fields.
*/
-const APIParametersFromClient initializeAPIParameters(const BSONObj& requestBody);
+const APIParametersFromClient initializeAPIParameters(const BSONObj& requestBody, Command* command);
/**
* Decorates operation context with methods to retrieve apiVersion, apiStrict, and
diff --git a/src/mongo/db/repl/replication_info.cpp b/src/mongo/db/repl/replication_info.cpp
index c6c0c331920..6350ffea81d 100644
--- a/src/mongo/db/repl/replication_info.cpp
+++ b/src/mongo/db/repl/replication_info.cpp
@@ -225,6 +225,10 @@ class CmdIsMaster final : public BasicCommandWithReplyBuilderInterface {
public:
CmdIsMaster() : BasicCommandWithReplyBuilderInterface("isMaster", "ismaster") {}
+ const std::set<std::string>& apiVersions() const {
+ return kApiVersions1;
+ }
+
bool requiresAuth() const final {
return false;
}
diff --git a/src/mongo/db/s/config/configsvr_drop_collection_command.cpp b/src/mongo/db/s/config/configsvr_drop_collection_command.cpp
index 77cf249fd41..fc74fafc0c5 100644
--- a/src/mongo/db/s/config/configsvr_drop_collection_command.cpp
+++ b/src/mongo/db/s/config/configsvr_drop_collection_command.cpp
@@ -59,6 +59,10 @@ class ConfigSvrDropCollectionCommand : public BasicCommand {
public:
ConfigSvrDropCollectionCommand() : BasicCommand("_configsvrDropCollection") {}
+ const std::set<std::string>& apiVersions() const {
+ return kApiVersions1;
+ }
+
AllowedOnSecondary secondaryAllowed(ServiceContext*) const override {
return AllowedOnSecondary::kNever;
}
diff --git a/src/mongo/db/s/config/configsvr_drop_database_command.cpp b/src/mongo/db/s/config/configsvr_drop_database_command.cpp
index 56aa8db1d94..eb3ef547e70 100644
--- a/src/mongo/db/s/config/configsvr_drop_database_command.cpp
+++ b/src/mongo/db/s/config/configsvr_drop_database_command.cpp
@@ -54,6 +54,10 @@ class ConfigSvrDropDatabaseCommand : public BasicCommand {
public:
ConfigSvrDropDatabaseCommand() : BasicCommand("_configsvrDropDatabase") {}
+ const std::set<std::string>& apiVersions() const {
+ return kApiVersions1;
+ }
+
AllowedOnSecondary secondaryAllowed(ServiceContext*) const override {
return AllowedOnSecondary::kNever;
}
diff --git a/src/mongo/db/service_entry_point_common.cpp b/src/mongo/db/service_entry_point_common.cpp
index e8c6f5808e4..d1554581e13 100644
--- a/src/mongo/db/service_entry_point_common.cpp
+++ b/src/mongo/db/service_entry_point_common.cpp
@@ -945,7 +945,7 @@ void execCommandDatabase(OperationContext* opCtx,
auto const replCoord = repl::ReplicationCoordinator::get(opCtx);
- auto const apiParamsFromClient = initializeAPIParameters(request.body);
+ auto const apiParamsFromClient = initializeAPIParameters(request.body, command);
APIParameters::get(opCtx) = APIParameters::fromClient(apiParamsFromClient);
sessionOptions = initializeOperationSessionInfo(
diff --git a/src/mongo/embedded/mongo_embedded/mongo_embedded_test.cpp b/src/mongo/embedded/mongo_embedded/mongo_embedded_test.cpp
index 6ab5108ae51..ab600e89e15 100644
--- a/src/mongo/embedded/mongo_embedded/mongo_embedded_test.cpp
+++ b/src/mongo/embedded/mongo_embedded/mongo_embedded_test.cpp
@@ -600,6 +600,7 @@ TEST_F(MongodbCAPITest, RunListCommands) {
"setParameter",
"sleep",
"startSession",
+ "testDeprecation",
"update",
"validate",
"waitForFailPoint",
diff --git a/src/mongo/s/commands/cluster_abort_transaction_cmd.cpp b/src/mongo/s/commands/cluster_abort_transaction_cmd.cpp
index a463e94854d..9259f9c108e 100644
--- a/src/mongo/s/commands/cluster_abort_transaction_cmd.cpp
+++ b/src/mongo/s/commands/cluster_abort_transaction_cmd.cpp
@@ -51,6 +51,10 @@ class ClusterAbortTransactionCmd : public BasicCommand {
public:
ClusterAbortTransactionCmd() : BasicCommand("abortTransaction") {}
+ const std::set<std::string>& apiVersions() const {
+ return kApiVersions1;
+ }
+
AllowedOnSecondary secondaryAllowed(ServiceContext*) const override {
return AllowedOnSecondary::kAlways;
}
diff --git a/src/mongo/s/commands/cluster_collection_mod_cmd.cpp b/src/mongo/s/commands/cluster_collection_mod_cmd.cpp
index 4c276f7d2e4..6296c71a8d6 100644
--- a/src/mongo/s/commands/cluster_collection_mod_cmd.cpp
+++ b/src/mongo/s/commands/cluster_collection_mod_cmd.cpp
@@ -44,6 +44,10 @@ class CollectionModCmd : public ErrmsgCommandDeprecated {
public:
CollectionModCmd() : ErrmsgCommandDeprecated("collMod") {}
+ const std::set<std::string>& apiVersions() const {
+ return kApiVersions1;
+ }
+
AllowedOnSecondary secondaryAllowed(ServiceContext*) const override {
return AllowedOnSecondary::kNever;
}
diff --git a/src/mongo/s/commands/cluster_commit_transaction_cmd.cpp b/src/mongo/s/commands/cluster_commit_transaction_cmd.cpp
index 863113e17dd..bbcfccd0dee 100644
--- a/src/mongo/s/commands/cluster_commit_transaction_cmd.cpp
+++ b/src/mongo/s/commands/cluster_commit_transaction_cmd.cpp
@@ -46,6 +46,10 @@ class ClusterCommitTransactionCmd : public BasicCommand {
public:
ClusterCommitTransactionCmd() : BasicCommand("commitTransaction") {}
+ const std::set<std::string>& apiVersions() const {
+ return kApiVersions1;
+ }
+
AllowedOnSecondary secondaryAllowed(ServiceContext*) const override {
return AllowedOnSecondary::kAlways;
}
diff --git a/src/mongo/s/commands/cluster_count_cmd.cpp b/src/mongo/s/commands/cluster_count_cmd.cpp
index 7bc290de6ea..00e186d4d05 100644
--- a/src/mongo/s/commands/cluster_count_cmd.cpp
+++ b/src/mongo/s/commands/cluster_count_cmd.cpp
@@ -53,6 +53,10 @@ class ClusterCountCmd : public ErrmsgCommandDeprecated {
public:
ClusterCountCmd() : ErrmsgCommandDeprecated("count") {}
+ const std::set<std::string>& apiVersions() const {
+ return kApiVersions1;
+ }
+
AllowedOnSecondary secondaryAllowed(ServiceContext*) const override {
return AllowedOnSecondary::kAlways;
}
diff --git a/src/mongo/s/commands/cluster_create_cmd.cpp b/src/mongo/s/commands/cluster_create_cmd.cpp
index 2feaa027e8c..2a4f2fd7dab 100644
--- a/src/mongo/s/commands/cluster_create_cmd.cpp
+++ b/src/mongo/s/commands/cluster_create_cmd.cpp
@@ -45,6 +45,10 @@ class CreateCmd : public BasicCommand {
public:
CreateCmd() : BasicCommand("create") {}
+ const std::set<std::string>& apiVersions() const {
+ return kApiVersions1;
+ }
+
AllowedOnSecondary secondaryAllowed(ServiceContext*) const override {
return AllowedOnSecondary::kNever;
}
diff --git a/src/mongo/s/commands/cluster_create_indexes_cmd.cpp b/src/mongo/s/commands/cluster_create_indexes_cmd.cpp
index 03fd5c28775..bd27780bb6c 100644
--- a/src/mongo/s/commands/cluster_create_indexes_cmd.cpp
+++ b/src/mongo/s/commands/cluster_create_indexes_cmd.cpp
@@ -44,6 +44,10 @@ class CreateIndexesCmd : public ErrmsgCommandDeprecated {
public:
CreateIndexesCmd() : ErrmsgCommandDeprecated("createIndexes") {}
+ const std::set<std::string>& apiVersions() const {
+ return kApiVersions1;
+ }
+
AllowedOnSecondary secondaryAllowed(ServiceContext*) const override {
return AllowedOnSecondary::kNever;
}
diff --git a/src/mongo/s/commands/cluster_drop_cmd.cpp b/src/mongo/s/commands/cluster_drop_cmd.cpp
index 59a2fef563f..a69e3292597 100644
--- a/src/mongo/s/commands/cluster_drop_cmd.cpp
+++ b/src/mongo/s/commands/cluster_drop_cmd.cpp
@@ -46,6 +46,10 @@ class DropCmd : public BasicCommand {
public:
DropCmd() : BasicCommand("drop") {}
+ virtual const std::set<std::string>& apiVersions() const {
+ return kApiVersions1;
+ }
+
AllowedOnSecondary secondaryAllowed(ServiceContext*) const override {
return AllowedOnSecondary::kAlways;
}
diff --git a/src/mongo/s/commands/cluster_drop_database_cmd.cpp b/src/mongo/s/commands/cluster_drop_database_cmd.cpp
index 8610dc673d3..a78cb00fd79 100644
--- a/src/mongo/s/commands/cluster_drop_database_cmd.cpp
+++ b/src/mongo/s/commands/cluster_drop_database_cmd.cpp
@@ -46,6 +46,10 @@ class DropDatabaseCmd : public BasicCommand {
public:
DropDatabaseCmd() : BasicCommand("dropDatabase") {}
+ const std::set<std::string>& apiVersions() const {
+ return kApiVersions1;
+ }
+
AllowedOnSecondary secondaryAllowed(ServiceContext*) const override {
return AllowedOnSecondary::kAlways;
}
diff --git a/src/mongo/s/commands/cluster_drop_indexes_cmd.cpp b/src/mongo/s/commands/cluster_drop_indexes_cmd.cpp
index b26d3703db9..87ca9422a13 100644
--- a/src/mongo/s/commands/cluster_drop_indexes_cmd.cpp
+++ b/src/mongo/s/commands/cluster_drop_indexes_cmd.cpp
@@ -71,6 +71,10 @@ void updateStateForStaleConfigRetry(OperationContext* opCtx,
class DropIndexesCmd : public ErrmsgCommandDeprecated {
public:
+ const std::set<std::string>& apiVersions() const {
+ return kApiVersions1;
+ }
+
DropIndexesCmd() : ErrmsgCommandDeprecated("dropIndexes", "deleteIndexes") {}
AllowedOnSecondary secondaryAllowed(ServiceContext*) const override {
diff --git a/src/mongo/s/commands/cluster_explain_cmd.cpp b/src/mongo/s/commands/cluster_explain_cmd.cpp
index 9fd37a65c78..4d17e5ebd19 100644
--- a/src/mongo/s/commands/cluster_explain_cmd.cpp
+++ b/src/mongo/s/commands/cluster_explain_cmd.cpp
@@ -54,6 +54,10 @@ class ClusterExplainCmd final : public Command {
public:
ClusterExplainCmd() : Command("explain") {}
+ const std::set<std::string>& apiVersions() const {
+ return kApiVersions1;
+ }
+
std::unique_ptr<CommandInvocation> parse(OperationContext* opCtx,
const OpMsgRequest& request) override;
diff --git a/src/mongo/s/commands/cluster_find_and_modify_cmd.cpp b/src/mongo/s/commands/cluster_find_and_modify_cmd.cpp
index 17013526125..c8b52598c2d 100644
--- a/src/mongo/s/commands/cluster_find_and_modify_cmd.cpp
+++ b/src/mongo/s/commands/cluster_find_and_modify_cmd.cpp
@@ -170,6 +170,10 @@ public:
FindAndModifyCmd()
: BasicCommand("findAndModify", "findandmodify"), _updateMetrics{"findAndModify"} {}
+ const std::set<std::string>& apiVersions() const {
+ return kApiVersions1;
+ }
+
AllowedOnSecondary secondaryAllowed(ServiceContext*) const override {
return AllowedOnSecondary::kAlways;
}
diff --git a/src/mongo/s/commands/cluster_find_cmd.cpp b/src/mongo/s/commands/cluster_find_cmd.cpp
index 51d6272400b..3bd8ff6c7c3 100644
--- a/src/mongo/s/commands/cluster_find_cmd.cpp
+++ b/src/mongo/s/commands/cluster_find_cmd.cpp
@@ -85,6 +85,10 @@ class ClusterFindCmd final : public Command {
public:
ClusterFindCmd() : Command("find") {}
+ const std::set<std::string>& apiVersions() const {
+ return kApiVersions1;
+ }
+
std::unique_ptr<CommandInvocation> parse(OperationContext* opCtx,
const OpMsgRequest& opMsgRequest) override {
// TODO: Parse into a QueryRequest here.
diff --git a/src/mongo/s/commands/cluster_getmore_cmd.cpp b/src/mongo/s/commands/cluster_getmore_cmd.cpp
index fdc167d2cb7..037e278d1e3 100644
--- a/src/mongo/s/commands/cluster_getmore_cmd.cpp
+++ b/src/mongo/s/commands/cluster_getmore_cmd.cpp
@@ -58,6 +58,12 @@ class ClusterGetMoreCmd final : public Command {
public:
ClusterGetMoreCmd() : Command("getMore") {}
+ // Do not currently use apiVersions because clients are prohibited from calling
+ // getMore with apiVersion.
+ const std::set<std::string>& apiVersions() const {
+ return kApiVersions1;
+ }
+
std::unique_ptr<CommandInvocation> parse(OperationContext* opCtx,
const OpMsgRequest& opMsgRequest) override {
return std::make_unique<Invocation>(this, opMsgRequest);
diff --git a/src/mongo/s/commands/cluster_is_master_cmd.cpp b/src/mongo/s/commands/cluster_is_master_cmd.cpp
index 778ec8aae17..cab3fca4f18 100644
--- a/src/mongo/s/commands/cluster_is_master_cmd.cpp
+++ b/src/mongo/s/commands/cluster_is_master_cmd.cpp
@@ -59,6 +59,10 @@ class CmdIsMaster : public BasicCommandWithReplyBuilderInterface {
public:
CmdIsMaster() : BasicCommandWithReplyBuilderInterface("isMaster", "ismaster") {}
+ const std::set<std::string>& apiVersions() const {
+ return kApiVersions1;
+ }
+
bool supportsWriteConcern(const BSONObj& cmd) const override {
return false;
}
diff --git a/src/mongo/s/commands/cluster_killcursors_cmd.cpp b/src/mongo/s/commands/cluster_killcursors_cmd.cpp
index 106a6f7f1d6..b02c3ebe2a3 100644
--- a/src/mongo/s/commands/cluster_killcursors_cmd.cpp
+++ b/src/mongo/s/commands/cluster_killcursors_cmd.cpp
@@ -42,6 +42,10 @@ class ClusterKillCursorsCmd final : public KillCursorsCmdBase {
public:
ClusterKillCursorsCmd() = default;
+ const std::set<std::string>& apiVersions() const {
+ return kApiVersions1;
+ }
+
ReadConcernSupportResult supportsReadConcern(const BSONObj& cmdObj,
repl::ReadConcernLevel level) const final {
// killCursors must support read concerns in order to be run in transactions.
diff --git a/src/mongo/s/commands/cluster_list_collections_cmd.cpp b/src/mongo/s/commands/cluster_list_collections_cmd.cpp
index 255d4ec7453..a6adf99544b 100644
--- a/src/mongo/s/commands/cluster_list_collections_cmd.cpp
+++ b/src/mongo/s/commands/cluster_list_collections_cmd.cpp
@@ -160,6 +160,10 @@ class CmdListCollections : public BasicCommand {
public:
CmdListCollections() : BasicCommand("listCollections") {}
+ const std::set<std::string>& apiVersions() const {
+ return kApiVersions1;
+ }
+
bool supportsWriteConcern(const BSONObj& cmd) const override {
return false;
}
diff --git a/src/mongo/s/commands/cluster_list_databases_cmd.cpp b/src/mongo/s/commands/cluster_list_databases_cmd.cpp
index 4222656f498..5dea5e17120 100644
--- a/src/mongo/s/commands/cluster_list_databases_cmd.cpp
+++ b/src/mongo/s/commands/cluster_list_databases_cmd.cpp
@@ -51,6 +51,10 @@ class ListDatabasesCmd : public BasicCommand {
public:
ListDatabasesCmd() : BasicCommand("listDatabases", "listdatabases") {}
+ const std::set<std::string>& apiVersions() const {
+ return kApiVersions1;
+ }
+
AllowedOnSecondary secondaryAllowed(ServiceContext*) const override {
return AllowedOnSecondary::kAlways;
}
diff --git a/src/mongo/s/commands/cluster_list_indexes_cmd.cpp b/src/mongo/s/commands/cluster_list_indexes_cmd.cpp
index 56828a9ee95..8a4d93a3297 100644
--- a/src/mongo/s/commands/cluster_list_indexes_cmd.cpp
+++ b/src/mongo/s/commands/cluster_list_indexes_cmd.cpp
@@ -72,6 +72,10 @@ class CmdListIndexes : public BasicCommand {
public:
CmdListIndexes() : BasicCommand("listIndexes") {}
+ const std::set<std::string>& apiVersions() const {
+ return kApiVersions1;
+ }
+
std::string parseNs(const std::string& dbname, const BSONObj& cmdObj) const override {
return CommandHelpers::parseNsCollectionRequired(dbname, cmdObj).ns();
}
diff --git a/src/mongo/s/commands/cluster_pipeline_cmd.cpp b/src/mongo/s/commands/cluster_pipeline_cmd.cpp
index 7cca5f09c17..cbeb9022c43 100644
--- a/src/mongo/s/commands/cluster_pipeline_cmd.cpp
+++ b/src/mongo/s/commands/cluster_pipeline_cmd.cpp
@@ -45,6 +45,10 @@ class ClusterPipelineCommand final : public Command {
public:
ClusterPipelineCommand() : Command("aggregate") {}
+ const std::set<std::string>& apiVersions() const {
+ return kApiVersions1;
+ }
+
/**
* It's not known until after parsing whether or not an aggregation command is an explain
* request, because it might include the `explain: true` field (ie. aggregation explains do not
diff --git a/src/mongo/s/commands/cluster_write_cmd.cpp b/src/mongo/s/commands/cluster_write_cmd.cpp
index 24e98b9dced..17d1d415679 100644
--- a/src/mongo/s/commands/cluster_write_cmd.cpp
+++ b/src/mongo/s/commands/cluster_write_cmd.cpp
@@ -633,6 +633,10 @@ class ClusterInsertCmd final : public ClusterWriteCmd {
public:
ClusterInsertCmd() : ClusterWriteCmd("insert") {}
+ const std::set<std::string>& apiVersions() const {
+ return kApiVersions1;
+ }
+
private:
class Invocation final : public InvocationBase {
public:
@@ -666,6 +670,10 @@ class ClusterUpdateCmd final : public ClusterWriteCmd {
public:
ClusterUpdateCmd() : ClusterWriteCmd("update"), _updateMetrics{"update"} {}
+ const std::set<std::string>& apiVersions() const {
+ return kApiVersions1;
+ }
+
private:
class Invocation final : public InvocationBase {
public:
@@ -705,6 +713,10 @@ class ClusterDeleteCmd final : public ClusterWriteCmd {
public:
ClusterDeleteCmd() : ClusterWriteCmd("delete") {}
+ const std::set<std::string>& apiVersions() const {
+ return kApiVersions1;
+ }
+
private:
class Invocation final : public InvocationBase {
public:
diff --git a/src/mongo/s/commands/strategy.cpp b/src/mongo/s/commands/strategy.cpp
index 13373695a05..2b7607cfcdc 100644
--- a/src/mongo/s/commands/strategy.cpp
+++ b/src/mongo/s/commands/strategy.cpp
@@ -348,7 +348,7 @@ void runCommand(OperationContext* opCtx,
// Fill out all currentOp details.
CurOp::get(opCtx)->setGenericOpRequestDetails(opCtx, nss, command, request.body, opType);
- auto const apiParamsFromClient = initializeAPIParameters(request.body);
+ auto const apiParamsFromClient = initializeAPIParameters(request.body, command);
APIParameters::get(opCtx) = APIParameters::fromClient(apiParamsFromClient);
auto osi = initializeOperationSessionInfo(opCtx,