mirror of https://github.com/mongodb/mongo
171 lines
6.5 KiB
JavaScript
171 lines
6.5 KiB
JavaScript
/**
|
|
* Tests adding standalones and replica sets as shards under a variety of configurations (setName,
|
|
* valid and invalid hosts, shardName matching or not matching a setName, etc).
|
|
*/
|
|
import {ReplSetTest} from "jstests/libs/replsettest.js";
|
|
import {ShardingTest} from "jstests/libs/shardingtest.js";
|
|
import {removeShard} from "jstests/sharding/libs/remove_shard_util.js";
|
|
|
|
// TODO SERVER-50144 Remove this and allow orphan checking.
|
|
// This test calls removeShard which can leave docs in config.rangeDeletions in state "pending",
|
|
// therefore preventing orphans from being cleaned up.
|
|
TestData.skipCheckOrphans = true;
|
|
|
|
let addShardRes;
|
|
|
|
const assertAddShardSucceeded = function (res, shardName) {
|
|
assert.commandWorked(res);
|
|
|
|
// If a shard name was specified, make sure that the name the addShard command reports the
|
|
// shard was added with matches the specified name.
|
|
if (shardName) {
|
|
assert.eq(shardName, res.shardAdded, "name returned by addShard does not match name specified in addShard");
|
|
}
|
|
|
|
// Make sure the shard shows up in config.shards with the shardName reported by the
|
|
// addShard command.
|
|
assert.neq(
|
|
null,
|
|
st.s.getDB("config").shards.findOne({_id: res.shardAdded}),
|
|
"newly added shard " + res.shardAdded + " not found in config.shards",
|
|
);
|
|
};
|
|
|
|
// Note: this method expects that the failure is *not* that the specified shardName is already
|
|
// the shardName of an existing shard.
|
|
const assertAddShardFailed = function (res, shardName) {
|
|
assert.commandFailed(res);
|
|
|
|
// If a shard name was specified in the addShard, make sure no shard with its name shows up
|
|
// in config.shards.
|
|
if (shardName) {
|
|
if (TestData.configShard && shardName === "config") {
|
|
// In config shard mode there's always an entry for config for the config server.
|
|
assert.neq(null, st.s.getDB("config").shards.findOne({_id: shardName}));
|
|
} else {
|
|
assert.eq(
|
|
null,
|
|
st.s.getDB("config").shards.findOne({_id: shardName}),
|
|
"addShard for " + shardName + " reported failure, but shard shows up in config.shards",
|
|
);
|
|
}
|
|
}
|
|
};
|
|
|
|
const st = new ShardingTest({
|
|
shards: TestData.configShard ? 1 : 0,
|
|
mongos: 1,
|
|
});
|
|
|
|
// Add one shard since the last shard cannot be removed.
|
|
const normalShard = new ReplSetTest({name: "add_shard_2-1", nodes: 1, nodeOptions: {shardsvr: ""}});
|
|
normalShard.startSet();
|
|
normalShard.initiate();
|
|
|
|
st.s.adminCommand({addShard: normalShard.getURL(), name: "normalShard"});
|
|
|
|
// Allocate a port that can be used to test adding invalid hosts.
|
|
const portWithoutHostRunning = allocatePort();
|
|
|
|
// 1. Test adding a *replica set* with an ordinary set name
|
|
|
|
// 1.a. with or without specifying the shardName.
|
|
|
|
jsTest.log("Adding a replica set without a specified shardName should succeed.");
|
|
const rst1 = new ReplSetTest({nodes: 1});
|
|
rst1.startSet({shardsvr: ""});
|
|
rst1.initiate();
|
|
addShardRes = st.s.adminCommand({addShard: rst1.getURL()});
|
|
assertAddShardSucceeded(addShardRes);
|
|
assert.eq(rst1.name, addShardRes.shardAdded);
|
|
removeShard(st, addShardRes.shardAdded);
|
|
rst1.stopSet();
|
|
|
|
jsTest.log("Adding a replica set with a specified shardName that matches the set's name should succeed.");
|
|
const rst2 = new ReplSetTest({nodes: 1});
|
|
rst2.startSet({shardsvr: ""});
|
|
rst2.initiate();
|
|
addShardRes = st.s.adminCommand({addShard: rst2.getURL(), name: rst2.name});
|
|
assertAddShardSucceeded(addShardRes, rst2.name);
|
|
removeShard(st, addShardRes.shardAdded);
|
|
rst2.stopSet();
|
|
|
|
let rst3 = new ReplSetTest({nodes: 1});
|
|
rst3.startSet({shardsvr: ""});
|
|
rst3.initiate();
|
|
|
|
jsTest.log("Adding a replica set with a specified shardName that differs from the set's name should succeed.");
|
|
addShardRes = st.s.adminCommand({addShard: rst3.getURL(), name: "differentShardName"});
|
|
assertAddShardSucceeded(addShardRes, "differentShardName");
|
|
removeShard(st, addShardRes.shardAdded);
|
|
|
|
jsTest.log("Adding a replica with a specified shardName of 'config' should fail.");
|
|
addShardRes = st.s.adminCommand({addShard: rst3.getURL(), name: "config"});
|
|
assertAddShardFailed(addShardRes, "config");
|
|
|
|
// 1.b. with invalid hostnames.
|
|
|
|
jsTest.log("Adding a replica set with only non-existing hosts should fail.");
|
|
addShardRes = st.s.adminCommand({addShard: rst3.name + "/NonExistingHost:" + portWithoutHostRunning});
|
|
assertAddShardFailed(addShardRes);
|
|
|
|
jsTest.log("Adding a replica set with mixed existing/non-existing hosts should fail.");
|
|
addShardRes = st.s.adminCommand({
|
|
addShard: rst3.name + "/" + rst3.getPrimary().name + ",NonExistingHost:" + portWithoutHostRunning,
|
|
});
|
|
assertAddShardFailed(addShardRes);
|
|
|
|
rst3.stopSet();
|
|
|
|
// 2. Test adding a replica set whose *set name* is "config" with or without specifying the
|
|
// shardName.
|
|
|
|
let rst4 = new ReplSetTest({name: "config", nodes: 1});
|
|
rst4.startSet({shardsvr: ""});
|
|
rst4.initiate();
|
|
|
|
jsTest.log("Adding a replica set whose setName is config without specifying shardName should fail.");
|
|
addShardRes = st.s.adminCommand({addShard: rst4.getURL()});
|
|
assertAddShardFailed(addShardRes);
|
|
|
|
jsTest.log("Adding a replica set whose setName is config with specified shardName 'config' should fail.");
|
|
addShardRes = st.s.adminCommand({addShard: rst4.getURL(), name: rst4.name});
|
|
assertAddShardFailed(addShardRes, rst4.name);
|
|
|
|
jsTest.log("Adding a replica set whose setName is config with a non-'config' shardName should succeed");
|
|
addShardRes = st.s.adminCommand({addShard: rst4.getURL(), name: "nonConfig"});
|
|
assertAddShardSucceeded(addShardRes, "nonConfig");
|
|
removeShard(st, addShardRes.shardAdded);
|
|
|
|
rst4.stopSet();
|
|
|
|
// 3. Test that a replica set whose *set name* is "admin" can be written to (SERVER-17232).
|
|
|
|
let rst5 = new ReplSetTest({name: "admin", nodes: 1});
|
|
rst5.startSet({shardsvr: ""});
|
|
rst5.initiate();
|
|
|
|
jsTest.log("A replica set whose set name is 'admin' should be able to be written to.");
|
|
|
|
addShardRes = st.s.adminCommand({addShard: rst5.getURL()});
|
|
assertAddShardSucceeded(addShardRes);
|
|
|
|
// Ensure the write goes to the newly added shard.
|
|
assert.commandWorked(st.s.adminCommand({enableSharding: "test", primaryShard: addShardRes.shardAdded}));
|
|
assert.commandWorked(st.s.getDB("test").runCommand({create: "foo"}));
|
|
const res = st.s.getDB("config").getCollection("databases").findOne({_id: "test"});
|
|
assert.neq(null, res);
|
|
assert.eq(res.primary, addShardRes.shardAdded);
|
|
|
|
assert.commandWorked(st.s.getDB("test").foo.insert({x: 1}));
|
|
assert.neq(null, rst5.getPrimary().getDB("test").foo.findOne());
|
|
|
|
assert.commandWorked(st.s.getDB("test").runCommand({dropDatabase: 1}));
|
|
|
|
removeShard(st, addShardRes.shardAdded);
|
|
|
|
rst5.stopSet();
|
|
|
|
st.stop();
|
|
normalShard.stopSet();
|