114 lines
4.0 KiB
JavaScript
114 lines
4.0 KiB
JavaScript
/**
|
|
* This tests whether slaveOk reads are properly routed through mongos in
|
|
* an authenticated environment. This test also includes restarting the
|
|
* entire set, then querying afterwards.
|
|
*
|
|
* This test involves a full restart of the replica set, so cannot be run with ephemeral storage
|
|
* engines. When all nodes in a replica set are using an ephemeral storage engine, the set cannot
|
|
* recover from a full restart. Once restarted, the nodes will have no knowledge of the replica set
|
|
* config and will be unable to elect a primary.
|
|
* @tags: [requires_persistence]
|
|
*/
|
|
|
|
/**
|
|
* Checks if a query to the given collection will be routed to the secondary.
|
|
*
|
|
* @param {DBCollection} coll
|
|
* @param {Object} query
|
|
*
|
|
* @return {boolean} true if query was routed to a secondary node.
|
|
*/
|
|
function doesRouteToSec( coll, query ) {
|
|
var explain = coll.find( query ).explain();
|
|
assert.eq("SINGLE_SHARD", explain.queryPlanner.winningPlan.stage);
|
|
var serverInfo = explain.queryPlanner.winningPlan.shards[0].serverInfo;
|
|
var conn = new Mongo( serverInfo.host + ":" + serverInfo.port.toString());
|
|
var cmdRes = conn.getDB( 'admin' ).runCommand({ isMaster: 1 });
|
|
|
|
jsTest.log('isMaster: ' + tojson(cmdRes));
|
|
|
|
return cmdRes.secondary;
|
|
}
|
|
|
|
var rsOpts = { oplogSize: 50 };
|
|
var st = new ShardingTest({ keyFile: 'jstests/libs/key1', shards: 1,
|
|
rs: rsOpts, other: { nopreallocj: 1 }});
|
|
|
|
var mongos = st.s;
|
|
var replTest = st.rs0;
|
|
var testDB = mongos.getDB( 'AAAAA' );
|
|
var coll = testDB.user;
|
|
var nodeCount = replTest.nodes.length;
|
|
|
|
/* Add an admin user to the replica member to simulate connecting from
|
|
* remote location. This is because mongod allows unautheticated
|
|
* connections to access the server from localhost connections if there
|
|
* is no admin user.
|
|
*/
|
|
var adminDB = mongos.getDB( 'admin' )
|
|
adminDB.createUser({user: 'user', pwd: 'password', roles: jsTest.adminUserRoles});
|
|
adminDB.auth( 'user', 'password' );
|
|
var priAdminDB = replTest.getPrimary().getDB( 'admin' );
|
|
priAdminDB.createUser({user: 'user', pwd: 'password', roles: jsTest.adminUserRoles},
|
|
{w: 3, wtimeout: 30000});
|
|
|
|
coll.drop();
|
|
coll.setSlaveOk( true );
|
|
|
|
/* Secondaries should be up here, but they can still be in RECOVERY
|
|
* state, which will make the ReplicaSetMonitor mark them as
|
|
* ok = false and not eligible for slaveOk queries.
|
|
*/
|
|
ReplSetTest.awaitRSClientHosts( mongos, replTest.getSecondaries(),
|
|
{ ok : true, secondary : true });
|
|
|
|
var bulk = coll.initializeUnorderedBulkOp();
|
|
for ( var x = 0; x < 20; x++ ) {
|
|
bulk.insert({ v: x, k: 10 });
|
|
}
|
|
assert.writeOK(bulk.execute({ w: nodeCount }));
|
|
|
|
/* Although mongos never caches query results, try to do a different query
|
|
* everytime just to be sure.
|
|
*/
|
|
var vToFind = 0;
|
|
|
|
jsTest.log( 'First query to SEC' );
|
|
assert( doesRouteToSec( coll, { v: vToFind++ }));
|
|
|
|
var SIG_TERM = 15;
|
|
replTest.stopSet( SIG_TERM, true, { auth: { user: 'user', pwd: 'password' }});
|
|
|
|
for ( var n = 0; n < nodeCount; n++ ) {
|
|
replTest.restart( n, rsOpts );
|
|
}
|
|
|
|
replTest.awaitSecondaryNodes();
|
|
|
|
coll.setSlaveOk( true );
|
|
|
|
/* replSetMonitor does not refresh the nodes information when getting secondaries.
|
|
* A node that is previously labeled as secondary can now be a primary, so we
|
|
* wait for the replSetMonitorWatcher thread to refresh the nodes information.
|
|
*/
|
|
ReplSetTest.awaitRSClientHosts( mongos, replTest.getSecondaries(),
|
|
{ ok : true, secondary : true });
|
|
//
|
|
// We also need to wait for the primary, it's possible that the mongos may think a node is a
|
|
// secondary but it actually changed to a primary before we send our final query.
|
|
//
|
|
ReplSetTest.awaitRSClientHosts( mongos, replTest.getPrimary(),
|
|
{ ok : true, ismaster : true });
|
|
|
|
// Recheck if we can still query secondaries after refreshing connections.
|
|
jsTest.log( 'Final query to SEC' );
|
|
assert( doesRouteToSec( coll, { v: vToFind++ }));
|
|
|
|
// Cleanup auth so Windows will be able to shutdown gracefully
|
|
priAdminDB = replTest.getPrimary().getDB( 'admin' );
|
|
priAdminDB.auth( 'user', 'password' );
|
|
priAdminDB.dropUser( 'user' );
|
|
|
|
st.stop();
|
|
|