summaryrefslogtreecommitdiff
path: root/jstests
diff options
context:
space:
mode:
authorXiangyu Yao <xiangyu.yao@mongodb.com>2018-08-23 15:54:59 -0400
committerXiangyu Yao <xiangyu.yao@mongodb.com>2018-10-05 16:10:38 -0400
commit13e13e9ba8a720b0ee95b70c62e59a712af52ac8 (patch)
tree1a9ed6fcae2a44979913e40fd4011b4a59f40ddb /jstests
parent5849932e9f4ce4c2bef9046fbaa21f3465e3d1eb (diff)
downloadmongo-13e13e9ba8a720b0ee95b70c62e59a712af52ac8.tar.gz
SERVER-36718 Add forceValidationWithFeatureCompatibilityVersion to collection validation hook
(cherry picked from commit bdb7951bc48accda8368f5893bdf2627fc2588bf)
Diffstat (limited to 'jstests')
-rw-r--r--jstests/hooks/run_validate_collections.js58
-rw-r--r--jstests/hooks/validate_collections.js54
-rw-r--r--jstests/libs/discover_topology.js34
3 files changed, 88 insertions, 58 deletions
diff --git a/jstests/hooks/run_validate_collections.js b/jstests/hooks/run_validate_collections.js
index 525003148e1..e0292740b97 100644
--- a/jstests/hooks/run_validate_collections.js
+++ b/jstests/hooks/run_validate_collections.js
@@ -10,11 +10,14 @@
const topology = DiscoverTopology.findConnectedNodes(db.getMongo());
const hostList = [];
+ let setFCVHost;
if (topology.type === Topology.kStandalone) {
hostList.push(topology.mongod);
+ setFCVHost = topology.mongod;
} else if (topology.type === Topology.kReplicaSet) {
hostList.push(...topology.nodes);
+ setFCVHost = topology.primary;
} else if (topology.type === Topology.kShardedCluster) {
hostList.push(...topology.configsvr.nodes);
@@ -29,6 +32,8 @@
throw new Error('Unrecognized topology format: ' + tojson(topology));
}
}
+ // Any of the mongos instances can be used for setting FCV.
+ setFCVHost = topology.mongos.nodes[0];
} else {
throw new Error('Unrecognized topology format: ' + tojson(topology));
}
@@ -44,6 +49,18 @@
conn.setSlaveOk();
jsTest.authenticate(conn);
+ if (jsTest.options().forceValidationWithFeatureCompatibilityVersion) {
+ let adminDB = conn.getDB('admin');
+ // Make sure this node has the desired FCV.
+ assert.soon(() => {
+ const res =
+ adminDB.system.version.findOne({_id: "featureCompatibilityVersion"});
+ return res !== null &&
+ res.version ===
+ jsTest.options().forceValidationWithFeatureCompatibilityVersion;
+ });
+ }
+
const dbNames = conn.getDBNames();
for (let dbName of dbNames) {
if (!validateCollections(conn.getDB(dbName), {full: true})) {
@@ -61,6 +78,43 @@
// We run the scoped threads in a try/finally block in case any thread throws an exception, in
// which case we want to still join all the threads.
let threads = [];
+ let adminDB;
+ let originalFCV;
+
+ function getFeatureCompatibilityVersion(adminDB) {
+ const res = adminDB.system.version.findOne({_id: "featureCompatibilityVersion"});
+ if (res === null) {
+ return "3.2";
+ }
+ return res.version;
+ }
+
+ if (jsTest.options().forceValidationWithFeatureCompatibilityVersion) {
+ let conn = new Mongo(setFCVHost);
+ adminDB = conn.getDB('admin');
+ try {
+ originalFCV = getFeatureCompatibilityVersion(adminDB);
+ } catch (e) {
+ if (jsTest.options().skipValidationOnInvalidViewDefinitions &&
+ e.code === ErrorCodes.InvalidViewDefinition) {
+ print("Reading the featureCompatibilityVersion from the admin.system.version" +
+ " collection failed due to an invalid view definition on the admin database");
+ // The view catalog would only have been resolved if the namespace doesn't exist as
+ // a collection. The absence of the admin.system.version collection is equivalent to
+ // having featureCompatibilityVersion=3.2.
+ originalFCV = "3.2";
+ } else {
+ throw e;
+ }
+ }
+
+ if (originalFCV !== jsTest.options().forceValidationWithFeatureCompatibilityVersion) {
+ assert.commandWorked(adminDB.adminCommand({
+ setFeatureCompatibilityVersion:
+ jsTest.options().forceValidationWithFeatureCompatibilityVersion
+ }));
+ }
+ }
try {
hostList.forEach(host => {
@@ -79,4 +133,8 @@
assert.commandWorked(res, 'Collection validation failed');
});
}
+
+ if (jsTest.options().forceValidationWithFeatureCompatibilityVersion !== originalFCV) {
+ assert.commandWorked(adminDB.runCommand({setFeatureCompatibilityVersion: originalFCV}));
+ }
})();
diff --git a/jstests/hooks/validate_collections.js b/jstests/hooks/validate_collections.js
index c5be1a230e8..8287388b6c9 100644
--- a/jstests/hooks/validate_collections.js
+++ b/jstests/hooks/validate_collections.js
@@ -13,19 +13,6 @@ function validateCollections(db, obj) {
}
}
- function getFeatureCompatibilityVersion(adminDB) {
- var res = adminDB.system.version.findOne({_id: "featureCompatibilityVersion"});
- if (res === null) {
- return "3.2";
- }
- return res.version;
- }
-
- function setFeatureCompatibilityVersion(adminDB, version) {
- assert.commandWorked(adminDB.runCommand({setFeatureCompatibilityVersion: version}));
- assert.eq(version, getFeatureCompatibilityVersion(adminDB));
- }
-
assert.eq(typeof db, 'object', 'Invalid `db` object, is the shell connected to a mongod?');
assert.eq(typeof obj, 'object', 'The `obj` argument must be an object');
assert(obj.hasOwnProperty('full'), 'Please specify whether to use full validation');
@@ -34,42 +21,6 @@ function validateCollections(db, obj) {
var success = true;
- var adminDB = db.getSiblingDB("admin");
-
- // Set the featureCompatibilityVersion to its required value for performing validation. Save the
- // original value.
- var originalFeatureCompatibilityVersion;
- if (jsTest.options().forceValidationWithFeatureCompatibilityVersion) {
- try {
- originalFeatureCompatibilityVersion = getFeatureCompatibilityVersion(adminDB);
- } catch (e) {
- if (jsTest.options().skipValidationOnInvalidViewDefinitions &&
- e.code === ErrorCodes.InvalidViewDefinition) {
- print("Reading the featureCompatibilityVersion from the admin.system.version" +
- " collection failed due to an invalid view definition on the admin database");
- // The view catalog would only have been resolved if the namespace doesn't exist as
- // a collection. The absence of the admin.system.version collection is equivalent to
- // having featureCompatibilityVersion=3.2.
- originalFeatureCompatibilityVersion = "3.2";
- } else {
- throw e;
- }
- }
-
- try {
- setFeatureCompatibilityVersion(
- adminDB, jsTest.options().forceValidationWithFeatureCompatibilityVersion);
- } catch (e) {
- if (e.code === ErrorCodes.NotMaster) {
- print('Skipping collection validation on ' + db.getMongo() + ' because the' +
- ' featureCompatibilityVersion cannot be changed while connected to a' +
- ' secondary');
- return true;
- }
- throw e;
- }
- }
-
// Don't run validate on view namespaces.
let filter = {type: "collection"};
if (jsTest.options().skipValidationOnInvalidViewDefinitions) {
@@ -108,10 +59,5 @@ function validateCollections(db, obj) {
}
}
- // Restore the original value for featureCompatibilityVersion.
- if (jsTest.options().forceValidationWithFeatureCompatibilityVersion) {
- setFeatureCompatibilityVersion(adminDB, originalFeatureCompatibilityVersion);
- }
-
return success;
}
diff --git a/jstests/libs/discover_topology.js b/jstests/libs/discover_topology.js
index 95b072894b0..175f5831eaf 100644
--- a/jstests/libs/discover_topology.js
+++ b/jstests/libs/discover_topology.js
@@ -4,6 +4,7 @@
// Symbol type, so we just use unique string values instead.
var Topology = {
kStandalone: 'stand-alone',
+ kRouter: 'mongos router',
kReplicaSet: 'replica set',
kShardedCluster: 'sharded cluster',
};
@@ -22,7 +23,11 @@ var DiscoverTopology = (function() {
// The "passives" field contains the list of unelectable (priority=0) secondaries
// and is omitted from the server's response when there are none.
res.passives = res.passives || [];
- return {type: Topology.kReplicaSet, nodes: [...res.hosts, ...res.passives]};
+ return {
+ type: Topology.kReplicaSet,
+ primary: res.primary,
+ nodes: [...res.hosts, ...res.passives]
+ };
}
function findConnectedNodesViaMongos(conn, options) {
@@ -58,7 +63,22 @@ var DiscoverTopology = (function() {
shardHosts[shardInfo._id] = getDataMemberConnectionStrings(shardConn);
}
- return {type: Topology.kShardedCluster, configsvr: configsvrHosts, shards: shardHosts};
+ // Discover mongos URIs from the connection string. If a mongos is not passed in explicitly,
+ // it will not be discovered. Prior to the changes from SERVER-28560 and SERVER-31061, only
+ // one mongos URI could be present in the connection string.
+ const mongosUris = new MongoURI("mongodb://" + conn.host);
+
+ const mongos = {
+ type: Topology.kRouter,
+ nodes: mongosUris.servers.map(uriObj => uriObj.server),
+ };
+
+ return {
+ type: Topology.kShardedCluster,
+ configsvr: configsvrHosts,
+ shards: shardHosts,
+ mongos: mongos,
+ };
}
return {
@@ -72,7 +92,11 @@ var DiscoverTopology = (function() {
* is returned.
*
* For a replica set, an object of the form
- * {type: Topology.kReplicaSet, nodes: [<conn-string1>, <conn-string2>, ...]}
+ * {
+ * type: Topology.kReplicaSet,
+ * primary: <primary-conn-string>,
+ * nodes: [<conn-string1>, <conn-string2>, ...],
+ * }
* is returned.
*
* For a sharded cluster, an object of the form
@@ -81,7 +105,9 @@ var DiscoverTopology = (function() {
* configsvr: {nodes: [...]},
* shards: {
* <shard-name1>: {type: Topology.kStandalone, mongod: ...},
- * <shard-name2>: {type: Topology.kReplicaSet, nodes: [...]},
+ * <shard-name2>: {type: Topology.kReplicaSet,
+ * primary: <primary-conn-string>,
+ * nodes: [...]},
* ...
* }
* }