summaryrefslogtreecommitdiff
path: root/jstests/noPassthrough/reconfig_for_psa_set_shell.js
diff options
context:
space:
mode:
authorXueruiFa <xuerui.fa@mongodb.com>2021-05-13 20:39:09 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-05-19 15:02:34 +0000
commit3192123cbc96d4c8121bd9849e70fd8b79eb37a9 (patch)
treee408fdb7593666f365655bc4660e02e892d8e574 /jstests/noPassthrough/reconfig_for_psa_set_shell.js
parent31f3ac2f55f528581cdd0ceb993ec514009a7088 (diff)
downloadmongo-3192123cbc96d4c8121bd9849e70fd8b79eb37a9.tar.gz
SERVER-56919: Add validation for memberIndex to reconfigToPSASet() shell helper
Diffstat (limited to 'jstests/noPassthrough/reconfig_for_psa_set_shell.js')
-rw-r--r--jstests/noPassthrough/reconfig_for_psa_set_shell.js104
1 files changed, 93 insertions, 11 deletions
diff --git a/jstests/noPassthrough/reconfig_for_psa_set_shell.js b/jstests/noPassthrough/reconfig_for_psa_set_shell.js
index 2b0ba125432..79e149d1156 100644
--- a/jstests/noPassthrough/reconfig_for_psa_set_shell.js
+++ b/jstests/noPassthrough/reconfig_for_psa_set_shell.js
@@ -19,24 +19,106 @@ rst.initiateWithHighElectionTimeout();
const primary = rst.getPrimary();
assert.eq(primary, rst.nodes[0], "the primary should be the node at index 0");
-// Verify that a reconfig that directly gives the secondary 'votes: 1' and 'priority: 1' will fail.
-const config = rst.getReplSetConfigFromNode();
+// Store the old config so that we can reset to it after every successful reconfig.
+const originalConfig = rst.getReplSetConfigFromNode();
+
+// Verify that directly calling the standard 'rs.reconfig()' function to give the secondary 'votes:
+// 1' and 'priority: 1' will fail.
+let config = rst.getReplSetConfigFromNode();
config.members[1].votes = 1;
config.members[1].priority = 1;
-let reconfigScript = `assert.commandFailedWithCode(rs.reconfig(${
+jsTestLog("Testing standard rs.reconfig() function");
+const reconfigScript = `assert.commandFailedWithCode(rs.reconfig(${
tojson(config)}), ErrorCodes.NewReplicaSetConfigurationIncompatible)`;
-let result = runMongoProgram('mongo', '--port', primary.port, '--eval', reconfigScript);
+const result = runMongoProgram('mongo', '--port', primary.port, '--eval', reconfigScript);
assert.eq(0, result, `reconfig did not fail with expected error code`);
-// Verify that calling 'reconfigForPSASet()' will succeed.
-reconfigScript = `assert.commandWorked(rs.reconfigForPSASet(1, ${tojson(config)}))`;
-result = runMongoProgram('mongo', '--port', primary.port, '--eval', reconfigScript);
-assert.eq(0, result, `reconfig did not succeed as expected`);
+const runReconfigForPSASet = (memberIndex, config, shouldSucceed, endPriority = 1) => {
+ jsTestLog(`Testing with memberIndex ${memberIndex} and config ${tojson(config)}`);
+
+ const reconfigScript =
+ `assert.commandWorked(rs.reconfigForPSASet(${memberIndex}, ${tojson(config)}))`;
+ const result = runMongoProgram('mongo', '--port', primary.port, '--eval', reconfigScript);
+ if (shouldSucceed) {
+ assert.eq(0, result, 'expected reconfigToPSASet to succeed, but it failed');
+
+ const replSetGetConfig =
+ assert.commandWorked(primary.adminCommand({replSetGetConfig: 1})).config;
+ assert.eq(1, replSetGetConfig.members[1].votes);
+ assert.eq(endPriority, replSetGetConfig.members[1].priority);
+
+ // Reset the config back to the original config.
+ originalConfig.members[memberIndex].votes = 0;
+ originalConfig.members[memberIndex].priority = 0;
+ const reconfigToOriginalConfig =
+ `assert.commandWorked(rs.reconfig(${tojson(originalConfig)}))`;
+ assert.eq(
+ 0,
+ runMongoProgram('mongo', '--port', primary.port, '--eval', reconfigToOriginalConfig));
+ } else {
+ assert.neq(0, result, 'expected reconfigToPSASet to fail, but it succeeded');
+ }
+};
+
+// Succeed with a reconfig to a standard PSA set, where the secondary has 'votes: 1' and 'priority:
+// 1'.
+jsTestLog("Testing reconfigForPSASet() succeeded: standard PSA set");
+runReconfigForPSASet(1, config, true /* shouldSucceed */);
+
+// Fail when 'memberIndex' does not refer to a node in the new config.
+jsTestLog("Testing reconfigForPSASet() failed: memberIndex out of bounds");
+runReconfigForPSASet(3, config, false /* shouldSucceed */);
+
+// Fail when the node in the new config at 'memberIndex' is not a voter.
+jsTestLog("Testing reconfigForPSASet() failed: node at memberIndex is not a voter");
+config.members[1].votes = 0;
+config.members[1].priority = 0;
+runReconfigForPSASet(1, config, false /* shouldSucceed */);
+
+// Test that reconfigToPSASet() will succeed when we are adding a new node at a specific
+// 'memberIndex'.
+jsTestLog("Testing reconfigForPSASet() succeeded: adding new node");
+
+// First remove the node at index 1 to simulate a two-node replica set.
+config = rst.getReplSetConfigFromNode();
+const filteredMembers = config.members.filter(member => member._id !== 1);
+config.members = filteredMembers;
+config.version += 1;
+assert.commandWorked(primary.adminCommand({replSetReconfig: config}));
-const replSetGetConfig = assert.commandWorked(primary.adminCommand({replSetGetConfig: 1})).config;
-assert.eq(1, replSetGetConfig.members[1].votes);
-assert.eq(1, replSetGetConfig.members[1].priority);
+// Attempt to add a node and assert that the reconfigToPSASet() call is successful.
+config.members = originalConfig.members;
+config.members[1].votes = 1;
+config.members[1].priority = 1;
+config.version += 1;
+runReconfigForPSASet(1, config, true /* shouldSucceed */);
+
+// Test that reconfigToPSASet() will succeed even if the priority of the node is 0 in the final
+// config.
+jsTestLog("Testing reconfigForPSASet() succeeded: priority of node is 0 in final config");
+config = rst.getReplSetConfigFromNode();
+config.members[1].votes = 1;
+config.members[1].priority = 0;
+runReconfigForPSASet(1, config, true /* shouldSucceed */, 0 /* endPriority */);
+
+// Test that reconfigToPSASet() will fail if the node at 'memberIndex' exists in the old config but
+// was a voter. It should fail because this is not the use case of the helper function.
+jsTestLog("Testing reconfigForPSASet() failed: node at memberIndex was a voter in old config");
+
+// First turn the secondary into a voting node but with priority 0.
+config = rst.getReplSetConfigFromNode();
+config.members[1].votes = 1;
+config.members[1].priority = 0;
+config.version += 1;
+assert.commandWorked(primary.adminCommand({replSetReconfig: config}));
+
+// Now attempt a reconfig to give the secondary priority 1 via the reconfigForPSASet() function.
+// This should fail because this function should not be used if the secondary is a voter in the old
+// config.
+config.members[1].priority = 1;
+config.version += 1;
+runReconfigForPSASet(1, config, false /* shouldSucceed */);
rst.stopSet();
})();