diff options
-rw-r--r-- | jstests/libs/feature_compatibility_version.js | 29 | ||||
-rw-r--r-- | jstests/multiVersion/remove_feature_compatibility_version.js | 18 | ||||
-rw-r--r-- | jstests/multiVersion/set_feature_compatibility_version.js | 26 | ||||
-rw-r--r-- | jstests/noPassthrough/feature_compatibility_version.js | 30 | ||||
-rw-r--r-- | src/mongo/db/commands/rename_collection_cmd.cpp | 7 | ||||
-rw-r--r-- | src/mongo/db/namespace_string.h | 3 | ||||
-rw-r--r-- | src/mongo/db/op_observer_impl.cpp | 7 | ||||
-rw-r--r-- | src/mongo/db/repl/sync_tail_test.cpp | 43 |
8 files changed, 65 insertions, 98 deletions
diff --git a/jstests/libs/feature_compatibility_version.js b/jstests/libs/feature_compatibility_version.js index 116706eaf27..81ac0956ae4 100644 --- a/jstests/libs/feature_compatibility_version.js +++ b/jstests/libs/feature_compatibility_version.js @@ -30,4 +30,31 @@ function checkFCV34(adminDB, version) { let doc = adminDB.system.version.findOne({_id: "featureCompatibilityVersion"}); assert.eq(doc.version, version, tojson(doc)); -}
\ No newline at end of file +} + +/** + * Since SERVER-29453 disallows us to remove the FCV document in 3.6, we need to + * do this hack to remove it. Notice this is only for 3.6. For 3.4, we can + * simply remove the FCV document. + */ +function removeFCVDocument(adminDB) { + let res = adminDB.runCommand({listCollections: 1, filter: {name: "system.version"}}); + assert.commandWorked(res, "failed to list collections"); + let originalUUID = res.cursor.firstBatch[0].info.uuid; + let newUUID = UUID(); + + // Create new collection with no FCV document, and then delete the + // original collection. + let createNewAdminSystemVersionCollection = + {op: "c", ns: "admin.$cmd", ui: newUUID, o: {create: "system.version"}}; + let dropOriginalAdminSystemVersionCollection = + {op: "c", ns: "admin.$cmd", ui: originalUUID, o: {drop: "admin.tmp_system_version"}}; + assert.commandWorked(adminDB.runCommand({ + applyOps: + [createNewAdminSystemVersionCollection, dropOriginalAdminSystemVersionCollection] + })); + + res = adminDB.runCommand({listCollections: 1, filter: {name: "system.version"}}); + assert.commandWorked(res, "failed to list collections"); + assert.eq(newUUID, res.cursor.firstBatch[0].info.uuid); +} diff --git a/jstests/multiVersion/remove_feature_compatibility_version.js b/jstests/multiVersion/remove_feature_compatibility_version.js new file mode 100644 index 00000000000..6e1448d5f5e --- /dev/null +++ b/jstests/multiVersion/remove_feature_compatibility_version.js @@ -0,0 +1,18 @@ +/** + * This test is for SERVER-29453: Renaming the admin.system.version collection + * or removing the FCV document should not be allowed. + */ +(function() { + 'use strict'; + + let standalone = MongoRunner.runMongod(); + assert.neq(null, standalone, 'mongod was unable to start up'); + let adminDB = standalone.getDB('admin'); + + // Renaming the collection or deleting the document should fail. + assert.commandFailedWithCode( + adminDB.runCommand( + {renameCollection: 'admin.system.version', to: 'admin.dummy.collection'}), + ErrorCodes.IllegalOperation); + assert.writeErrorWithCode(adminDB.system.version.remove({}), 40670); +})(); diff --git a/jstests/multiVersion/set_feature_compatibility_version.js b/jstests/multiVersion/set_feature_compatibility_version.js index 83c88ec77f5..abf6043546d 100644 --- a/jstests/multiVersion/set_feature_compatibility_version.js +++ b/jstests/multiVersion/set_feature_compatibility_version.js @@ -80,13 +80,15 @@ TestData.skipCheckingUUIDsConsistentAcrossCluster = true; adminDB.system.version.findOne({_id: "featureCompatibilityVersion"}).version, "3.6", "expected 3.6 mongod with no data files to start up with featureCompatibilityVersion 3.6"); + removeFCVDocument(adminDB); } else { assert.eq( adminDB.system.version.findOne({_id: "featureCompatibilityVersion"}).version, "3.4", "expected 3.4 mongod with no data files to start up with featureCompatibilityVersion 3.4"); + assert.writeOK(adminDB.system.version.remove({_id: "featureCompatibilityVersion"})); } - assert.writeOK(adminDB.system.version.remove({_id: "featureCompatibilityVersion"})); + MongoRunner.stopMongod(conn); return conn; }; @@ -376,28 +378,6 @@ TestData.skipCheckingUUIDsConsistentAcrossCluster = true; 0); rst.stopSet(); - // A mixed 3.4/3.6 replica set without a featureCompatibilityVersion document unfortunately - // reports mixed 3.2/3.4 featureCompatibilityVersion. - rst = new ReplSetTest({nodes: [{binVersion: downgrade}, {binVersion: latest}]}); - rstConns = rst.startSet(); - replSetConfig = rst.getReplSetConfig(); - replSetConfig.members[1].priority = 0; - replSetConfig.members[1].votes = 0; - rst.initiate(replSetConfig); - - primaryAdminDB = rst.getPrimary().getDB("admin"); - secondaryAdminDB = rst.getSecondary().getDB("admin"); - assert.writeOK(primaryAdminDB.system.version.remove({_id: "featureCompatibilityVersion"}, - {writeConcern: {w: 2}})); - res = primaryAdminDB.runCommand({getParameter: 1, featureCompatibilityVersion: 1}); - assert.commandWorked(res); - assert.eq(res.featureCompatibilityVersion, "3.2"); - res = secondaryAdminDB.runCommand({getParameter: 1, featureCompatibilityVersion: 1}); - assert.commandWorked(res); - assert.eq(res.featureCompatibilityVersion.version, "3.4", tojson(res)); - assert.eq(res.featureCompatibilityVersion.targetVersion, null, tojson(res)); - rst.stopSet(); - // Test idempotency for setFeatureCompatibilityVersion. rst = new ReplSetTest({nodes: 2, nodeOpts: {binVersion: latest}}); rst.startSet(); diff --git a/jstests/noPassthrough/feature_compatibility_version.js b/jstests/noPassthrough/feature_compatibility_version.js index de37a2a29a2..016c5d12e08 100644 --- a/jstests/noPassthrough/feature_compatibility_version.js +++ b/jstests/noPassthrough/feature_compatibility_version.js @@ -12,11 +12,6 @@ */ let checkFCVDocumentMissing = function(adminDB) { assert.eq(null, adminDB.system.version.findOne({_id: "featureCompatibilityVersion"})); - - let res = adminDB.runCommand({getParameter: 1, featureCompatibilityVersion: 1}); - assert.commandWorked(res); - assert.eq("3.4", res.featureCompatibilityVersion.version, tojson(res)); - assert.eq(null, res.featureCompatibilityVersion.targetVersion, tojson(res)); }; const conn = MongoRunner.runMongod({}); @@ -65,7 +60,7 @@ // Deleting the featureCompatibilityVersion document changes the featureCompatibilityVersion // server parameter to 3.4. - assert.writeOK(adminDB.system.version.remove({_id: "featureCompatibilityVersion"})); + removeFCVDocument(adminDB); checkFCVDocumentMissing(adminDB); // Inserting a featureCompatibilityVersion document with an invalid version fails. @@ -92,29 +87,6 @@ ErrorCodes.BadValue); checkFCVDocumentMissing(adminDB); - // Inserting the featureCompatibilityVersion document changes the featureCompatibilityVersion - // server parameter. - assert.writeOK( - adminDB.system.version.insert({_id: "featureCompatibilityVersion", version: "3.4"})); - checkFCV(adminDB, "3.4"); - - assert.writeOK(adminDB.system.version.remove({_id: "featureCompatibilityVersion"})); - checkFCVDocumentMissing(adminDB); - - assert.writeOK(adminDB.system.version.insert( - {_id: "featureCompatibilityVersion", version: "3.4", targetVersion: "3.6"})); - checkFCV(adminDB, "3.4", "3.6"); - - assert.writeOK(adminDB.system.version.remove({_id: "featureCompatibilityVersion"})); - checkFCVDocumentMissing(adminDB); - - assert.writeOK(adminDB.system.version.insert( - {_id: "featureCompatibilityVersion", version: "3.4", targetVersion: "3.4"})); - checkFCV(adminDB, "3.4", "3.4"); - - assert.writeOK(adminDB.system.version.remove({_id: "featureCompatibilityVersion"})); - checkFCVDocumentMissing(adminDB); - assert.writeOK( adminDB.system.version.insert({_id: "featureCompatibilityVersion", version: "3.6"})); checkFCV(adminDB, "3.6"); diff --git a/src/mongo/db/commands/rename_collection_cmd.cpp b/src/mongo/db/commands/rename_collection_cmd.cpp index 569907eaab2..6385dcc5d0f 100644 --- a/src/mongo/db/commands/rename_collection_cmd.cpp +++ b/src/mongo/db/commands/rename_collection_cmd.cpp @@ -144,6 +144,13 @@ public: return false; } + if (source.isAdminDotSystemDotVersion()) { + appendCommandStatus(result, + Status(ErrorCodes::IllegalOperation, + "renaming admin.system.version is not allowed")); + return false; + } + RenameCollectionOptions options; options.dropTarget = cmdObj["dropTarget"].trueValue(); options.stayTemp = cmdObj["stayTemp"].trueValue(); diff --git a/src/mongo/db/namespace_string.h b/src/mongo/db/namespace_string.h index f110489916e..07240fa9f0a 100644 --- a/src/mongo/db/namespace_string.h +++ b/src/mongo/db/namespace_string.h @@ -192,6 +192,9 @@ public: bool isSystemDotViews() const { return coll() == kSystemDotViewsCollectionName; } + bool isAdminDotSystemDotVersion() const { + return ((db() == "admin") && (coll() == "system.version")); + } bool isConfigDB() const { return db() == "config"; } diff --git a/src/mongo/db/op_observer_impl.cpp b/src/mongo/db/op_observer_impl.cpp index 6da9b7f9599..cdc1dbc4756 100644 --- a/src/mongo/db/op_observer_impl.cpp +++ b/src/mongo/db/op_observer_impl.cpp @@ -437,8 +437,11 @@ void OpObserverImpl::onDelete(OperationContext* opCtx, Scope::storedFuncMod(opCtx); } else if (nss.coll() == DurableViewCatalog::viewsCollectionName()) { DurableViewCatalog::onExternalChange(opCtx, nss); - } else if (nss.ns() == FeatureCompatibilityVersion::kCollection) { - FeatureCompatibilityVersion::onDelete(opCtx, deleteState.documentKey); + } else if (nss.isAdminDotSystemDotVersion()) { + auto _id = deleteState.documentKey["_id"]; + if (_id.type() == BSONType::String && + _id.String() == FeatureCompatibilityVersion::kParameterName) + uasserted(40670, "removing FeatureCompatibilityVersion document is not allowed"); } else if (nss == NamespaceString::kSessionTransactionsTableNamespace && !opTime.writeOpTime.isNull()) { SessionCatalog::get(opCtx)->invalidateSessions(opCtx, deleteState.documentKey); diff --git a/src/mongo/db/repl/sync_tail_test.cpp b/src/mongo/db/repl/sync_tail_test.cpp index e1c83e5e89f..6f7537ee68f 100644 --- a/src/mongo/db/repl/sync_tail_test.cpp +++ b/src/mongo/db/repl/sync_tail_test.cpp @@ -1664,29 +1664,6 @@ TEST_F(SyncTailTest, FailOnDropFCVCollectionInRecovering) { ASSERT_EQUALS(runOpSteadyState(op), ErrorCodes::OplogOperationUnsupported); } -TEST_F(SyncTailTest, FailOnDeleteFCVDocumentInRecovering) { - auto fcvNS = NamespaceString(FeatureCompatibilityVersion::kCollection); - CollectionOptions options; - options.uuid = UUID::gen(); - ::mongo::repl::createCollection(_opCtx.get(), fcvNS, options); - - // Insert the fCV document. - ASSERT_OK( - ReplicationCoordinator::get(_opCtx.get())->setFollowerMode(MemberState::RS_SECONDARY)); - auto insertCmd = BSON("_id" << FeatureCompatibilityVersion::kParameterName - << FeatureCompatibilityVersion::kVersionField - << FeatureCompatibilityVersionCommandParser::kVersion36); - auto insertOp = makeInsertDocumentOplogEntry(nextOpTime(), fcvNS, insertCmd); - ASSERT_OK(runOpSteadyState(insertOp)); - - ASSERT_OK( - ReplicationCoordinator::get(_opCtx.get())->setFollowerMode(MemberState::RS_RECOVERING)); - - auto cmd = BSON("_id" << FeatureCompatibilityVersion::kParameterName); - auto op = makeDeleteDocumentOplogEntry(nextOpTime(), fcvNS, cmd); - ASSERT_EQUALS(runOpSteadyState(op), ErrorCodes::OplogOperationUnsupported); -} - TEST_F(SyncTailTest, SuccessOnUpdateFCV34TargetVersionUnsetDocumentInRecovering) { auto fcvNS = NamespaceString(FeatureCompatibilityVersion::kCollection); ::mongo::repl::createCollection(_opCtx.get(), fcvNS, CollectionOptions()); @@ -1732,26 +1709,6 @@ TEST_F(SyncTailTest, SuccessOnDropFCVCollectionInSecondary) { ASSERT_OK(runOpSteadyState(op)); } -TEST_F(SyncTailTest, SuccessOnDeleteFCVDocumentInSecondary) { - auto fcvNS = NamespaceString(FeatureCompatibilityVersion::kCollection); - CollectionOptions options; - options.uuid = UUID::gen(); - ::mongo::repl::createCollection(_opCtx.get(), fcvNS, options); - ASSERT_OK( - ReplicationCoordinator::get(_opCtx.get())->setFollowerMode(MemberState::RS_SECONDARY)); - - // Insert the fCV document. - auto insertCmd = BSON("_id" << FeatureCompatibilityVersion::kParameterName - << FeatureCompatibilityVersion::kVersionField - << FeatureCompatibilityVersionCommandParser::kVersion36); - auto insertOp = makeInsertDocumentOplogEntry(nextOpTime(), fcvNS, insertCmd); - ASSERT_OK(runOpSteadyState(insertOp)); - - auto cmd = BSON("_id" << FeatureCompatibilityVersion::kParameterName); - auto op = makeDeleteDocumentOplogEntry(nextOpTime(), fcvNS, cmd); - ASSERT_OK(runOpSteadyState(op)); -} - TEST_F(SyncTailTest, SuccessOnUpdateFCV34TargetVersion34DocumentInSecondary) { auto fcvNS = NamespaceString(FeatureCompatibilityVersion::kCollection); ::mongo::repl::createCollection(_opCtx.get(), fcvNS, CollectionOptions()); |