diff options
author | Matt Broadstone <mbroadst@mongodb.com> | 2022-02-04 13:23:59 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2022-02-04 13:54:45 +0000 |
commit | 2e878f0d1f4234199fe0602878de0ac1ce7aa0cc (patch) | |
tree | 727c8804b0c6258af883f87a6a957eb37275da25 /jstests | |
parent | 08ca09bda76f5d1082b7d8fea5e874c1113a5542 (diff) | |
download | mongo-2e878f0d1f4234199fe0602878de0ac1ce7aa0cc.tar.gz |
SERVER-62482 Build recipient connection string from tag/set name
Diffstat (limited to 'jstests')
-rw-r--r-- | jstests/replsets/shard_split_enabled.js | 58 | ||||
-rw-r--r-- | jstests/replsets/shard_split_test.js | 94 | ||||
-rw-r--r-- | jstests/serverless/libs/basic_serverless_test.js | 55 |
3 files changed, 131 insertions, 76 deletions
diff --git a/jstests/replsets/shard_split_enabled.js b/jstests/replsets/shard_split_enabled.js index ece5f4d2cb1..5047fd8e178 100644 --- a/jstests/replsets/shard_split_enabled.js +++ b/jstests/replsets/shard_split_enabled.js @@ -8,44 +8,45 @@ "use strict"; load("jstests/replsets/libs/tenant_migration_util.js"); +load("jstests/serverless/libs/basic_serverless_test.js"); + +class ShardSplitEnabledTest extends BasicServerlessTest { + makeCommitShardSplitCmd() { + return { + commitShardSplit: 1, + tenantIds: ["foo"], + migrationId: UUID(), + recipientTagName: this.recipientTagName, + recipientSetName: this.recipientSetName + }; + } + + makeAbortShardSplitCmd() { + return {abortShardSplit: 1, migrationId: UUID()}; + } +} -const kDummyConnStr = "mongodb://localhost/?replicaSet=foo"; function makeShardSplitTest() { return function(downgradeFCV) { - function commitShardSplitCmd(recipientConnectionString) { - return { - commitShardSplit: 1, - tenantIds: ["foo"], - migrationId: UUID(), - recipientConnectionString - }; - } - function abortShardSplitCmd() { - return {abortShardSplit: 1, migrationId: UUID()}; - } + const test = new ShardSplitEnabledTest( + {recipientTagName: "recipientNode", recipientSetName: "recipient"}); + test.addRecipientNodes(); - // start up a replica set for the recipient - const recipientRst = new ReplSetTest({name: "recipientRst", nodes: 1}); - recipientRst.startSet(); - recipientRst.initiate(); + const donorPrimary = test.donor.getPrimary(); + const adminDB = donorPrimary.getDB("admin"); - // start up a replica set - // server-side setup - const donorRst = new ReplSetTest({name: "donorRst", nodes: 1}); - donorRst.startSet(); - donorRst.initiate(); - const primary = donorRst.getPrimary(); - const adminDB = primary.getDB("admin"); + // TODO(SERVER-63091): remove this when we actually split recipients + configureFailPoint(adminDB, "skipShardSplitWaitForSplitAcceptance"); assert(TenantMigrationUtil.isShardSplitEnabled(adminDB)); assert.eq(getFCVConstants().latest, adminDB.system.version.findOne({_id: 'featureCompatibilityVersion'}).version); - let res = adminDB.runCommand(commitShardSplitCmd(recipientRst.getURL())); + let res = adminDB.runCommand(test.makeCommitShardSplitCmd()); assert.neq(res.code, 6057900, `commitShardSplitCmd shouldn't reject when featureFlagShardSplit is enabled`); - res = adminDB.runCommand(abortShardSplitCmd()); + res = adminDB.runCommand(test.makeAbortShardSplitCmd()); assert.neq(res.code, 6057902, `abortShardSplitCmd shouldn't reject when featureFlagShardSplit is enabled`); @@ -53,17 +54,16 @@ function makeShardSplitTest() { assert.commandWorked(adminDB.adminCommand({setFeatureCompatibilityVersion: downgradeFCV})); assert.commandFailedWithCode( - adminDB.runCommand(commitShardSplitCmd(recipientRst.getURL())), + adminDB.runCommand(test.makeCommitShardSplitCmd()), 6057900, `commitShardSplitCmd should reject when featureFlagShardSplit is disabled`); assert.commandFailedWithCode( - adminDB.runCommand(abortShardSplitCmd()), + adminDB.runCommand(test.makeAbortShardSplitCmd()), 6057902, `abortShardSplitCmd should reject when featureFlagShardSplit is disabled`); // shut down replica sets - donorRst.stopSet(); - recipientRst.stopSet(); + test.stop(); }; } diff --git a/jstests/replsets/shard_split_test.js b/jstests/replsets/shard_split_test.js index 902d66a7918..22302965367 100644 --- a/jstests/replsets/shard_split_test.js +++ b/jstests/replsets/shard_split_test.js @@ -5,6 +5,7 @@ load("jstests/libs/fail_point_util.js"); load('jstests/libs/parallel_shell_helpers.js'); +load("jstests/serverless/libs/basic_serverless_test.js"); const kMaxTimeMS = 1 * 1000; @@ -19,16 +20,6 @@ function assertDocumentState(primary, uuid, state) { assert.eq(migrationDoc.state, state); } -function startReplica(name, numNodes) { - const replTest = new ReplSetTest({name, nodes: numNodes}); - - jsTestLog("Starting replica set for test"); - const donorNodes = replTest.startSet(); - replTest.initiate(); - - return replTest; -} - function runAbort() { "use strict"; @@ -37,21 +28,24 @@ function runAbort() { // Skip db hash check because secondary is left with a different config. TestData.skipCheckDBHashes = true; - const donorSet = startReplica("donorSet", 3); - const primary = donorSet.getPrimary(); - const adminDb = primary.getDB("admin"); + const test = + new BasicServerlessTest({recipientTagName: "recipientNode", recipientSetName: "recipient"}); + test.addRecipientNodes(); + + const donorPrimary = test.donor.getPrimary(); + const adminDb = donorPrimary.getDB("admin"); const migrationId = UUID(); jsTestLog("Asserting no state document exist before command"); - assert.isnull(findMigration(primary, migrationId)); + assert.isnull(findMigration(donorPrimary, migrationId)); jsTestLog("Running abortShardSplit command"); - assert.commandWorked(adminDb.runCommand({abortShardSplit: 1, migrationId: migrationId})); + assert.commandWorked(adminDb.runCommand({abortShardSplit: 1, migrationId})); jsTestLog("Asserting state document exist after command"); - assertDocumentState(primary, migrationId, "aborted"); + assertDocumentState(donorPrimary, migrationId, "aborted"); - donorSet.stopSet(); + test.stop(); } function runBlocking() { @@ -62,65 +56,71 @@ function runBlocking() { // Skip db hash check because secondary is left with a different config. TestData.skipCheckDBHashes = true; - const donorSet = startReplica("donorSet", 3); - const recipientSet = startReplica("recipientSet", 3); - const primary = donorSet.getPrimary(); - const adminDb = primary.getDB("admin"); - const migrationId = UUID(); + const test = + new BasicServerlessTest({recipientTagName: "recipientNode", recipientSetName: "recipient"}); + test.addRecipientNodes(); - const tenantId1 = "test_tenant_1"; - const tenantId2 = "test_tenant_2"; - const tenants = [tenantId1, tenantId2]; + const donorPrimary = test.donor.getPrimary(); + const migrationId = UUID(); + const tenantIds = ["test_tenant_1", "test_tenant_2"]; jsTestLog("Asserting no state document exist before command"); - assert.isnull(findMigration(primary, migrationId)); + assert.isnull(findMigration(donorPrimary, migrationId)); jsTestLog("Asserting we can write before the migration"); - tenants.forEach(id => { - const tenantDB = primary.getDB(id + "_data"); + tenantIds.forEach(id => { + const tenantDB = donorPrimary.getDB(id + "_data"); let insertedObj = {name: id + "1", payload: "testing_data"}; assert.commandWorked(tenantDB.runCommand( {insert: "testing_collection", documents: [insertedObj], maxTimeMS: kMaxTimeMS})); }); - jsTestLog("Inserting failpoint after blocking"); - let blockingFailPoint = configureFailPoint(adminDb, "pauseShardSplitAfterBlocking"); + // configure failpoints + const adminDb = donorPrimary.getDB("admin"); + const blockingFailPoint = configureFailPoint(adminDb, "pauseShardSplitAfterBlocking"); + + // TODO(SERVER-63091): remove this when we actually split recipients + configureFailPoint(adminDb, "skipShardSplitWaitForSplitAcceptance"); jsTestLog("Running commitShardSplit command"); const awaitCommand = startParallelShell( - funWithArgs(function(migrationId, url, tenants) { - assert.commandWorked(db.adminCommand({ - commitShardSplit: 1, - migrationId: migrationId, - recipientConnectionString: url, - "tenantIds": tenants - })); - }, migrationId, recipientSet.getURL(), [tenantId1, tenantId2]), donorSet.getPrimary().port); + funWithArgs( + function(migrationId, recipientTagName, recipientSetName, tenantIds) { + assert.commandWorked(db.adminCommand({ + commitShardSplit: 1, + migrationId, + recipientTagName, + recipientSetName, + tenantIds + })); + }, + migrationId, + test.recipientTagName, + test.recipientSetName, + tenantIds), + donorPrimary.port); blockingFailPoint.wait(); jsTestLog("Asserting state document is in blocking state"); - assertDocumentState(primary, migrationId, "blocking"); + assertDocumentState(donorPrimary, migrationId, "blocking"); jsTestLog("Asserting we cannot write in blocking state"); - tenants.forEach(id => { - const tenantDB = primary.getDB(id + "_data"); + tenantIds.forEach(id => { + const tenantDB = donorPrimary.getDB(id + "_data"); let insertedObj = {name: id + "2", payload: "testing_data2"}; let res = tenantDB.runCommand( {insert: "testing_collection", documents: [insertedObj], maxTimeMS: kMaxTimeMS}); assert.commandFailedWithCode(res, ErrorCodes.MaxTimeMSExpired); }); + jsTestLog("Disabling failpoints and waiting for command to complete"); blockingFailPoint.off(); awaitCommand(); jsTestLog("Asserting state document exist after command"); - assertDocumentState(primary, migrationId, "committed"); - - // If we validate, it will try to list all collections and the migrated collections will return - // a TenantMigrationCommitted error. - donorSet.stopSet(undefined /* signal */, false /* forRestart */, {skipValidation: 1}); - recipientSet.stopSet(); + assertDocumentState(donorPrimary, migrationId, "committed"); + test.stop(); } runAbort(); diff --git a/jstests/serverless/libs/basic_serverless_test.js b/jstests/serverless/libs/basic_serverless_test.js new file mode 100644 index 00000000000..b19c95ec0cb --- /dev/null +++ b/jstests/serverless/libs/basic_serverless_test.js @@ -0,0 +1,55 @@ +class BasicServerlessTest { + constructor({recipientTagName, recipientSetName}) { + this.donor = new ReplSetTest({name: "donor", nodes: 3}); + this.donor.startSet(); + this.donor.initiate(); + + this.recipientTagName = recipientTagName; + this.recipientSetName = recipientSetName; + this.recipientNodes = []; + } + + stop() { + // If we validate, it will try to list all collections and the migrated collections will + // return a TenantMigrationCommitted error. + this.donor.stopSet(undefined /* signal */, false /* forRestart */, {skipValidation: 1}); + } + + addRecipientNodes(numNodes) { + numNodes = numNodes || 3; // default to three nodes + + if (this.recipientNodes.lengh > 0) { + throw new Error("Recipient nodes may only be added once"); + } + + jsTestLog(`Adding ${numNodes} non-voting recipient nodes to donor`); + const donor = this.donor; + for (let i = 0; i < numNodes; ++i) { + this.recipientNodes.push(donor.add()); + } + + const primary = donor.getPrimary(); + const admin = primary.getDB('admin'); + const config = donor.getReplSetConfigFromNode(); + config.version++; + + // ensure recipient nodes are added as non-voting members + this.recipientNodes.forEach(node => { + config.members.push({ + host: node.host, + votes: 0, + priority: 0, + tags: {[this.recipientTagName]: ObjectId().valueOf()} + }); + }); + + // reindex all members from 0 + config.members = config.members.map((member, idx) => { + member._id = idx; + return member; + }); + + assert.commandWorked(admin.runCommand({replSetReconfig: config})); + this.recipientNodes.forEach(node => donor.waitForState(node, ReplSetTest.State.SECONDARY)); + } +} |