diff options
author | Moustafa Maher <m.maher@10gen.com> | 2021-05-19 01:41:11 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2021-05-19 20:31:00 +0000 |
commit | a04e6daade40026c2dca545622d082ef6bb8c82c (patch) | |
tree | f0b7f0e262ae3c870856e8dba62ed0aab30e1558 | |
parent | f99bf23e8e6d88e4ff6800eb24b200fc382e7753 (diff) | |
download | mongo-a04e6daade40026c2dca545622d082ef6bb8c82c.tar.gz |
SERVER-57010 Check default write concern during replica set reconfig When the feature flag is enabled
-rw-r--r-- | jstests/replsets/libs/rename_across_dbs.js | 9 | ||||
-rw-r--r-- | jstests/replsets/reconfig_add_remove_arbiter.js | 9 | ||||
-rw-r--r-- | jstests/replsets/reconfig_fails_no_cwwc_set.js | 62 | ||||
-rw-r--r-- | src/mongo/db/read_write_concern_defaults.cpp | 17 | ||||
-rw-r--r-- | src/mongo/db/read_write_concern_defaults.h | 5 | ||||
-rw-r--r-- | src/mongo/db/read_write_concern_defaults_test.cpp | 39 | ||||
-rw-r--r-- | src/mongo/db/repl/SConscript | 1 | ||||
-rw-r--r-- | src/mongo/db/repl/replication_coordinator_impl.cpp | 23 | ||||
-rw-r--r-- | src/mongo/db/repl/replication_coordinator_impl_reconfig_test.cpp | 9 | ||||
-rw-r--r-- | src/mongo/db/repl/replication_coordinator_test_fixture.cpp | 3 | ||||
-rw-r--r-- | src/mongo/db/repl/replication_coordinator_test_fixture.h | 4 |
11 files changed, 170 insertions, 11 deletions
diff --git a/jstests/replsets/libs/rename_across_dbs.js b/jstests/replsets/libs/rename_across_dbs.js index a602b51326f..59b0fba4e14 100644 --- a/jstests/replsets/libs/rename_across_dbs.js +++ b/jstests/replsets/libs/rename_across_dbs.js @@ -48,6 +48,15 @@ var RenameAcrossDatabasesTest = function(options) { replTest.startSet(); replTest.initiate(); + // This test performs a reconfig that will change the implicit default write concern + // from {w: "majority"} to {w: 1}. In order for this reconfig to succeed, we must first + // set the cluster-wide write concern. + assert.commandWorked(replTest.getPrimary().adminCommand({ + setDefaultRWConcern: 1, + defaultWriteConcern: {w: "majority"}, + writeConcern: {w: "majority"} + })); + // If provided in 'options', we set the featureCompatibilityVersion. We do this prior to // adding any other members to the replica set. if (options.setFeatureCompatibilityVersion) { diff --git a/jstests/replsets/reconfig_add_remove_arbiter.js b/jstests/replsets/reconfig_add_remove_arbiter.js index 0ae14b64b0d..7cbb733c306 100644 --- a/jstests/replsets/reconfig_add_remove_arbiter.js +++ b/jstests/replsets/reconfig_add_remove_arbiter.js @@ -14,9 +14,16 @@ const replTest = new ReplSetTest({nodes: 2}); replTest.startSet(); replTest.initiate(); +const primary = replTest.getPrimary(); +// This test performs a reconfig that will change the implicit default write concern +// from {w: "majority"} to {w: 1}. In order for this reconfig to succeed, we must first +// set the cluster-wide write concern. +assert.commandWorked(primary.adminCommand( + {setDefaultRWConcern: 1, defaultWriteConcern: {w: "majority"}, writeConcern: {w: "majority"}})); + jsTestLog('Start arbiter'); const arbiterConn = replTest.add(); -const admin = replTest.getPrimary().getDB('admin'); +const admin = primary.getDB('admin'); const conf = replTest.getReplSetConfigFromNode(); conf.members.push({_id: 2, host: arbiterConn.host, arbiterOnly: true}); conf.version++; diff --git a/jstests/replsets/reconfig_fails_no_cwwc_set.js b/jstests/replsets/reconfig_fails_no_cwwc_set.js new file mode 100644 index 00000000000..326f193ffd7 --- /dev/null +++ b/jstests/replsets/reconfig_fails_no_cwwc_set.js @@ -0,0 +1,62 @@ +/* + * Test that a reconfig that would change the implicit default write concern fails. + * In order to perform such a reconfig, users must set a cluster-wide write concern. + * + * @tags: [requires_fcv_50] + */ + +(function() { +'use strict'; + +load("jstests/libs/write_concern_util.js"); // For 'isDefaultWriteConcernMajorityFlagEnabled()'. + +const rst = new ReplSetTest({nodes: 2}); +rst.startSet(); +rst.initiate(); + +const primary = rst.getPrimary(); + +const featureFlagEnabled = isDefaultWriteConcernMajorityFlagEnabled(primary); +let cwwc = primary.adminCommand({getDefaultRWConcern: 1}); +if (featureFlagEnabled) { + assert(cwwc.hasOwnProperty("defaultWriteConcern")); + assert.eq({w: "majority", wtimeout: 0}, cwwc.defaultWriteConcern, tojson(cwwc)); +} else { + assert(!cwwc.hasOwnProperty("defaultWriteConcern")); +} + +jsTestLog("Starting arbiter"); +const arbiter = rst.add(); +const config = rst.getReplSetConfigFromNode(); +config.members.push({_id: 2, host: arbiter.host, arbiterOnly: true}); +config.version++; +const reconfigErrorMsg = + "Reconfig attempted to install a config that would change the implicit default write concern"; + +if (featureFlagEnabled) { + // Adding the arbiter would change the implicit default write concern from {w: majority} to + // {w:1}, so we fail the reconfig. + let res = assert.commandFailed(primary.adminCommand({replSetReconfig: config})); + assert.eq(res.code, ErrorCodes.NewReplicaSetConfigurationIncompatible); + assert(res.errmsg.includes(reconfigErrorMsg)); + + // A force reconfig should also fail. + res = assert.commandFailed(primary.adminCommand({replSetReconfig: config, force: true})); + assert.eq(res.code, ErrorCodes.NewReplicaSetConfigurationIncompatible); + assert(res.errmsg.includes(reconfigErrorMsg)); + + assert.commandWorked(primary.adminCommand( + {setDefaultRWConcern: 1, defaultWriteConcern: {w: 1}, writeConcern: {w: "majority"}})); + + // After setting the cluster-wide write concern, the same reconfig command should succeed. + assert.commandWorked(primary.adminCommand({replSetReconfig: config})); + + cwwc = primary.adminCommand({getDefaultRWConcern: 1}); + assert(cwwc.hasOwnProperty("defaultWriteConcern")); + assert.eq({w: 1, wtimeout: 0}, cwwc.defaultWriteConcern, tojson(cwwc)); +} else { + assert.commandWorked(primary.adminCommand({replSetReconfig: config})); +} + +rst.stopSet(); +})(); diff --git a/src/mongo/db/read_write_concern_defaults.cpp b/src/mongo/db/read_write_concern_defaults.cpp index 183805cf64d..c982ef78bda 100644 --- a/src/mongo/db/read_write_concern_defaults.cpp +++ b/src/mongo/db/read_write_concern_defaults.cpp @@ -161,6 +161,23 @@ RWConcernDefault ReadWriteConcernDefaults::generateNewCWRWCToBeSavedOnDisk( return rwc; } +bool ReadWriteConcernDefaults::isCWWCSet(OperationContext* opCtx) { + // TODO (SERVER-57042): Call getDefault() instead and return writeConcernSource == KGlobal. + auto cached = _getDefaultCWRWCFromDisk(opCtx); + if (!cached) { + return false; + } + + auto wc = cached.get().getDefaultWriteConcern(); + if (!wc) { + return false; + } + + // CWWC should have "usedDefault" flag set to false, as this flag only set to true if the + // default constructed WC is used. + return !wc.get().usedDefault; +} + void ReadWriteConcernDefaults::observeDirectWriteToConfigSettings(OperationContext* opCtx, BSONElement idElem, boost::optional<BSONObj> newDoc) { diff --git a/src/mongo/db/read_write_concern_defaults.h b/src/mongo/db/read_write_concern_defaults.h index 2108cb8c189..1ce216c2b80 100644 --- a/src/mongo/db/read_write_concern_defaults.h +++ b/src/mongo/db/read_write_concern_defaults.h @@ -130,6 +130,11 @@ public: const boost::optional<WriteConcern>& wc); /** + * Returns true if cluster-wide write concern is set and false otherwise. + */ + bool isCWWCSet(OperationContext* opCtx); + + /** * Invalidates the cached RWC defaults, causing them to be refreshed. * * After this call returns, the read methods below (getDefault, getDefaultReadConcern, diff --git a/src/mongo/db/read_write_concern_defaults_test.cpp b/src/mongo/db/read_write_concern_defaults_test.cpp index 1d558ff2ed4..73009587628 100644 --- a/src/mongo/db/read_write_concern_defaults_test.cpp +++ b/src/mongo/db/read_write_concern_defaults_test.cpp @@ -54,6 +54,10 @@ protected: return ReadWriteConcernDefaults::get(getServiceContext()).getDefault(_opCtx); } + bool isCWWCSet() { + return ReadWriteConcernDefaults::get(getServiceContext()).isCWWCSet(_opCtx); + } + ReadWriteConcernDefaultsLookupMock _lookupMock; bool _isDefaultWCMajorityEnabled{ @@ -72,6 +76,7 @@ TEST_F(ReadWriteConcernDefaultsTest, TestGetDefaultWithAbsentCWRWCWithImplicitWC auto defaults = getDefault(); ASSERT(!defaults.getDefaultReadConcern()); ASSERT(!defaults.getDefaultWriteConcern()); + ASSERT(!isCWWCSet()); ASSERT(!defaults.getUpdateOpTime()); ASSERT(!defaults.getUpdateWallClockTime()); ASSERT_EQ(Date_t(), defaults.localUpdateWallClockTime()); @@ -89,6 +94,7 @@ TEST_F(ReadWriteConcernDefaultsTest, TestGetDefaultWithAbsentCWRWCWithImplicitWC // By not calling _lookupMock.setLookupCallReturnValue(), tests _defaults.lookup() returning // boost::none. + ASSERT(!isCWWCSet()); auto defaults = getDefault(); ASSERT(!defaults.getDefaultReadConcern()); ASSERT(defaults.getDefaultWriteConcern()); @@ -105,6 +111,7 @@ TEST_F(ReadWriteConcernDefaultsTest, TestGetDefaultWithCWRWCNeverSetWithImplicit // _defaults.lookup() returning default constructed RWConcern not boost::none. _lookupMock.setLookupCallReturnValue({}); + ASSERT(!isCWWCSet()); auto defaults = getDefault(); ASSERT(!defaults.getDefaultReadConcern()); ASSERT(!defaults.getDefaultWriteConcern()); @@ -124,6 +131,7 @@ TEST_F(ReadWriteConcernDefaultsTest, TestGetDefaultWithCWRWCNeverSetWithImplicit createDefaults(true /* isImplicitWCMajority */); // _defaults.lookup() returning default constructed RWConcern not boost::none. + ASSERT(!isCWWCSet()); _lookupMock.setLookupCallReturnValue({}); auto defaults = getDefault(); ASSERT(!defaults.getDefaultReadConcern()); @@ -143,6 +151,7 @@ TEST_F(ReadWriteConcernDefaultsTest, TestGetDefaultWithUnsetCWRWCWithImplicitWCW newDefaults.setUpdateWallClockTime(Date_t::fromMillisSinceEpoch(1234)); _lookupMock.setLookupCallReturnValue(std::move(newDefaults)); + ASSERT(!isCWWCSet()); auto defaults = getDefault(); ASSERT(!defaults.getDefaultReadConcern()); ASSERT(!defaults.getDefaultWriteConcern()); @@ -166,6 +175,7 @@ TEST_F(ReadWriteConcernDefaultsTest, TestGetDefaultWithUnsetCWRWCWithImplicitWCM newDefaults.setUpdateWallClockTime(Date_t::fromMillisSinceEpoch(1234)); _lookupMock.setLookupCallReturnValue(std::move(newDefaults)); + ASSERT(!isCWWCSet()); auto defaults = getDefault(); ASSERT(!defaults.getDefaultReadConcern()); ASSERT(defaults.getDefaultWriteConcern()); @@ -184,6 +194,8 @@ TEST_F(ReadWriteConcernDefaultsTest, TestGetDefaultWithSetCWRWCWithImplicitWCW1) repl::ReadConcernArgs(repl::ReadConcernLevel::kLocalReadConcern)); WriteConcernOptions wc; wc.wNumNodes = 4; + wc.usedDefault = false; + wc.usedDefaultW = false; newDefaults.setDefaultWriteConcern(wc); newDefaults.setUpdateOpTime(Timestamp(1, 2)); newDefaults.setUpdateWallClockTime(Date_t::fromMillisSinceEpoch(1234)); @@ -192,6 +204,7 @@ TEST_F(ReadWriteConcernDefaultsTest, TestGetDefaultWithSetCWRWCWithImplicitWCW1) } _lookupMock.setLookupCallReturnValue(std::move(newDefaults)); + ASSERT(isCWWCSet()); auto defaults = getDefault(); ASSERT(defaults.getDefaultReadConcern()->getLevel() == repl::ReadConcernLevel::kLocalReadConcern); @@ -226,6 +239,7 @@ TEST_F(ReadWriteConcernDefaultsTest, TestGetDefaultWithSetCWRWCWithImplicitWCMaj } _lookupMock.setLookupCallReturnValue(std::move(newDefaults)); + ASSERT(isCWWCSet()); auto defaults = getDefault(); ASSERT(defaults.getDefaultReadConcern()->getLevel() == repl::ReadConcernLevel::kLocalReadConcern); @@ -246,17 +260,14 @@ TEST_F(ReadWriteConcernDefaultsTest, TestGetDefaultWriteConcernSourceImplicitWit createDefaults(true /* isImplicitWCMajority */); RWConcernDefault newDefaults; - WriteConcernOptions wc; - wc.wNumNodes = 4; - wc.usedDefault = true; - wc.usedDefaultW = false; - newDefaults.setDefaultWriteConcern(wc); + newDefaults.setDefaultWriteConcern(WriteConcernOptions()); newDefaults.setUpdateOpTime(Timestamp(1, 2)); newDefaults.setUpdateWallClockTime(Date_t::fromMillisSinceEpoch(1234)); newDefaults.setDefaultWriteConcernSource(DefaultWriteConcernSourceEnum::kGlobal); _lookupMock.setLookupCallReturnValue(std::move(newDefaults)); + ASSERT(!isCWWCSet()); // The default write concern source should be set to implicit if wc.usedDefault is true auto defaults = getDefault(); ASSERT(!defaults.getDefaultReadConcern()); @@ -279,6 +290,7 @@ TEST_F(ReadWriteConcernDefaultsTest, TestGetDefaultWithSetAndUnSetCWRCWithImplic newDefaults.setUpdateWallClockTime(Date_t::fromMillisSinceEpoch(1234)); _lookupMock.setLookupCallReturnValue(std::move(newDefaults)); + ASSERT(!isCWWCSet()); auto defaults = getDefault(); ASSERT(defaults.getDefaultReadConcern()->getLevel() == repl::ReadConcernLevel::kLocalReadConcern); @@ -298,6 +310,7 @@ TEST_F(ReadWriteConcernDefaultsTest, TestGetDefaultWithSetAndUnSetCWRCWithImplic ReadWriteConcernDefaults::get(getServiceContext()).refreshIfNecessary(_opCtx); + ASSERT(!isCWWCSet()); defaults = getDefault(); ASSERT(!defaults.getDefaultReadConcern()); ASSERT(!defaults.getDefaultWriteConcern()); @@ -324,7 +337,7 @@ TEST_F(ReadWriteConcernDefaultsTest, TestGetDefaultWithSetAndUnSetCWRCWithImplic newDefaults.setUpdateWallClockTime(Date_t::fromMillisSinceEpoch(1234)); _lookupMock.setLookupCallReturnValue(std::move(newDefaults)); - + ASSERT(!isCWWCSet()); auto defaults = getDefault(); ASSERT(defaults.getDefaultReadConcern()->getLevel() == repl::ReadConcernLevel::kLocalReadConcern); @@ -343,6 +356,7 @@ TEST_F(ReadWriteConcernDefaultsTest, TestGetDefaultWithSetAndUnSetCWRCWithImplic ReadWriteConcernDefaults::get(getServiceContext()).refreshIfNecessary(_opCtx); + ASSERT(!isCWWCSet()); defaults = getDefault(); ASSERT(!defaults.getDefaultReadConcern()); ASSERT(defaults.getDefaultWriteConcern()); @@ -358,6 +372,7 @@ TEST_F(ReadWriteConcernDefaultsTest, TestGetDefaultLookupFailure) { createDefaults(true /* isImplicitWCMajority */); _lookupMock.setLookupCallFailure(Status{ErrorCodes::Error(1234), "foobar"}); ASSERT_THROWS_CODE_AND_WHAT(getDefault(), AssertionException, 1234, "foobar"); + ASSERT_THROWS_CODE_AND_WHAT(isCWWCSet(), AssertionException, 1234, "foobar"); } TEST_F(ReadWriteConcernDefaultsTest, TestGetDefaultWithoutInvalidateDoesNotCallLookup) { @@ -368,6 +383,7 @@ TEST_F(ReadWriteConcernDefaultsTest, TestGetDefaultWithoutInvalidateDoesNotCallL newDefaults.setUpdateWallClockTime(Date_t::fromMillisSinceEpoch(1234)); _lookupMock.setLookupCallReturnValue(std::move(newDefaults)); + ASSERT(!isCWWCSet()); auto defaults = getDefault(); ASSERT(!defaults.getDefaultReadConcern()); ASSERT(!defaults.getDefaultWriteConcern()); @@ -383,6 +399,8 @@ TEST_F(ReadWriteConcernDefaultsTest, TestGetDefaultWithoutInvalidateDoesNotCallL repl::ReadConcernArgs(repl::ReadConcernLevel::kLocalReadConcern)); WriteConcernOptions wc; wc.wNumNodes = 4; + wc.usedDefault = false; + wc.usedDefaultW = false; newDefaults2.setDefaultWriteConcern(wc); newDefaults2.setUpdateOpTime(Timestamp(3, 4)); newDefaults2.setUpdateWallClockTime(Date_t::fromMillisSinceEpoch(5678)); @@ -391,6 +409,7 @@ TEST_F(ReadWriteConcernDefaultsTest, TestGetDefaultWithoutInvalidateDoesNotCallL } _lookupMock.setLookupCallReturnValue(std::move(newDefaults2)); + ASSERT(!isCWWCSet()); auto defaults2 = getDefault(); ASSERT(!defaults2.getDefaultReadConcern()); ASSERT(!defaults2.getDefaultWriteConcern()); @@ -411,6 +430,7 @@ TEST_F(ReadWriteConcernDefaultsTest, TestInvalidate) { newDefaults.setUpdateWallClockTime(Date_t::fromMillisSinceEpoch(1234)); _lookupMock.setLookupCallReturnValue(std::move(newDefaults)); + ASSERT(!isCWWCSet()); auto defaults = getDefault(); ASSERT(!defaults.getDefaultReadConcern()); ASSERT(!defaults.getDefaultWriteConcern()); @@ -426,6 +446,8 @@ TEST_F(ReadWriteConcernDefaultsTest, TestInvalidate) { repl::ReadConcernArgs(repl::ReadConcernLevel::kLocalReadConcern)); WriteConcernOptions wc; wc.wNumNodes = 4; + wc.usedDefault = false; + wc.usedDefaultW = false; newDefaults2.setDefaultWriteConcern(wc); newDefaults2.setUpdateOpTime(Timestamp(3, 4)); newDefaults2.setUpdateWallClockTime(Date_t::fromMillisSinceEpoch(5678)); @@ -435,6 +457,7 @@ TEST_F(ReadWriteConcernDefaultsTest, TestInvalidate) { _lookupMock.setLookupCallReturnValue(std::move(newDefaults2)); ReadWriteConcernDefaults::get(getServiceContext()).invalidate(); + ASSERT(isCWWCSet()); auto defaults2 = getDefault(); ASSERT(defaults2.getDefaultReadConcern()->getLevel() == repl::ReadConcernLevel::kLocalReadConcern); @@ -451,6 +474,7 @@ TEST_F(ReadWriteConcernDefaultsTest, TestRefreshDefaultsWithEmptyCacheAndAbsentD createDefaults(false /* isImplicitWCMajority */); ReadWriteConcernDefaults::get(getServiceContext()).refreshIfNecessary(_opCtx); + ASSERT(!isCWWCSet()); auto defaults = getDefault(); ASSERT(!defaults.getDefaultReadConcern()); ASSERT(!defaults.getDefaultWriteConcern()); @@ -472,6 +496,7 @@ TEST_F(ReadWriteConcernDefaultsTest, TestRefreshDefaultsWithEmptyCacheAndSetDefa ReadWriteConcernDefaults::get(getServiceContext()).refreshIfNecessary(_opCtx); + ASSERT(!isCWWCSet()); auto defaults = getDefault(); ASSERT_EQ(Timestamp(1, 2), *defaults.getUpdateOpTime()); ASSERT_EQ(1234, defaults.getUpdateWallClockTime()->toMillisSinceEpoch()); @@ -489,6 +514,7 @@ TEST_F(ReadWriteConcernDefaultsTest, TestRefreshDefaultsWithHigherEpoch) { newDefaults.setUpdateWallClockTime(Date_t::fromMillisSinceEpoch(1234)); _lookupMock.setLookupCallReturnValue(std::move(newDefaults)); + ASSERT(!isCWWCSet()); auto defaults = getDefault(); ASSERT_EQ(Timestamp(1, 2), *defaults.getUpdateOpTime()); ASSERT_EQ(1234, defaults.getUpdateWallClockTime()->toMillisSinceEpoch()); @@ -503,6 +529,7 @@ TEST_F(ReadWriteConcernDefaultsTest, TestRefreshDefaultsWithHigherEpoch) { ReadWriteConcernDefaults::get(getServiceContext()).refreshIfNecessary(_opCtx); + ASSERT(!isCWWCSet()); auto defaults2 = getDefault(); ASSERT_EQ(Timestamp(3, 4), *defaults2.getUpdateOpTime()); ASSERT_EQ(5678, defaults2.getUpdateWallClockTime()->toMillisSinceEpoch()); diff --git a/src/mongo/db/repl/SConscript b/src/mongo/db/repl/SConscript index 67b2c9f9580..eb8ce074e9e 100644 --- a/src/mongo/db/repl/SConscript +++ b/src/mongo/db/repl/SConscript @@ -1686,6 +1686,7 @@ env.CppUnitTest( 'topology_coordinator_v1_test.cpp', ], LIBDEPS=[ + '$BUILD_DIR/mongo/db/read_write_concern_defaults_mock', 'isself', 'repl_coordinator_impl', 'repl_coordinator_test_fixture', diff --git a/src/mongo/db/repl/replication_coordinator_impl.cpp b/src/mongo/db/repl/replication_coordinator_impl.cpp index 0fb1400aafe..80b7a39f614 100644 --- a/src/mongo/db/repl/replication_coordinator_impl.cpp +++ b/src/mongo/db/repl/replication_coordinator_impl.cpp @@ -3451,6 +3451,29 @@ Status ReplicationCoordinatorImpl::_doReplSetReconfig(OperationContext* opCtx, return status; ReplSetConfig newConfig = newConfigStatus.getValue(); + // If the new config changes the replica set's implicit default write concern, we fail the + // reconfig command. This includes force reconfigs, but excludes reconfigs that bump the config + // term during step-up. The user should set a cluster-wide write concern and attempt the + // reconfig command again. We also need to exclude shard servers from this validation, as shard + // servers don't store the cluster-wide write concern. + if (!skipSafetyChecks /* skipping step-up reconfig */ && + repl::feature_flags::gDefaultWCMajority.isEnabled( + serverGlobalParams.featureCompatibility) && + serverGlobalParams.clusterRole != ClusterRole::ShardServer && + !repl::enableDefaultWriteConcernUpdatesForInitiate.load()) { + bool currIDWC = oldConfig.isImplicitDefaultWriteConcernMajority(); + bool newIDWC = newConfig.isImplicitDefaultWriteConcernMajority(); + bool isCWWCSet = ReadWriteConcernDefaults::get(opCtx).isCWWCSet(opCtx); + if (!isCWWCSet && currIDWC != newIDWC) { + return Status( + ErrorCodes::NewReplicaSetConfigurationIncompatible, + str::stream() + << "Reconfig attempted to install a config that would change the " + "implicit default write concern. Use the setDefaultRWConcern command to " + "set a cluster-wide write concern and try the reconfig again."); + } + } + BSONObj oldConfigObj = oldConfig.toBSON(); BSONObj newConfigObj = newConfig.toBSON(); audit::logReplSetReconfig(opCtx->getClient(), &oldConfigObj, &newConfigObj); diff --git a/src/mongo/db/repl/replication_coordinator_impl_reconfig_test.cpp b/src/mongo/db/repl/replication_coordinator_impl_reconfig_test.cpp index b3fb19795f7..4fdb2403540 100644 --- a/src/mongo/db/repl/replication_coordinator_impl_reconfig_test.cpp +++ b/src/mongo/db/repl/replication_coordinator_impl_reconfig_test.cpp @@ -32,6 +32,7 @@ #include "mongo/platform/basic.h" #include "mongo/db/jsobj.h" +#include "mongo/db/read_write_concern_defaults_cache_lookup_mock.h" #include "mongo/db/repl/repl_server_parameters_gen.h" #include "mongo/db/repl/repl_set_config.h" #include "mongo/db/repl/repl_set_heartbeat_args_v1.h" @@ -1953,6 +1954,14 @@ TEST_F(ReplCoordReconfigTest, NodesWithNewlyAddedFieldSetHavePriorityZero) { } TEST_F(ReplCoordReconfigTest, ArbiterNodesShouldNeverHaveNewlyAddedField) { + RWConcernDefault newDefaults; + WriteConcernOptions wc; + wc.wMode = "majority"; + wc.usedDefault = false; + wc.usedDefaultW = false; + newDefaults.setDefaultWriteConcern(wc); + lookupMock.setLookupCallReturnValue(std::move(newDefaults)); + setUpNewlyAddedFieldTest(); auto opCtx = makeOperationContext(); diff --git a/src/mongo/db/repl/replication_coordinator_test_fixture.cpp b/src/mongo/db/repl/replication_coordinator_test_fixture.cpp index 802b4e921fb..2c6a45f4d0a 100644 --- a/src/mongo/db/repl/replication_coordinator_test_fixture.cpp +++ b/src/mongo/db/repl/replication_coordinator_test_fixture.cpp @@ -144,8 +144,7 @@ void ReplCoordTest::init() { // The ReadWriteConcernDefaults decoration on the service context won't always be created, // so we should manually instantiate it to ensure it exists in our tests. - ReadWriteConcernDefaults::create(service, _lookupMock.getFetchDefaultsFn()); - enableDefaultWriteConcernUpdatesForInitiate.store(true); + ReadWriteConcernDefaults::create(service, lookupMock.getFetchDefaultsFn()); TopologyCoordinator::Options settings; auto topo = std::make_unique<TopologyCoordinator>(settings); diff --git a/src/mongo/db/repl/replication_coordinator_test_fixture.h b/src/mongo/db/repl/replication_coordinator_test_fixture.h index 46a81edaff0..4589c82aca5 100644 --- a/src/mongo/db/repl/replication_coordinator_test_fixture.h +++ b/src/mongo/db/repl/replication_coordinator_test_fixture.h @@ -320,6 +320,8 @@ protected: */ void simulateCatchUpAbort(); + ReadWriteConcernDefaultsLookupMock lookupMock; + private: std::unique_ptr<ReplicationCoordinatorImpl> _repl; // Owned by ReplicationCoordinatorImpl @@ -335,8 +337,6 @@ private: ReplSettings _settings; bool _callShutdown = false; - - ReadWriteConcernDefaultsLookupMock _lookupMock; }; } // namespace repl |