mirror of https://github.com/mongodb/mongo
399 lines
14 KiB
JavaScript
399 lines
14 KiB
JavaScript
/**
|
|
* Test dropDatabase command in a sharded cluster.
|
|
*/
|
|
|
|
import {ShardingTest} from "jstests/libs/shardingtest.js";
|
|
|
|
let st = new ShardingTest({shards: 2});
|
|
|
|
let configDB = st.s.getDB("config");
|
|
const dbNamePrefix = "testDropDB";
|
|
let dbCounter = 0;
|
|
|
|
function getNewDb() {
|
|
return st.s.getDB(dbNamePrefix + "_" + dbCounter++);
|
|
}
|
|
|
|
function getPrefixRegExp(prefix) {
|
|
return RegExp("^" + RegExp.escape(prefix) + ".*");
|
|
}
|
|
|
|
function getDbPrefixRegExp(dbName) {
|
|
return getPrefixRegExp(dbName + ".");
|
|
}
|
|
|
|
function listDatabases(options) {
|
|
return assert.commandWorked(st.s.adminCommand(Object.assign({listDatabases: 1}, options))).databases;
|
|
}
|
|
|
|
function assertDatabaseExists(dbName) {
|
|
// Check that listDatabase return the db
|
|
assert.gte(1, listDatabases({nameOnly: true, filter: {name: dbName}}).length);
|
|
// Database entry exists
|
|
assert.eq(1, configDB.databases.countDocuments({_id: dbName}));
|
|
}
|
|
|
|
function assertDatabaseDropped(dbName) {
|
|
// Check that listDatabase doesn't return the db
|
|
assert.eq(0, listDatabases({nameOnly: true, filter: {name: dbName}}).length);
|
|
// No more database entry
|
|
assert.eq(0, configDB.databases.countDocuments({_id: dbName}));
|
|
// No more tags for this database
|
|
assert.eq(0, configDB.tags.countDocuments({ns: getDbPrefixRegExp(dbName)}));
|
|
|
|
// Check dropped collections.
|
|
assert.eq(0, configDB.collections.countDocuments({_id: getDbPrefixRegExp(dbName)}));
|
|
}
|
|
|
|
jsTest.log("Test that dropping admin/config DB is illegal");
|
|
{
|
|
assert.commandFailedWithCode(st.s.getDB("admin").dropDatabase(), ErrorCodes.IllegalOperation);
|
|
assert.commandFailedWithCode(st.s.getDB("config").dropDatabase(), ErrorCodes.IllegalOperation);
|
|
}
|
|
|
|
jsTest.log("Test dropping unexistent database");
|
|
{
|
|
const db = getNewDb();
|
|
// Dropping a database that doesn't exist will result in an info field in the response.
|
|
const res = assert.commandWorked(db.dropDatabase());
|
|
assertDatabaseDropped(db.getName());
|
|
}
|
|
|
|
jsTest.log("Test dropping unsharded database");
|
|
{
|
|
const db = getNewDb();
|
|
// Create the database
|
|
assert.commandWorked(db.foo.insert({}));
|
|
assertDatabaseExists(db.getName());
|
|
// Drop the database
|
|
assert.commandWorked(db.dropDatabase());
|
|
assertDatabaseDropped(db.getName());
|
|
|
|
// Test drop database idempotency
|
|
assert.commandWorked(db.dropDatabase());
|
|
assertDatabaseDropped(db.getName());
|
|
}
|
|
|
|
jsTest.log("Test dropping unsharded database with multiple collections");
|
|
{
|
|
const db = getNewDb();
|
|
// Create 3 unsharded collection
|
|
const colls = Array.from({length: 3}, (_, i) => db["unshardedColl_" + i]);
|
|
colls.forEach((coll) => coll.insert({}));
|
|
|
|
// Create the database
|
|
assertDatabaseExists(db.getName());
|
|
// Drop the database
|
|
assert.commandWorked(db.dropDatabase());
|
|
assertDatabaseDropped(db.getName());
|
|
}
|
|
|
|
jsTest.log("Test dropping sharded database");
|
|
{
|
|
const db = getNewDb();
|
|
// Create the database
|
|
st.s.adminCommand({enableSharding: db.getName()});
|
|
assertDatabaseExists(db.getName());
|
|
// Drop the database
|
|
assert.commandWorked(db.dropDatabase());
|
|
assertDatabaseDropped(db.getName());
|
|
|
|
// Test drop database idempotency
|
|
assert.commandWorked(db.dropDatabase());
|
|
assertDatabaseDropped(db.getName());
|
|
}
|
|
|
|
jsTest.log("Test dropping database that contains regex characters");
|
|
// Original bugs [SERVER-4954, SERVER-4955]
|
|
{
|
|
const db = st.s.getDB("onlysmallcaseletters");
|
|
assert.commandWorked(st.s.adminCommand({enablesharding: db.getName(), primaryShard: st.shard1.shardName}));
|
|
st.shardColl(db["data"], {num: 1});
|
|
assertDatabaseExists(db.getName());
|
|
|
|
const specialDB = st.s.getDB("[a-z]+");
|
|
const specialColl = db["special"];
|
|
assert.commandWorked(st.s.adminCommand({enablesharding: specialDB.getName(), primaryShard: st.shard0.shardName}));
|
|
assertDatabaseExists(specialDB.getName());
|
|
st.shardColl(specialColl, {num: 1});
|
|
assert(specialColl.exists());
|
|
|
|
// Drop special database
|
|
assert.commandWorked(specialDB.dropDatabase());
|
|
assertDatabaseDropped(specialDB.getName());
|
|
|
|
// The normal database still exists
|
|
assertDatabaseExists(db.getName());
|
|
|
|
// Drop also the normal database
|
|
assert.commandWorked(db.dropDatabase());
|
|
assertDatabaseDropped(db.getName());
|
|
}
|
|
|
|
jsTest.log("Test dropping sharded database with multiple collections");
|
|
{
|
|
const db = getNewDb();
|
|
const unshardedColls = Array.from({length: 3}, (_, i) => db["unshardedColl_" + i]);
|
|
unshardedColls.forEach((coll) => coll.insert({}));
|
|
const shardedColls = Array.from({length: 3}, (_, i) => db["shardedColl_" + i]);
|
|
shardedColls.forEach((coll) => st.shardColl(coll, {_id: 1}));
|
|
// Create the database
|
|
st.s.adminCommand({enableSharding: db.getName()});
|
|
assertDatabaseExists(db.getName());
|
|
// Drop the database
|
|
assert.commandWorked(db.dropDatabase());
|
|
assertDatabaseDropped(db.getName());
|
|
}
|
|
|
|
jsTest.log("Tests that dropping a database also removes the zones associated with the collections in the database.");
|
|
{
|
|
const db = getNewDb();
|
|
const coll = db["sharededColl"];
|
|
const zoneName = "zone";
|
|
|
|
assert.commandWorked(st.s.adminCommand({addShardToZone: st.shard0.shardName, zone: zoneName}));
|
|
st.shardColl(coll, {x: 1});
|
|
assertDatabaseExists(db.getName());
|
|
assert.commandWorked(
|
|
st.s.adminCommand({updateZoneKeyRange: coll.getFullName(), min: {x: 0}, max: {x: 10}, zone: zoneName}),
|
|
);
|
|
|
|
assert.eq(1, configDB.tags.countDocuments({ns: getDbPrefixRegExp(db.getName())}));
|
|
|
|
// Drop the database
|
|
assert.commandWorked(db.dropDatabase());
|
|
assertDatabaseDropped(db.getName());
|
|
}
|
|
|
|
{
|
|
const db = getNewDb();
|
|
const conn = st.rs0.getPrimary().getDB(db.getName());
|
|
const fcvDoc = conn.adminCommand({getParameter: 1, featureCompatibilityVersion: 1});
|
|
if (MongoRunner.compareBinVersions(fcvDoc.featureCompatibilityVersion.version, "6.3") >= 0) {
|
|
jsTest.log(
|
|
"Tests that dropping a database also removes all associated zones for nonexisting and " +
|
|
"unsharded collections.",
|
|
);
|
|
{
|
|
const coll = db["shardedColl"];
|
|
const unshardedColl = db["unshardedColl"];
|
|
const zoneName = "zone";
|
|
|
|
st.shardColl(coll, {x: 1});
|
|
assertDatabaseExists(db.getName());
|
|
|
|
// Create an unsharded collection
|
|
assert.commandWorked(unshardedColl.insert({x: 3}));
|
|
|
|
// Append zones for a sharded collection, unsharded collection, a nonexisting collection
|
|
// and a collection from another database.
|
|
st.addShardTag(st.shard0.shardName, zoneName);
|
|
assert.commandWorked(
|
|
st.s.adminCommand({
|
|
updateZoneKeyRange: coll.getFullName(),
|
|
min: {x: 0},
|
|
max: {x: 10},
|
|
zone: zoneName,
|
|
}),
|
|
);
|
|
assert.commandWorked(
|
|
st.s.adminCommand({
|
|
updateZoneKeyRange: unshardedColl.getFullName(),
|
|
min: {x: 10},
|
|
max: {x: 15},
|
|
zone: zoneName,
|
|
}),
|
|
);
|
|
assert.commandWorked(
|
|
st.s.adminCommand({
|
|
updateZoneKeyRange: db.getName() + ".nonexisting",
|
|
min: {x: 15},
|
|
max: {x: 20},
|
|
zone: zoneName,
|
|
}),
|
|
);
|
|
assert.commandWorked(
|
|
st.s.adminCommand({updateZoneKeyRange: "otherDb.coll", min: {x: 20}, max: {x: 25}, zone: zoneName}),
|
|
);
|
|
|
|
// Assert that has been added some entries on 'config.tags'
|
|
assert.eq(3, configDB.tags.countDocuments({ns: getDbPrefixRegExp(db.getName())}));
|
|
|
|
// Drop the database
|
|
assert.commandWorked(db.dropDatabase());
|
|
assertDatabaseDropped(db.getName());
|
|
|
|
// Assert that there are no zones left for database
|
|
assert.eq(0, configDB.tags.countDocuments({ns: getDbPrefixRegExp(db.getName())}));
|
|
|
|
// Assert that there is one zone from another database that has not been deleted.
|
|
assert.eq(1, configDB.tags.countDocuments({ns: getDbPrefixRegExp("otherDb")}));
|
|
}
|
|
}
|
|
}
|
|
|
|
{
|
|
const db = st.s.getDB("db[a-z]+");
|
|
const conn = st.rs0.getPrimary().getDB(db.getName());
|
|
const fcvDoc = conn.adminCommand({getParameter: 1, featureCompatibilityVersion: 1});
|
|
if (MongoRunner.compareBinVersions(fcvDoc.featureCompatibilityVersion.version, "6.3") >= 0) {
|
|
jsTest.log(
|
|
"Tests that dropping a database with regex characters also removes all associated " +
|
|
"zones for nonexisting and unsharded collections.",
|
|
);
|
|
{
|
|
const coll = db["shardedColl"];
|
|
const unshardedColl = db["unshardedColl"];
|
|
const zoneName = "zone";
|
|
|
|
st.shardColl(coll, {x: 1});
|
|
assertDatabaseExists(db.getName());
|
|
|
|
// Create an unsharded collection
|
|
assert.commandWorked(unshardedColl.insert({x: 3}));
|
|
|
|
// Append zones for a sharded collection, unsharded collection, a nonexisting collection
|
|
// and a collection from another database.
|
|
st.addShardTag(st.shard0.shardName, zoneName);
|
|
assert.commandWorked(
|
|
st.s.adminCommand({
|
|
updateZoneKeyRange: coll.getFullName(),
|
|
min: {x: 0},
|
|
max: {x: 10},
|
|
zone: zoneName,
|
|
}),
|
|
);
|
|
assert.commandWorked(
|
|
st.s.adminCommand({
|
|
updateZoneKeyRange: unshardedColl.getFullName(),
|
|
min: {x: 10},
|
|
max: {x: 15},
|
|
zone: zoneName,
|
|
}),
|
|
);
|
|
assert.commandWorked(
|
|
st.s.adminCommand({
|
|
updateZoneKeyRange: db.getName() + ".nonexisting",
|
|
min: {x: 15},
|
|
max: {x: 20},
|
|
zone: zoneName,
|
|
}),
|
|
);
|
|
assert.commandWorked(
|
|
st.s.adminCommand({
|
|
updateZoneKeyRange: "otherDbRegex.coll",
|
|
min: {x: 20},
|
|
max: {x: 25},
|
|
zone: zoneName,
|
|
}),
|
|
);
|
|
|
|
// Assert that has been added some entries on 'config.tags'
|
|
assert.eq(3, configDB.tags.countDocuments({ns: getDbPrefixRegExp(db.getName())}));
|
|
|
|
// Drop the database
|
|
assert.commandWorked(db.dropDatabase());
|
|
assertDatabaseDropped(db.getName());
|
|
|
|
// Assert that there are no zones left for database
|
|
assert.eq(0, configDB.tags.countDocuments({ns: getDbPrefixRegExp(db.getName())}));
|
|
|
|
// Assert that there is one zone from another database that has not been deleted.
|
|
assert.eq(1, configDB.tags.countDocuments({ns: getDbPrefixRegExp("otherDbRegex")}));
|
|
}
|
|
}
|
|
}
|
|
|
|
jsTest.log("Tests that dropping a database doesn't affects other database with the same prefix.");
|
|
// Original bug SERVER-3471
|
|
{
|
|
// Create 3 DBs
|
|
// - SomePrefix
|
|
// - SomePrefix_A
|
|
// - SomePrefix_b
|
|
const dbPrefix = dbNamePrefix + "Prefix";
|
|
const databases = [st.s.getDB(dbPrefix), st.s.getDB(dbPrefix + "_A"), st.s.getDB(dbPrefix + "_B")];
|
|
// Assert all database have the same prefix
|
|
assert.containsPrefix(
|
|
dbNamePrefix,
|
|
databases.map((db) => db.getName()),
|
|
);
|
|
|
|
const collPrefix = "coll_";
|
|
const numColls = 3;
|
|
const numDocs = 3;
|
|
|
|
// Create 3 colls with 3 documents on each database
|
|
databases.forEach((db) => {
|
|
for (let collID = 0; collID < numColls; collID++) {
|
|
let coll = db[collPrefix + collID];
|
|
// Create 3 documents for each collection
|
|
for (let docID = 0; docID < numDocs; docID++) {
|
|
coll.insert({_id: docID});
|
|
}
|
|
// shard the collection
|
|
st.shardColl(coll, {_id: 1});
|
|
}
|
|
assertDatabaseExists(db.getName());
|
|
});
|
|
|
|
// Insert a document to an unsharded collection and make sure that the document is there.
|
|
const unshardedColl = databases[0]["unshardedColl"];
|
|
assert.commandWorked(unshardedColl.insert({dummy: 1}));
|
|
assert.eq(1, unshardedColl.countDocuments({dummy: 1}));
|
|
|
|
// Drop the non-suffixed db
|
|
assert.commandWorked(databases[0].dropDatabase());
|
|
assertDatabaseDropped(databases[0].getName());
|
|
assert.eq(0, unshardedColl.countDocuments({}));
|
|
|
|
// Ensure that the others databases exists and still contains all the collections
|
|
databases.slice(1).forEach((db) => {
|
|
assertDatabaseExists(db.getName());
|
|
assert.eq(numColls, configDB.collections.countDocuments({_id: getDbPrefixRegExp(db.getName())}));
|
|
|
|
// Assert that all the collections still have all the documents
|
|
for (let collID = 0; collID < numColls; collID++) {
|
|
assert.eq(numDocs, db[collPrefix + collID].countDocuments({}));
|
|
}
|
|
});
|
|
}
|
|
|
|
jsTest.log("Test that dropping a non-sharded database, relevant events are properly logged on CSRS");
|
|
{
|
|
// Create a non-sharded database
|
|
const db = getNewDb();
|
|
assert.commandWorked(db.foo.insert({}));
|
|
|
|
// Drop the database
|
|
assert.commandWorked(db.dropDatabase());
|
|
|
|
// Verify that the drop database start event has been logged
|
|
const startLogCount = configDB.changelog.countDocuments({what: "dropDatabase.start", ns: db.getName()});
|
|
assert.gte(startLogCount, 1, "dropDatabase start event not found in changelog");
|
|
|
|
// Verify that the drop database end event has been logged
|
|
const endLogCount = configDB.changelog.countDocuments({what: "dropDatabase", ns: db.getName()});
|
|
assert.gte(endLogCount, 1, "dropDatabase end event not found in changelog");
|
|
}
|
|
|
|
jsTest.log("Test that dropping a sharded database, relevant events are properly logged on CSRS");
|
|
{
|
|
// Create a sharded database
|
|
const db = getNewDb();
|
|
st.s.adminCommand({enableSharding: db.getName()});
|
|
|
|
// Drop the database
|
|
assert.commandWorked(db.dropDatabase());
|
|
|
|
// Verify that the drop database start event has been logged
|
|
const startLogCount = configDB.changelog.countDocuments({what: "dropDatabase.start", ns: db.getName()});
|
|
assert.gte(startLogCount, 1, "dropDatabase start event not found in changelog");
|
|
|
|
// Verify that the drop database end event has been logged
|
|
const endLogCount = configDB.changelog.countDocuments({what: "dropDatabase", ns: db.getName()});
|
|
assert.gte(endLogCount, 1, "dropDatabase end event not found in changelog");
|
|
}
|
|
|
|
st.stop();
|