mirror of https://github.com/mongodb/mongo
285 lines
10 KiB
JavaScript
285 lines
10 KiB
JavaScript
// Check that the output from printShardingStatus() (aka sh.status())
|
|
// contains important information that it should, like the major section
|
|
// headings and the names of sharded collections and their shard keys.
|
|
|
|
import {ShardingTest} from "jstests/libs/shardingtest.js";
|
|
|
|
const MONGOS_COUNT = 2;
|
|
|
|
let st = new ShardingTest({shards: 1, mongos: MONGOS_COUNT});
|
|
|
|
let standalone = MongoRunner.runMongod();
|
|
|
|
let mongos = st.s0;
|
|
let admin = mongos.getDB("admin");
|
|
|
|
// Wait for the background thread from the mongos to insert their entries before beginning
|
|
// the tests.
|
|
assert.soon(function () {
|
|
return MONGOS_COUNT == mongos.getDB("config").mongos.count();
|
|
});
|
|
|
|
function grabStatusOutput(configdb, verbose) {
|
|
let res = print.captureAllOutput(function () {
|
|
return printShardingStatus(configdb, verbose);
|
|
});
|
|
let output = res.output.join("\n");
|
|
jsTestLog(output);
|
|
return output;
|
|
}
|
|
|
|
function assertPresentInOutput(output, content, what) {
|
|
assert(
|
|
output.includes(content),
|
|
what + ' "' + content + '" NOT present in output of ' + "printShardingStatus() (but it should be)",
|
|
);
|
|
}
|
|
|
|
function assertNotPresentInOutput(output, content, what) {
|
|
assert(
|
|
!output.includes(content),
|
|
what + ' "' + content + '" IS present in output of ' + "printShardingStatus() (but it should not be)",
|
|
);
|
|
}
|
|
|
|
////////////////////////
|
|
// Basic tests
|
|
////////////////////////
|
|
|
|
let dbName = "thisIsTheDatabase";
|
|
let collName = "thisIsTheCollection";
|
|
let shardKeyName = "thisIsTheShardKey";
|
|
let nsName = dbName + "." + collName;
|
|
|
|
assert.commandWorked(admin.runCommand({enableSharding: dbName}));
|
|
let key = {};
|
|
key[shardKeyName] = 1;
|
|
assert.commandWorked(admin.runCommand({shardCollection: nsName, key: key}));
|
|
|
|
function testBasic(output) {
|
|
assertPresentInOutput(output, "shards:", "section header");
|
|
assertPresentInOutput(output, "databases:", "section header");
|
|
assertPresentInOutput(output, "balancer:", "section header");
|
|
assertPresentInOutput(output, "active mongoses:", "section header");
|
|
assertNotPresentInOutput(output, "most recently active mongoses:", "section header");
|
|
|
|
assertPresentInOutput(output, dbName, "database");
|
|
assertPresentInOutput(output, collName, "collection");
|
|
assertPresentInOutput(output, shardKeyName, "shard key");
|
|
}
|
|
|
|
function testBasicNormalOnly(output) {
|
|
assertPresentInOutput(output, tojson(version) + " : 2\n", "active mongos version");
|
|
}
|
|
|
|
function testBasicVerboseOnly(output) {
|
|
assertPresentInOutput(output, '"mongoVersion" : ' + tojson(version), "active mongos version");
|
|
assertPresentInOutput(output, '"_id" : ' + tojson(s1Host), "active mongos hostname");
|
|
assertPresentInOutput(output, '"_id" : ' + tojson(s2Host), "active mongos hostname");
|
|
}
|
|
|
|
let buildinfo = assert.commandWorked(mongos.adminCommand("buildinfo"));
|
|
let serverStatus1 = assert.commandWorked(mongos.adminCommand("serverStatus"));
|
|
let serverStatus2 = assert.commandWorked(st.s1.adminCommand("serverStatus"));
|
|
var version = buildinfo.version;
|
|
var s1Host = serverStatus1.host;
|
|
var s2Host = serverStatus2.host;
|
|
|
|
// Normal, active mongoses
|
|
let outputNormal = grabStatusOutput(st.config, false);
|
|
testBasic(outputNormal);
|
|
testBasicNormalOnly(outputNormal);
|
|
|
|
let outputVerbose = grabStatusOutput(st.config, true);
|
|
testBasic(outputVerbose);
|
|
testBasicVerboseOnly(outputVerbose);
|
|
|
|
// Take a copy of the config db, in order to test the harder-to-setup cases below.
|
|
// Copy into a standalone to also test running printShardingStatus() against a config dump.
|
|
let config = mongos.getDB("config");
|
|
let configCopy = standalone.getDB("configCopy");
|
|
config.getCollectionInfos().forEach(function (c) {
|
|
// It's illegal to copy the system collections.
|
|
if (
|
|
[
|
|
"system.indexBuilds",
|
|
"system.preimages",
|
|
"system.change_collection",
|
|
"cache.chunks.config.system.sessions",
|
|
"system.sessions",
|
|
"system.sharding_ddl_coordinators",
|
|
].includes(c.name)
|
|
) {
|
|
return;
|
|
}
|
|
|
|
// Create collection with options.
|
|
assert.commandWorked(configCopy.createCollection(c.name, c.options));
|
|
// Clone the docs.
|
|
config
|
|
.getCollection(c.name)
|
|
.find()
|
|
.hint({_id: 1})
|
|
.forEach(function (d) {
|
|
assert.commandWorked(configCopy.getCollection(c.name).insert(d));
|
|
});
|
|
// Build the indexes.
|
|
config
|
|
.getCollection(c.name)
|
|
.getIndexes()
|
|
.forEach(function (i) {
|
|
let key = i.key;
|
|
delete i.key;
|
|
delete i.ns;
|
|
delete i.v;
|
|
assert.commandWorked(configCopy.getCollection(c.name).createIndex(key, i));
|
|
});
|
|
});
|
|
|
|
// Inactive mongoses
|
|
// Make the first ping be older than now by 1 second more than the threshold
|
|
// Make the second ping be older still by the same amount again
|
|
let pingAdjustMs = 60000 + 1000;
|
|
let then = new Date();
|
|
then.setTime(then.getTime() - pingAdjustMs);
|
|
configCopy.mongos.update({_id: s1Host}, {$set: {ping: then}});
|
|
then.setTime(then.getTime() - pingAdjustMs);
|
|
configCopy.mongos.update({_id: s2Host}, {$set: {ping: then}});
|
|
|
|
let output = grabStatusOutput(configCopy, false);
|
|
assertPresentInOutput(output, "most recently active mongoses:", "section header");
|
|
assertPresentInOutput(output, tojson(version) + " : 1\n", "recent mongos version");
|
|
|
|
output = grabStatusOutput(configCopy, true);
|
|
assertPresentInOutput(output, "most recently active mongoses:", "section header");
|
|
assertPresentInOutput(output, '"_id" : ' + tojson(s1Host), "recent mongos hostname");
|
|
assertNotPresentInOutput(output, '"_id" : ' + tojson(s2Host), "old mongos hostname");
|
|
|
|
// Older mongoses
|
|
configCopy.mongos.remove({_id: s1Host});
|
|
|
|
output = grabStatusOutput(configCopy, false);
|
|
assertPresentInOutput(output, "most recently active mongoses:", "section header");
|
|
assertPresentInOutput(output, tojson(version) + " : 1\n", "recent mongos version");
|
|
|
|
output = grabStatusOutput(configCopy, true);
|
|
assertPresentInOutput(output, "most recently active mongoses:", "section header");
|
|
assertNotPresentInOutput(output, '"_id" : ' + tojson(s1Host), "removed mongos hostname");
|
|
assertPresentInOutput(output, '"_id" : ' + tojson(s2Host), "recent mongos hostname");
|
|
|
|
// No mongoses at all
|
|
configCopy.mongos.remove({});
|
|
|
|
output = grabStatusOutput(configCopy, false);
|
|
assertPresentInOutput(output, "most recently active mongoses:\n none", "no mongoses");
|
|
|
|
output = grabStatusOutput(configCopy, true);
|
|
assertPresentInOutput(output, "most recently active mongoses:\n none", "no mongoses (verbose)");
|
|
|
|
assert(mongos.getDB(dbName).dropDatabase());
|
|
|
|
////////////////////////
|
|
// Extended tests
|
|
////////////////////////
|
|
|
|
let testCollDetailsNum = 0;
|
|
function testCollDetails(args) {
|
|
if (args === undefined || typeof args != "object") {
|
|
args = {};
|
|
}
|
|
|
|
let getCollName = function (x) {
|
|
return "test.test" + x.zeroPad(4);
|
|
};
|
|
let collName = getCollName(testCollDetailsNum);
|
|
|
|
let cmdObj = {shardCollection: collName, key: {_id: 1}};
|
|
if (args.unique) {
|
|
cmdObj.unique = true;
|
|
}
|
|
assert.commandWorked(admin.runCommand(cmdObj));
|
|
|
|
let originalValues = {};
|
|
if (args.hasOwnProperty("unique")) {
|
|
originalValues["unique"] = mongos.getDB("config").collections.findOne({_id: collName}).unique;
|
|
assert.commandWorked(
|
|
mongos.getDB("config").collections.update({_id: collName}, {$set: {"unique": args.unique}}),
|
|
);
|
|
}
|
|
if (args.hasOwnProperty("noBalance")) {
|
|
originalValues["noBalance"] = mongos.getDB("config").collections.findOne({_id: collName}).noBalance;
|
|
assert.commandWorked(
|
|
mongos.getDB("config").collections.update({_id: collName}, {$set: {"noBalance": args.noBalance}}),
|
|
);
|
|
}
|
|
|
|
let output = grabStatusOutput(st.config);
|
|
|
|
assertPresentInOutput(output, collName, "collection");
|
|
|
|
// If any of the previous collection names are present, then their optional indicators
|
|
// might also be present. This might taint the results when we go searching through
|
|
// the output.
|
|
// This also means that earlier collNames can't be a prefix of later collNames.
|
|
for (let i = 0; i < testCollDetailsNum; i++) {
|
|
assertNotPresentInOutput(output, getCollName(i), "previous collection");
|
|
}
|
|
|
|
assertPresentInOutput(output, "unique: " + !!args.unique, "unique shard key indicator");
|
|
|
|
if (args.hasOwnProperty("unique") && typeof args.unique != "boolean") {
|
|
// non-bool: actual value must be shown
|
|
assertPresentInOutput(output, tojson(args.unique), "unique shard key indicator (non bool)");
|
|
|
|
// Restore original value.
|
|
assert.commandWorked(
|
|
mongos.getDB("config").collections.update({_id: collName}, {$set: {"unique": originalValues.unique}}),
|
|
);
|
|
}
|
|
|
|
assertPresentInOutput(output, "balancing: " + !args.noBalance, "balancing indicator (inverse of noBalance)");
|
|
if (args.hasOwnProperty("noBalance") && typeof args.noBalance != "boolean") {
|
|
// non-bool: actual value must be shown
|
|
assertPresentInOutput(output, tojson(args.noBalance), "noBalance indicator (non bool)");
|
|
|
|
// Restore original value.
|
|
assert.commandWorked(
|
|
mongos.getDB("config").collections.update({_id: collName}, {$set: {"noBalance": originalValues.noBalance}}),
|
|
);
|
|
}
|
|
|
|
try {
|
|
mongos.getCollection(collName).drop();
|
|
} catch (e) {
|
|
// Ignore drop errors because they are from the illegal values in the collection entry
|
|
assert.commandWorked(mongos.getDB("config").collections.remove({_id: collName}));
|
|
}
|
|
|
|
testCollDetailsNum++;
|
|
}
|
|
|
|
assert.commandWorked(admin.runCommand({enableSharding: "test"}));
|
|
|
|
// Defaults
|
|
testCollDetails({});
|
|
|
|
// Expected values
|
|
testCollDetails({unique: false, noBalance: false});
|
|
testCollDetails({unique: true, noBalance: true});
|
|
|
|
// Unexpected truthy values
|
|
testCollDetails({unique: "truthy unique value 1", noBalance: "truthy noBalance value 1"});
|
|
testCollDetails({unique: 1, noBalance: 1});
|
|
testCollDetails({unique: -1, noBalance: -1});
|
|
testCollDetails({unique: {}, noBalance: {}});
|
|
|
|
// Unexpected falsy values
|
|
testCollDetails({unique: "", noBalance: ""});
|
|
testCollDetails({unique: 0, noBalance: 0});
|
|
|
|
assert(mongos.getDB("test").dropDatabase());
|
|
|
|
MongoRunner.stopMongod(standalone);
|
|
|
|
st.stop();
|