1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
|
/**
* Tests that the "shard merge" protocol is enabled only in the proper FCV.
* @tags: [requires_fcv_52, featureFlagShardMerge]
*/
(function() {
"use strict";
load("jstests/replsets/libs/tenant_migration_util.js");
load("jstests/libs/fail_point_util.js");
function runTest(downgradeFCV) {
let rst = new ReplSetTest({nodes: 1});
rst.startSet();
rst.initiate();
let primary = rst.getPrimary();
let adminDB = primary.getDB("admin");
const kDummyConnStr = "mongodb://localhost/?replicaSet=foo";
const readPreference = {mode: 'primary'};
const migrationCertificates = TenantMigrationUtil.makeMigrationCertificatesForTest();
// A function, not a constant, to ensure unique UUIDs.
function donorStartMigrationCmd() {
return {
donorStartMigration: 1,
protocol: "shard merge",
migrationId: UUID(),
recipientConnectionString: kDummyConnStr,
readPreference: readPreference,
donorCertificateForRecipient: migrationCertificates.donorCertificateForRecipient,
recipientCertificateForDonor: migrationCertificates.recipientCertificateForDonor
};
}
function recipientSyncDataCmd() {
return {
recipientSyncData: 1,
protocol: "shard merge",
migrationId: UUID(),
donorConnectionString: kDummyConnStr,
readPreference: readPreference,
startMigrationDonorTimestamp: Timestamp(1, 1),
recipientCertificateForDonor: migrationCertificates.recipientCertificateForDonor
};
}
function recipientForgetMigrationCmd() {
return {
recipientForgetMigration: 1,
protocol: "shard merge",
migrationId: UUID(),
donorConnectionString: kDummyConnStr,
readPreference: readPreference,
recipientCertificateForDonor: migrationCertificates.recipientCertificateForDonor
};
}
function func(cmd) {
return eval(cmd + "Cmd()");
}
function upgradeTest(cmd) {
let msg = cmd + " shouldn't reject 'shard merge' protocol when it's enabled";
assert.commandWorked(adminDB.runCommand(func(cmd)), msg);
}
function downgradeTest(cmd) {
let msg = cmd + " should reject 'shard merge' protocol when it's disabled";
let expectedErrorMsg = "'protocol' field is not supported for FCV below 5.2'";
let response = assert.commandFailedWithCode(
adminDB.runCommand(func(cmd)), ErrorCodes.InvalidOptions, msg);
assert.neq(-1,
response.errmsg.indexOf(expectedErrorMsg),
"Error message did not contain '" + expectedErrorMsg + "', found:\n" +
tojson(response));
}
// Enable below fail points to prevent starting the donor/recipient POS instance.
configureFailPoint(primary, "returnResponseCommittedForDonorStartMigrationCmd");
configureFailPoint(primary, "returnResponseOkForRecipientSyncDataCmd");
configureFailPoint(primary, "returnResponseOkForRecipientForgetMigrationCmd");
// Preconditions: the shard merge feature is enabled and our fresh RS is on the latest FCV.
assert(TenantMigrationUtil.isShardMergeEnabled(adminDB));
assert.eq(getFCVConstants().latest,
adminDB.system.version.findOne({_id: 'featureCompatibilityVersion'}).version);
// Shard merge is enabled, so this call should work.
let cmds = ["donorStartMigration", "recipientSyncData", "recipientForgetMigration"];
cmds.forEach((cmd) => {
upgradeTest(cmd);
});
assert.commandWorked(adminDB.adminCommand({setFeatureCompatibilityVersion: downgradeFCV}));
// Now that FCV is downgraded, shard merge is automatically disabled.
cmds.forEach((cmd) => {
downgradeTest(cmd);
});
rst.stopSet();
}
runFeatureFlagMultiversionTest('featureFlagShardMerge', runTest);
})();
|