def test_tagging(self): if SERVER_VERSION < (2, 2, 0): raise SkipTest( "mongodb v{version} doesn't support shard tagging".format( version='.'.join(map(str, SERVER_VERSION)))) tags = ['tag1', 'tag2'] tags_repl = ['replTag'] config = { 'configsvrs': [{}], 'routers': [{}], 'shards': [{ 'id': 'sh01', 'shardParams': { 'tags': tags } }, { 'id': 'sh02' }, { 'id': 'sh03', 'shardParams': { 'tags': tags_repl, 'members': [{}, {}] } }] } self.sh = ShardedCluster(config) self.assertEqual(tags, self.sh.member_info('sh01')['tags']) self.assertEqual([], self.sh.member_info('sh02')['tags']) self.assertEqual(tags_repl, self.sh.member_info('sh03')['tags']) self.sh.cleanup()
def test_ssl(self): config = { 'configsvrs': [{}], 'routers': [{}], 'shards': [{}, { 'shardParams': { 'members': [{}] } }], 'sslParams': { 'sslCAFile': certificate('ca.pem'), 'sslPEMKeyFile': certificate('server.pem'), 'sslMode': 'requireSSL', 'sslClusterFile': certificate('cluster_cert.pem'), 'sslAllowInvalidCertificates': True } } # Should not raise an Exception. self.sh = ShardedCluster(config) # Server should require SSL. host = self.sh.router['hostname'] with self.assertRaises(pymongo.errors.ConnectionFailure): connected(pymongo.MongoClient(host)) # This shouldn't raise. connected( pymongo.MongoClient(host, ssl_certfile=certificate('client.pem'), ssl_cert_reqs=ssl.CERT_NONE))
def test_reset(self): all_hosts = [] # Start a ShardedCluster with 1 router and 1 config server. self.sh = ShardedCluster({}) # Add 1 Server shard and 1 ReplicaSet shard. server_id = self.sh.member_add(params={})['_id'] all_hosts.append(Servers().hostname(server_id)) repl_id = self.sh.member_add(params={'members': [{}, {}, {}]})['_id'] # Shut down the standalone. Servers().command(server_id, 'stop') # Shut down each member of the replica set. server_ids = [m['server_id'] for m in ReplicaSets().members(repl_id)] for s_id in server_ids: Servers().command(s_id, 'stop') all_hosts.append(Servers().hostname(s_id)) # Shut down config server and router. config_id = self.sh.configsvrs[0]['id'] print("config_id=%r" % config_id) all_hosts.append(Servers().hostname(config_id)) router_id = self.sh.routers[0]['id'] print("router_id=%r" % router_id) all_hosts.append(Servers().hostname(router_id)) Servers().command(config_id, 'stop') Servers().command(router_id, 'stop') # Reset the ShardedCluster. self.sh.reset() # Everything is up. for host in all_hosts: # No ConnectionFailure/AutoReconnect. pymongo.MongoClient(host)
def test_member_remove(self): config = {'shards': [{'id': 'member1'}, {'id': 'member2'}, {'id': 'sh-rs-01', 'shardParams': {'id': 'rs1', 'members': [{}, {}]}}]} self.sh = ShardedCluster(config) self.assertEqual(len(self.sh.members), 3) # remove member-host result = self.sh.member_remove('member1') self.assertEqual(len(self.sh.members), 3) self.assertEqual(result['state'], 'started') self.assertEqual(result['shard'], 'member1') time.sleep(5) result = self.sh.member_remove('member1') self.assertEqual(result['state'], 'completed') self.assertEqual(len(self.sh.members), 2) self.assertEqual(result['shard'], 'member1') # remove member-replicaset result = self.sh.member_remove('sh-rs-01') self.assertEqual(len(self.sh.members), 2) self.assertEqual(result['state'], 'started') self.assertEqual(result['shard'], 'sh-rs-01') time.sleep(7) result = self.sh.member_remove('sh-rs-01') self.assertEqual(result['state'], 'completed') self.assertEqual(len(self.sh.members), 1) self.assertEqual(result['shard'], 'sh-rs-01') self.sh.cleanup()
def test_member_info_with_auth(self): config = { 'auth_key': 'secret', 'login': '******', 'password': '******', 'shards': [{ 'id': 'member1' }, { 'id': 'sh-rs-01', 'shardParams': { 'id': 'rs1', 'members': [{}, {}] } }] } self.sh = ShardedCluster(config) info = self.sh.member_info('member1') self.assertEqual(info['id'], 'member1') self.assertTrue(info['isServer']) self.assertTrue('_id' in info) info = self.sh.member_info('sh-rs-01') self.assertEqual(info['id'], 'sh-rs-01') self.assertTrue(info['isReplicaSet']) self.assertTrue('_id' in info) self.sh.cleanup()
def test_auth_key_without_login(self): self.sh = ShardedCluster({ 'auth_key': 'secret', 'routers': [{}], 'shards': [{}] }) self.assertIsNotNone(self.sh.key_file)
def test_cleanup(self): config = { 'id': 'shard_cluster_1', 'configsvrs': [{}], 'routers': [{}], 'shards': [ { 'id': 'sh01' }, { 'id': 'sh02' }, { 'id': 'sh-rs-01', 'shardParams': { 'id': 'rs1', 'members': [{}, {}] } }, ] } self.sh = ShardedCluster(config) self.assertTrue(len(self.sh) == len(config['shards'])) self.sh.cleanup() self.assertTrue(len(self.sh) == 0)
def test_sh_new_with_auth(self): port = PortPool().port(check=True) config = { 'id': 'shard_cluster_1', 'auth_key': 'secret', 'login': '******', 'password': '******', 'configsvrs': [{}], 'routers': [{ "port": port }], 'shards': [{ 'id': 'sh01' }, { 'id': 'sh02' }] } self.sh = ShardedCluster(config) c = pymongo.MongoClient(self.sh.router['hostname']) self.assertRaises(pymongo.errors.OperationFailure, c.admin.command, "listShards") c.admin.authenticate('admin', 'adminpass') self.assertTrue(isinstance(c.admin.command("listShards"), dict)) for item in c.admin.command("listShards")['shards']: self.assertTrue(item['_id'] in ('sh01', 'sh02'))
def test_router_add(self): config = {} self.sh = ShardedCluster(config) self.assertEqual(len(self.sh.routers), 1) self.sh.router_add({}) self.assertEqual(len(self.sh.routers), 2) self.sh.router_add({}) self.assertEqual(len(self.sh.routers), 3) self.sh.cleanup()
def test_routers(self): config = {} self.sh = ShardedCluster(config) self.assertEqual(len(self.sh.routers), 1) self.sh.cleanup() config = {'routers': [{}, {}, {}]} self.sh = ShardedCluster(config) self.assertEqual(len(self.sh.routers), 3) self.sh.cleanup()
def test_members(self): config = {} self.sh = ShardedCluster(config) self.assertEqual(len(self.sh.members), 0) self.sh.cleanup() config = {'shards': [{}, {}, {}]} self.sh = ShardedCluster(config) self.assertEqual(len(self.sh.members), 3) self.sh.cleanup()
def test_len(self): config = {} self.sh = ShardedCluster(config) self.assertEqual(len(self.sh), 0) self.sh.member_add('test01', {}) self.assertEqual(len(self.sh), 1) self.sh.member_add('test02', {}) self.assertEqual(len(self.sh), 2) while self.sh.member_remove('test01')['state'] != 'completed': time.sleep(1) self.assertEqual(len(self.sh), 1)
def test_sh_new(self): port = PortPool().port(check=True) config = { 'id': 'shard_cluster_1', 'configsvrs': [{}], 'routers': [{"port": port}], 'shards': [{'id': 'sh01'}, {'id': 'sh02'}] } self.sh = ShardedCluster(config) c = pymongo.MongoClient(self.sh.router['hostname']) for item in c.admin.command("listShards")['shards']: self.assertTrue(item['_id'] in ('sh01', 'sh02'))
def test_operations(self): config = {'shards': [{}, {}, {}]} cluster = ShardedCluster(config) self.assertEqual(len(self.sh), 0) operator.setitem(self.sh, 1, cluster) self.assertEqual(len(self.sh), 1) self.assertEqual(operator.getitem(self.sh, 1)['id'], cluster.id) operator.delitem(self.sh, 1) self.assertEqual(len(self.sh), 0) self.assertRaises(KeyError, operator.getitem, self.sh, 1) cluster.cleanup()
def test_mongodb_auth_uri(self): self.sh = ShardedCluster({ 'login': '******', 'password': '******', 'routers': [{}, {}], 'shards': [{}] }) self.assertIn('mongodb_auth_uri', self.sh.info()) auth_uri = self.sh.info()['mongodb_auth_uri'] hosts = ','.join(r['hostname'] for r in self.sh.routers) self.assertIn(hosts, auth_uri) self.assertIn('luke:ekul', auth_uri) self.assertIn('authSource=admin', auth_uri)
def test_member_info(self): config = {'shards': [{'id': 'member1'}, {'id': 'sh-rs-01', 'shardParams': {'id': 'rs1', 'members': [{}, {}]}}]} self.sh = ShardedCluster(config) info = self.sh.member_info('member1') self.assertEqual(info['id'], 'member1') self.assertTrue(info['isServer']) self.assertTrue('_id' in info) info = self.sh.member_info('sh-rs-01') self.assertEqual(info['id'], 'sh-rs-01') self.assertTrue(info['isReplicaSet']) self.assertTrue('_id' in info) self.sh.cleanup()
def test_ssl_auth(self): if SERVER_VERSION < (2, 4): raise SkipTest("Need to be able to set 'authenticationMechanisms' " "parameter to test.") shard_params = { 'shardParams': { 'procParams': { 'clusterAuthMode': 'x509', 'setParameter': { 'authenticationMechanisms': 'MONGODB-X509' } } } } config = { 'login': TEST_SUBJECT, 'authSource': '$external', 'configsvrs': self.x509_configsvrs, 'routers': [{ 'clusterAuthMode': 'x509' }], 'shards': [shard_params, shard_params], 'sslParams': { 'sslCAFile': certificate('ca.pem'), 'sslPEMKeyFile': certificate('server.pem'), 'sslMode': 'requireSSL', 'sslClusterFile': certificate('cluster_cert.pem'), 'sslAllowInvalidCertificates': True } } # Should not raise an Exception. self.sh = ShardedCluster(config) # Should create an extra user. No raise on authenticate. host = self.sh.router['hostname'] client = pymongo.MongoClient(host, ssl_certfile=DEFAULT_CLIENT_CERT, ssl_cert_reqs=ssl.CERT_NONE) client['$external'].authenticate(DEFAULT_SUBJECT, mechanism='MONGODB-X509') # Should create the user we requested. No raise on authenticate. client = pymongo.MongoClient(host, ssl_certfile=certificate('client.pem'), ssl_cert_reqs=ssl.CERT_NONE) client['$external'].authenticate(TEST_SUBJECT, mechanism='MONGODB-X509')
def test_member_add(self): config = {} self.sh = ShardedCluster(config) self.assertEqual(len(self.sh.members), 0) result = self.sh.member_add('test1', {}) self.assertTrue(result.get('isServer', False)) self.assertEqual(result['id'], 'test1') self.assertEqual(len(self.sh.members), 1) result = self.sh.member_add('test2', {'id': 'rs1', 'members': [{}, {}]}) self.assertFalse(result.get('isServer', False)) self.assertTrue(result.get('isReplicaSet', False)) self.assertEqual(result['id'], 'test2') self.assertEqual(len(self.sh.members), 2) self.sh.cleanup()
def test_scram_with_ssl(self): proc_params = {'procParams': {'clusterAuthMode': 'x509'}} config = { 'login': '******', 'password': '******', 'configsvrs': [{'clusterAuthMode': 'x509'}], 'routers': [{'clusterAuthMode': 'x509'}], 'shards': [{'shardParams': proc_params}, {'shardParams': {'members': [proc_params]}}], 'sslParams': { 'sslCAFile': certificate('ca.pem'), 'sslPEMKeyFile': certificate('server.pem'), 'sslMode': 'requireSSL', 'sslClusterFile': certificate('cluster_cert.pem'), 'sslAllowInvalidCertificates': True } } # Should not raise an Exception. self.sh = ShardedCluster(config) # Should create the user we requested. No raise on authenticate. host = self.sh.router['hostname'] client = pymongo.MongoClient( host, ssl_certfile=certificate('client.pem')) client.admin.authenticate('luke', 'ekul') # This should be the only user. self.assertEqual(len(client.admin.command('usersInfo')['users']), 1) self.assertFalse(client['$external'].command('usersInfo')['users'])
def test_mongodb_auth_uri(self): if SERVER_VERSION < (2, 4): raise SkipTest("Need to be able to set 'authenticationMechanisms' " "parameter to test.") shard_params = { 'shardParams': { 'procParams': { 'clusterAuthMode': 'x509', 'setParameter': {'authenticationMechanisms': 'MONGODB-X509'} } } } config = { 'login': TEST_SUBJECT, 'authSource': '$external', 'configsvrs': [{'clusterAuthMode': 'x509'}], 'routers': [{'clusterAuthMode': 'x509'}], 'shards': [shard_params, shard_params], 'sslParams': { 'sslCAFile': certificate('ca.pem'), 'sslPEMKeyFile': certificate('server.pem'), 'sslMode': 'requireSSL', 'sslClusterFile': certificate('cluster_cert.pem'), 'sslAllowInvalidCertificates': True } } self.sh = ShardedCluster(config) self.assertIn('mongodb_auth_uri', self.sh.info()) auth_uri = self.sh.info()['mongodb_auth_uri'] hosts = ','.join(r['hostname'] for r in self.sh.routers) self.assertIn(hosts, auth_uri) self.assertIn(TEST_SUBJECT, auth_uri) self.assertIn('authSource=$external', auth_uri) self.assertIn('authMechanism=MONGODB-X509', auth_uri)
def test_scram_with_ssl(self): proc_params = {'procParams': {'clusterAuthMode': 'x509'}} config = { 'login': '******', 'password': '******', 'configsvrs': [{'clusterAuthMode': 'x509'}], 'routers': [{'clusterAuthMode': 'x509'}], 'shards': [{'shardParams': proc_params}, {'shardParams': {'members': [proc_params]}}], 'sslParams': { 'sslCAFile': certificate('ca.pem'), 'sslPEMKeyFile': certificate('server.pem'), 'sslMode': 'requireSSL', 'sslClusterFile': certificate('cluster_cert.pem'), 'sslAllowInvalidCertificates': True } } # Should not raise an Exception. self.sh = ShardedCluster(config) time.sleep(1) # Should create the user we requested. No raise on authenticate. host = self.sh.router['hostname'] client = pymongo.MongoClient( host, ssl_certfile=certificate('client.pem'), ssl_cert_reqs=ssl.CERT_NONE) client.admin.authenticate('luke', 'ekul') # This should be the only user. self.assertEqual(len(client.admin.command('usersInfo')['users']), 1) self.assertFalse(client['$external'].command('usersInfo')['users'])
def test_info(self): config = { 'configsvrs': [{}, {}, {}], 'routers': [{}, {}, {}], 'shards': [{}, {}] } self.sh = ShardedCluster(config) info = self.sh.info() self.assertTrue('shards' in info) self.assertTrue('configsvrs' in info) self.assertTrue('routers' in info) self.assertEqual(len(info['shards']), 2) self.assertEqual(len(info['configsvrs']), 3) self.assertEqual(len(info['routers']), 3) self.sh.cleanup()
def test_router(self): config = {} self.sh = ShardedCluster(config) self.assertTrue(Servers().info(self.sh.router['id'])['statuses']['mongos']) self.sh.cleanup() config = {'routers': [{}, {}, {}]} self.sh = ShardedCluster(config) routers = self.sh.routers hostname = routers[1]['hostname'] _id = routers[1]['id'] # stop routers 0 and 2 Servers().command(routers[0]['id'], 'stop') Servers().command(routers[2]['id'], 'stop') router = self.sh.router self.assertEqual(router['id'], _id) self.assertEqual(router['hostname'], hostname) self.sh.cleanup()
def test_mongodb_auth_uri(self): if SERVER_VERSION < (2, 4): raise SkipTest("Need to be able to set 'authenticationMechanisms' " "parameter to test.") shard_params = { 'shardParams': { 'procParams': { 'clusterAuthMode': 'x509', 'setParameter': { 'authenticationMechanisms': 'MONGODB-X509' } } } } config = { 'login': TEST_SUBJECT, 'authSource': '$external', 'configsvrs': [{ 'clusterAuthMode': 'x509' }], 'routers': [{ 'clusterAuthMode': 'x509' }], 'shards': [shard_params, shard_params], 'sslParams': { 'sslCAFile': certificate('ca.pem'), 'sslPEMKeyFile': certificate('server.pem'), 'sslMode': 'requireSSL', 'sslClusterFile': certificate('cluster_cert.pem'), 'sslAllowInvalidCertificates': True } } self.sh = ShardedCluster(config) self.assertIn('mongodb_auth_uri', self.sh.info()) auth_uri = self.sh.info()['mongodb_auth_uri'] hosts = ','.join(r['hostname'] for r in self.sh.routers) self.assertIn(hosts, auth_uri) self.assertIn(TEST_SUBJECT, auth_uri) self.assertIn('authSource=$external', auth_uri) self.assertIn('authMechanism=MONGODB-X509', auth_uri)
def test_cleanup(self): config = { 'id': 'shard_cluster_1', 'configsvrs': [{}], 'routers': [{}], 'shards': [{'id': 'sh01'}, {'id': 'sh02'}, {'id': 'sh-rs-01', 'shardParams': {'id': 'rs1', 'members': [{}, {}]}}, ] } self.sh = ShardedCluster(config) self.assertTrue(len(self.sh) == len(config['shards'])) self.sh.cleanup() self.assertTrue(len(self.sh) == 0)
def test_member_info_with_auth(self): config = {'auth_key': 'secret', 'login': '******', 'password': '******', 'shards': [{'id': 'member1'}, {'id': 'sh-rs-01', 'shardParams': {'id': 'rs1', 'members': [{}, {}]}}]} self.sh = ShardedCluster(config) info = self.sh.member_info('member1') self.assertEqual(info['id'], 'member1') self.assertTrue(info['isServer']) self.assertTrue('_id' in info) info = self.sh.member_info('sh-rs-01') self.assertEqual(info['id'], 'sh-rs-01') self.assertTrue(info['isReplicaSet']) self.assertTrue('_id' in info) self.sh.cleanup()
def test_sh_new_with_auth(self): port = PortPool().port(check=True) config = { 'id': 'shard_cluster_1', 'auth_key': 'secret', 'login': '******', 'password': '******', 'configsvrs': [{}], 'routers': [{"port": port}], 'shards': [{'id': 'sh01'}, {'id': 'sh02'}] } self.sh = ShardedCluster(config) c = pymongo.MongoClient(self.sh.router['hostname']) self.assertRaises(pymongo.errors.OperationFailure, c.admin.command, "listShards") c.admin.authenticate('admin', 'adminpass') self.assertTrue(isinstance(c.admin.command("listShards"), dict)) for item in c.admin.command("listShards")['shards']: self.assertTrue(item['_id'] in ('sh01', 'sh02'))
def test_ssl_auth(self): if SERVER_VERSION < (2, 4): raise SkipTest("Need to be able to set 'authenticationMechanisms' " "parameter to test.") shard_params = { 'shardParams': { 'procParams': { 'clusterAuthMode': 'x509', 'setParameter': {'authenticationMechanisms': 'MONGODB-X509'} } } } config = { 'login': TEST_SUBJECT, 'authSource': '$external', 'configsvrs': [{'clusterAuthMode': 'x509'}], 'routers': [{'clusterAuthMode': 'x509'}], 'shards': [shard_params, shard_params], 'sslParams': { 'sslCAFile': certificate('ca.pem'), 'sslPEMKeyFile': certificate('server.pem'), 'sslMode': 'requireSSL', 'sslClusterFile': certificate('cluster_cert.pem'), 'sslAllowInvalidCertificates': True } } # Should not raise an Exception. self.sh = ShardedCluster(config) # Should create an extra user. No raise on authenticate. host = self.sh.router['hostname'] client = pymongo.MongoClient( host, ssl_certfile=DEFAULT_CLIENT_CERT, ssl_cert_reqs=ssl.CERT_NONE) client['$external'].authenticate( DEFAULT_SUBJECT, mechanism='MONGODB-X509') # Should create the user we requested. No raise on authenticate. client = pymongo.MongoClient( host, ssl_certfile=certificate('client.pem'), ssl_cert_reqs=ssl.CERT_NONE) client['$external'].authenticate(TEST_SUBJECT, mechanism='MONGODB-X509')
def test_tagging(self): if SERVER_VERSION < (2, 2, 0): raise SkipTest("mongodb v{version} doesn't support shard tagging" .format(version='.'.join(map(str, SERVER_VERSION)))) tags = ['tag1', 'tag2'] tags_repl = ['replTag'] config = { 'configsvrs': [{}], 'routers': [{}], 'shards': [{'id': 'sh01', 'shardParams': {'tags': tags}}, {'id': 'sh02'}, {'id': 'sh03', 'shardParams': {'tags': tags_repl, 'members': [{}, {}]}} ] } self.sh = ShardedCluster(config) self.assertEqual(tags, self.sh.member_info('sh01')['tags']) self.assertEqual([], self.sh.member_info('sh02')['tags']) self.assertEqual(tags_repl, self.sh.member_info('sh03')['tags']) self.sh.cleanup()
def test_ssl(self): config = { 'configsvrs': [{}], 'routers': [{}], 'shards': [{}, {'shardParams': {'members': [{}]}}], 'sslParams': { 'sslCAFile': certificate('ca.pem'), 'sslPEMKeyFile': certificate('server.pem'), 'sslMode': 'requireSSL', 'sslClusterFile': certificate('cluster_cert.pem'), 'sslAllowInvalidCertificates': True } } # Should not raise an Exception. self.sh = ShardedCluster(config) # Server should require SSL. host = self.sh.router['hostname'] with self.assertRaises(pymongo.errors.ConnectionFailure): connected(pymongo.MongoClient(host)) # This shouldn't raise. connected( pymongo.MongoClient(host, ssl_certfile=certificate('client.pem'), ssl_cert_reqs=ssl.CERT_NONE))
class ShardTestCase(unittest.TestCase): def mongod_version(self): proc = subprocess.Popen( [os.path.join(self.bin_path, 'mongod'), '--version'], stdin=subprocess.PIPE, stdout=subprocess.PIPE) version_raw = str(proc.stdout.read()) m = MONGODB_VERSION.match(version_raw) if m: return m.groups() def setUp(self): self.bin_path = os.environ.get('MONGOBIN', '') set_releases({'default-release': self.bin_path}, 'default-release') PortPool().change_range() def tearDown(self): if hasattr(self, 'sh') and self.sh is not None: self.sh.cleanup() def test_len(self): config = {} self.sh = ShardedCluster(config) self.assertEqual(len(self.sh), 0) self.sh.member_add('test01', {}) self.assertEqual(len(self.sh), 1) self.sh.member_add('test02', {}) self.assertEqual(len(self.sh), 2) while self.sh.member_remove('test01')['state'] != 'completed': time.sleep(1) self.assertEqual(len(self.sh), 1) def test_sh_new(self): port = PortPool().port(check=True) config = { 'id': 'shard_cluster_1', 'configsvrs': [{}], 'routers': [{"port": port}], 'shards': [{'id': 'sh01'}, {'id': 'sh02'}] } self.sh = ShardedCluster(config) c = pymongo.MongoClient(self.sh.router['hostname']) for item in c.admin.command("listShards")['shards']: self.assertTrue(item['_id'] in ('sh01', 'sh02')) @attr('auth') def test_sh_new_with_auth(self): port = PortPool().port(check=True) config = { 'id': 'shard_cluster_1', 'auth_key': 'secret', 'login': '******', 'password': '******', 'configsvrs': [{}], 'routers': [{"port": port}], 'shards': [{'id': 'sh01'}, {'id': 'sh02'}] } self.sh = ShardedCluster(config) c = pymongo.MongoClient(self.sh.router['hostname']) self.assertRaises(pymongo.errors.OperationFailure, c.admin.command, "listShards") c.admin.authenticate('admin', 'adminpass') self.assertTrue(isinstance(c.admin.command("listShards"), dict)) for item in c.admin.command("listShards")['shards']: self.assertTrue(item['_id'] in ('sh01', 'sh02')) def test_cleanup(self): config = { 'id': 'shard_cluster_1', 'configsvrs': [{}], 'routers': [{}], 'shards': [{'id': 'sh01'}, {'id': 'sh02'}, {'id': 'sh-rs-01', 'shardParams': {'id': 'rs1', 'members': [{}, {}]}}, ] } self.sh = ShardedCluster(config) self.assertTrue(len(self.sh) == len(config['shards'])) self.sh.cleanup() self.assertTrue(len(self.sh) == 0) def test_configsvrs(self): config = {} self.sh = ShardedCluster(config) self.assertEqual(len(self.sh.configsvrs), 1) self.sh.cleanup() config = {'configsvrs': [{}, {}, {}]} self.sh = ShardedCluster(config) self.assertEqual(len(self.sh.configsvrs), 3) self.sh.cleanup() def test_routers(self): config = {} self.sh = ShardedCluster(config) self.assertEqual(len(self.sh.routers), 1) self.sh.cleanup() config = {'routers': [{}, {}, {}]} self.sh = ShardedCluster(config) self.assertEqual(len(self.sh.routers), 3) self.sh.cleanup() def test_members(self): config = {} self.sh = ShardedCluster(config) self.assertEqual(len(self.sh.members), 0) self.sh.cleanup() config = {'shards': [{}, {}, {}]} self.sh = ShardedCluster(config) self.assertEqual(len(self.sh.members), 3) self.sh.cleanup() def test_router(self): config = {} self.sh = ShardedCluster(config) self.assertTrue(Servers().info(self.sh.router['id'])['statuses']['mongos']) self.sh.cleanup() config = {'routers': [{}, {}, {}]} self.sh = ShardedCluster(config) routers = self.sh.routers hostname = routers[1]['hostname'] _id = routers[1]['id'] # stop routers 0 and 2 Servers().command(routers[0]['id'], 'stop') Servers().command(routers[2]['id'], 'stop') router = self.sh.router self.assertEqual(router['id'], _id) self.assertEqual(router['hostname'], hostname) self.sh.cleanup() def test_router_add(self): config = {} self.sh = ShardedCluster(config) self.assertEqual(len(self.sh.routers), 1) self.sh.router_add({}) self.assertEqual(len(self.sh.routers), 2) self.sh.router_add({}) self.assertEqual(len(self.sh.routers), 3) self.sh.cleanup() def test_router_command(self): config = {'shards': [{}, {}]} self.sh = ShardedCluster(config) result = self.sh.router_command('listShards', is_eval=False) self.assertEqual(result['ok'], 1) self.sh.cleanup() def test_member_add(self): config = {} self.sh = ShardedCluster(config) self.assertEqual(len(self.sh.members), 0) result = self.sh.member_add('test1', {}) self.assertTrue(result.get('isServer', False)) self.assertEqual(result['id'], 'test1') self.assertEqual(len(self.sh.members), 1) result = self.sh.member_add('test2', {'id': 'rs1', 'members': [{}, {}]}) self.assertFalse(result.get('isServer', False)) self.assertTrue(result.get('isReplicaSet', False)) self.assertEqual(result['id'], 'test2') self.assertEqual(len(self.sh.members), 2) self.sh.cleanup() def test_member_info(self): config = {'shards': [{'id': 'member1'}, {'id': 'sh-rs-01', 'shardParams': {'id': 'rs1', 'members': [{}, {}]}}]} self.sh = ShardedCluster(config) info = self.sh.member_info('member1') self.assertEqual(info['id'], 'member1') self.assertTrue(info['isServer']) self.assertTrue('_id' in info) info = self.sh.member_info('sh-rs-01') self.assertEqual(info['id'], 'sh-rs-01') self.assertTrue(info['isReplicaSet']) self.assertTrue('_id' in info) self.sh.cleanup() @attr('auth') def test_member_info_with_auth(self): config = {'auth_key': 'secret', 'login': '******', 'password': '******', 'shards': [{'id': 'member1'}, {'id': 'sh-rs-01', 'shardParams': {'id': 'rs1', 'members': [{}, {}]}}]} self.sh = ShardedCluster(config) info = self.sh.member_info('member1') self.assertEqual(info['id'], 'member1') self.assertTrue(info['isServer']) self.assertTrue('_id' in info) info = self.sh.member_info('sh-rs-01') self.assertEqual(info['id'], 'sh-rs-01') self.assertTrue(info['isReplicaSet']) self.assertTrue('_id' in info) self.sh.cleanup() def test_member_remove(self): config = {'shards': [{'id': 'member1'}, {'id': 'member2'}, {'id': 'sh-rs-01', 'shardParams': {'id': 'rs1', 'members': [{}, {}]}}]} self.sh = ShardedCluster(config) self.assertEqual(len(self.sh.members), 3) # remove member-host result = self.sh.member_remove('member1') self.assertEqual(len(self.sh.members), 3) self.assertEqual(result['state'], 'started') self.assertEqual(result['shard'], 'member1') time.sleep(5) result = self.sh.member_remove('member1') self.assertEqual(result['state'], 'completed') self.assertEqual(len(self.sh.members), 2) self.assertEqual(result['shard'], 'member1') # remove member-replicaset result = self.sh.member_remove('sh-rs-01') self.assertEqual(len(self.sh.members), 2) self.assertEqual(result['state'], 'started') self.assertEqual(result['shard'], 'sh-rs-01') time.sleep(7) result = self.sh.member_remove('sh-rs-01') self.assertEqual(result['state'], 'completed') self.assertEqual(len(self.sh.members), 1) self.assertEqual(result['shard'], 'sh-rs-01') self.sh.cleanup() def test_info(self): config = { 'configsvrs': [{}, {}, {}], 'routers': [{}, {}, {}], 'shards': [{}, {}] } self.sh = ShardedCluster(config) info = self.sh.info() self.assertTrue('shards' in info) self.assertTrue('configsvrs' in info) self.assertTrue('routers' in info) self.assertEqual(len(info['shards']), 2) self.assertEqual(len(info['configsvrs']), 3) self.assertEqual(len(info['routers']), 3) self.sh.cleanup() def test_tagging(self): version = self.mongod_version() if version and version < ('2', '2', '0'): raise SkipTest("mongodb v{version} doesn't support shard tagging".format(version='.'.join(version))) tags = ['tag1', 'tag2'] tags_repl = ['replTag'] config = { 'configsvrs': [{}], 'routers': [{}], 'shards': [{'id': 'sh01', 'shardParams': {'tags': tags}}, {'id': 'sh02'}, {'id': 'sh03', 'shardParams': {'tags': tags_repl, 'members': [{}, {}]}} ] } self.sh = ShardedCluster(config) self.assertEqual(tags, self.sh.member_info('sh01')['tags']) self.assertEqual([], self.sh.member_info('sh02')['tags']) self.assertEqual(tags_repl, self.sh.member_info('sh03')['tags']) self.sh.cleanup() def test_reset(self): all_hosts = [] # Start a ShardedCluster with 1 router and 1 config server. self.sh = ShardedCluster({}) # Add 1 Server shard and 1 ReplicaSet shard. server_id = self.sh.member_add(params={})['_id'] all_hosts.append(Servers().hostname(server_id)) repl_id = self.sh.member_add(params={'members': [{}, {}, {}]})['_id'] # Shut down the standalone. Servers().command(server_id, 'stop') # Shut down each member of the replica set. server_ids = [m['server_id'] for m in ReplicaSets().members(repl_id)] for s_id in server_ids: Servers().command(s_id, 'stop') all_hosts.append(Servers().hostname(s_id)) # Shut down config server and router. config_id = self.sh.configsvrs[0]['id'] print("config_id=%r" % config_id) all_hosts.append(Servers().hostname(config_id)) router_id = self.sh.routers[0]['id'] print("router_id=%r" % router_id) all_hosts.append(Servers().hostname(router_id)) Servers().command(config_id, 'stop') Servers().command(router_id, 'stop') # Reset the ShardedCluster. self.sh.reset() # Everything is up. for host in all_hosts: # No ConnectionFailure/AutoReconnect. pymongo.MongoClient(host)
def test_router_command(self): config = {'shards': [{}, {}]} self.sh = ShardedCluster(config) result = self.sh.router_command('listShards', is_eval=False) self.assertEqual(result['ok'], 1) self.sh.cleanup()
class ShardSSLTestCase(SSLTestCase): def setUp(self): self.sh = None PortPool().change_range() def tearDown(self): if self.sh is not None: self.sh.cleanup() def test_ssl_auth(self): if SERVER_VERSION < (2, 4): raise SkipTest("Need to be able to set 'authenticationMechanisms' " "parameter to test.") shard_params = { 'shardParams': { 'procParams': { 'clusterAuthMode': 'x509', 'setParameter': {'authenticationMechanisms': 'MONGODB-X509'} } } } config = { 'login': TEST_SUBJECT, 'authSource': '$external', 'configsvrs': [{'clusterAuthMode': 'x509'}], 'routers': [{'clusterAuthMode': 'x509'}], 'shards': [shard_params, shard_params], 'sslParams': { 'sslCAFile': certificate('ca.pem'), 'sslPEMKeyFile': certificate('server.pem'), 'sslMode': 'requireSSL', 'sslClusterFile': certificate('cluster_cert.pem'), 'sslAllowInvalidCertificates': True } } # Should not raise an Exception. self.sh = ShardedCluster(config) # Should create an extra user. No raise on authenticate. host = self.sh.router['hostname'] client = pymongo.MongoClient( host, ssl_certfile=DEFAULT_CLIENT_CERT, ssl_cert_reqs=ssl.CERT_NONE) client['$external'].authenticate( DEFAULT_SUBJECT, mechanism='MONGODB-X509') # Should create the user we requested. No raise on authenticate. client = pymongo.MongoClient( host, ssl_certfile=certificate('client.pem'), ssl_cert_reqs=ssl.CERT_NONE) client['$external'].authenticate(TEST_SUBJECT, mechanism='MONGODB-X509') def test_scram_with_ssl(self): proc_params = {'procParams': {'clusterAuthMode': 'x509'}} config = { 'login': '******', 'password': '******', 'configsvrs': [{'clusterAuthMode': 'x509'}], 'routers': [{'clusterAuthMode': 'x509'}], 'shards': [{'shardParams': proc_params}, {'shardParams': {'members': [proc_params]}}], 'sslParams': { 'sslCAFile': certificate('ca.pem'), 'sslPEMKeyFile': certificate('server.pem'), 'sslMode': 'requireSSL', 'sslClusterFile': certificate('cluster_cert.pem'), 'sslAllowInvalidCertificates': True } } # Should not raise an Exception. self.sh = ShardedCluster(config) time.sleep(1) # Should create the user we requested. No raise on authenticate. host = self.sh.router['hostname'] client = pymongo.MongoClient( host, ssl_certfile=certificate('client.pem'), ssl_cert_reqs=ssl.CERT_NONE) client.admin.authenticate('luke', 'ekul') # This should be the only user. self.assertEqual(len(client.admin.command('usersInfo')['users']), 1) self.assertFalse(client['$external'].command('usersInfo')['users']) def test_ssl(self): config = { 'configsvrs': [{}], 'routers': [{}], 'shards': [{}, {'shardParams': {'members': [{}]}}], 'sslParams': { 'sslCAFile': certificate('ca.pem'), 'sslPEMKeyFile': certificate('server.pem'), 'sslMode': 'requireSSL', 'sslClusterFile': certificate('cluster_cert.pem'), 'sslAllowInvalidCertificates': True } } # Should not raise an Exception. self.sh = ShardedCluster(config) # Server should require SSL. host = self.sh.router['hostname'] with self.assertRaises(pymongo.errors.ConnectionFailure): connected(pymongo.MongoClient(host)) # This shouldn't raise. connected( pymongo.MongoClient(host, ssl_certfile=certificate('client.pem'), ssl_cert_reqs=ssl.CERT_NONE)) def test_mongodb_auth_uri(self): if SERVER_VERSION < (2, 4): raise SkipTest("Need to be able to set 'authenticationMechanisms' " "parameter to test.") shard_params = { 'shardParams': { 'procParams': { 'clusterAuthMode': 'x509', 'setParameter': {'authenticationMechanisms': 'MONGODB-X509'} } } } config = { 'login': TEST_SUBJECT, 'authSource': '$external', 'configsvrs': [{'clusterAuthMode': 'x509'}], 'routers': [{'clusterAuthMode': 'x509'}], 'shards': [shard_params, shard_params], 'sslParams': { 'sslCAFile': certificate('ca.pem'), 'sslPEMKeyFile': certificate('server.pem'), 'sslMode': 'requireSSL', 'sslClusterFile': certificate('cluster_cert.pem'), 'sslAllowInvalidCertificates': True } } self.sh = ShardedCluster(config) self.assertIn('mongodb_auth_uri', self.sh.info()) auth_uri = self.sh.info()['mongodb_auth_uri'] hosts = ','.join(r['hostname'] for r in self.sh.routers) self.assertIn(hosts, auth_uri) self.assertIn(TEST_SUBJECT, auth_uri) self.assertIn('authSource=$external', auth_uri) self.assertIn('authMechanism=MONGODB-X509', auth_uri)
class ShardTestCase(unittest.TestCase): def setUp(self): PortPool().change_range() def tearDown(self): if hasattr(self, 'sh') and self.sh is not None: self.sh.cleanup() def test_len(self): config = {} self.sh = ShardedCluster(config) self.assertEqual(len(self.sh), 0) self.sh.member_add('test01', {}) self.assertEqual(len(self.sh), 1) self.sh.member_add('test02', {}) self.assertEqual(len(self.sh), 2) while self.sh.member_remove('test01')['state'] != 'completed': time.sleep(1) self.assertEqual(len(self.sh), 1) def test_sh_new(self): port = PortPool().port(check=True) config = { 'id': 'shard_cluster_1', 'configsvrs': [{}], 'routers': [{"port": port}], 'shards': [{'id': 'sh01'}, {'id': 'sh02'}] } self.sh = ShardedCluster(config) c = pymongo.MongoClient(self.sh.router['hostname']) for item in c.admin.command("listShards")['shards']: self.assertTrue(item['_id'] in ('sh01', 'sh02')) def test_sh_new_with_auth(self): port = PortPool().port(check=True) config = { 'id': 'shard_cluster_1', 'auth_key': 'secret', 'login': '******', 'password': '******', 'configsvrs': [{}], 'routers': [{"port": port}], 'shards': [{'id': 'sh01'}, {'id': 'sh02'}] } self.sh = ShardedCluster(config) c = pymongo.MongoClient(self.sh.router['hostname']) self.assertRaises(pymongo.errors.OperationFailure, c.admin.command, "listShards") c.admin.authenticate('admin', 'adminpass') self.assertTrue(isinstance(c.admin.command("listShards"), dict)) for item in c.admin.command("listShards")['shards']: self.assertTrue(item['_id'] in ('sh01', 'sh02')) def test_cleanup(self): config = { 'id': 'shard_cluster_1', 'configsvrs': [{}], 'routers': [{}], 'shards': [{'id': 'sh01'}, {'id': 'sh02'}, {'id': 'sh-rs-01', 'shardParams': {'id': 'rs1', 'members': [{}, {}]}}, ] } self.sh = ShardedCluster(config) self.assertTrue(len(self.sh) == len(config['shards'])) self.sh.cleanup() self.assertTrue(len(self.sh) == 0) def test_configsvrs(self): config = {} self.sh = ShardedCluster(config) self.assertEqual(len(self.sh.configsvrs), 1) self.sh.cleanup() config = {'configsvrs': [{}, {}, {}]} self.sh = ShardedCluster(config) self.assertEqual(len(self.sh.configsvrs), 3) self.sh.cleanup() def test_routers(self): config = {} self.sh = ShardedCluster(config) self.assertEqual(len(self.sh.routers), 1) self.sh.cleanup() config = {'routers': [{}, {}, {}]} self.sh = ShardedCluster(config) self.assertEqual(len(self.sh.routers), 3) self.sh.cleanup() def test_members(self): config = {} self.sh = ShardedCluster(config) self.assertEqual(len(self.sh.members), 0) self.sh.cleanup() config = {'shards': [{}, {}, {}]} self.sh = ShardedCluster(config) self.assertEqual(len(self.sh.members), 3) self.sh.cleanup() def test_router(self): config = {} self.sh = ShardedCluster(config) self.assertTrue(Servers().info(self.sh.router['id'])['statuses']['mongos']) self.sh.cleanup() config = {'routers': [{}, {}, {}]} self.sh = ShardedCluster(config) routers = self.sh.routers hostname = routers[1]['hostname'] _id = routers[1]['id'] # stop routers 0 and 2 Servers().command(routers[0]['id'], 'stop') Servers().command(routers[2]['id'], 'stop') router = self.sh.router self.assertEqual(router['id'], _id) self.assertEqual(router['hostname'], hostname) self.sh.cleanup() def test_router_add(self): config = {} self.sh = ShardedCluster(config) self.assertEqual(len(self.sh.routers), 1) self.sh.router_add({}) self.assertEqual(len(self.sh.routers), 2) self.sh.router_add({}) self.assertEqual(len(self.sh.routers), 3) self.sh.cleanup() def test_router_command(self): config = {'shards': [{}, {}]} self.sh = ShardedCluster(config) result = self.sh.router_command('listShards', is_eval=False) self.assertEqual(result['ok'], 1) self.sh.cleanup() def test_member_add(self): config = {} self.sh = ShardedCluster(config) self.assertEqual(len(self.sh.members), 0) result = self.sh.member_add('test1', {}) self.assertTrue(result.get('isServer', False)) self.assertEqual(result['id'], 'test1') self.assertEqual(len(self.sh.members), 1) result = self.sh.member_add('test2', {'id': 'rs1', 'members': [{}, {}]}) self.assertFalse(result.get('isServer', False)) self.assertTrue(result.get('isReplicaSet', False)) self.assertEqual(result['id'], 'test2') self.assertEqual(len(self.sh.members), 2) self.sh.cleanup() def test_member_info(self): config = {'shards': [{'id': 'member1'}, {'id': 'sh-rs-01', 'shardParams': {'id': 'rs1', 'members': [{}, {}]}}]} self.sh = ShardedCluster(config) info = self.sh.member_info('member1') self.assertEqual(info['id'], 'member1') self.assertTrue(info['isServer']) self.assertTrue('_id' in info) info = self.sh.member_info('sh-rs-01') self.assertEqual(info['id'], 'sh-rs-01') self.assertTrue(info['isReplicaSet']) self.assertTrue('_id' in info) self.sh.cleanup() def test_member_info_with_auth(self): config = {'auth_key': 'secret', 'login': '******', 'password': '******', 'shards': [{'id': 'member1'}, {'id': 'sh-rs-01', 'shardParams': {'id': 'rs1', 'members': [{}, {}]}}]} self.sh = ShardedCluster(config) info = self.sh.member_info('member1') self.assertEqual(info['id'], 'member1') self.assertTrue(info['isServer']) self.assertTrue('_id' in info) info = self.sh.member_info('sh-rs-01') self.assertEqual(info['id'], 'sh-rs-01') self.assertTrue(info['isReplicaSet']) self.assertTrue('_id' in info) self.sh.cleanup() def test_member_remove(self): config = {'shards': [{'id': 'member1'}, {'id': 'member2'}, {'id': 'sh-rs-01', 'shardParams': {'id': 'rs1', 'members': [{}, {}]}}]} self.sh = ShardedCluster(config) self.assertEqual(len(self.sh.members), 3) # remove member-host result = self.sh.member_remove('member1') self.assertEqual(len(self.sh.members), 3) self.assertEqual(result['state'], 'started') self.assertEqual(result['shard'], 'member1') time.sleep(5) result = self.sh.member_remove('member1') self.assertEqual(result['state'], 'completed') self.assertEqual(len(self.sh.members), 2) self.assertEqual(result['shard'], 'member1') # remove member-replicaset result = self.sh.member_remove('sh-rs-01') self.assertEqual(len(self.sh.members), 2) self.assertEqual(result['state'], 'started') self.assertEqual(result['shard'], 'sh-rs-01') time.sleep(7) result = self.sh.member_remove('sh-rs-01') self.assertEqual(result['state'], 'completed') self.assertEqual(len(self.sh.members), 1) self.assertEqual(result['shard'], 'sh-rs-01') self.sh.cleanup() def test_info(self): config = { 'configsvrs': [{}, {}, {}], 'routers': [{}, {}, {}], 'shards': [{}, {}] } self.sh = ShardedCluster(config) info = self.sh.info() self.assertTrue('shards' in info) self.assertTrue('configsvrs' in info) self.assertTrue('routers' in info) self.assertEqual(len(info['shards']), 2) self.assertEqual(len(info['configsvrs']), 3) self.assertEqual(len(info['routers']), 3) self.sh.cleanup() def test_tagging(self): if SERVER_VERSION < (2, 2, 0): raise SkipTest("mongodb v{version} doesn't support shard tagging" .format(version='.'.join(map(str, SERVER_VERSION)))) tags = ['tag1', 'tag2'] tags_repl = ['replTag'] config = { 'configsvrs': [{}], 'routers': [{}], 'shards': [{'id': 'sh01', 'shardParams': {'tags': tags}}, {'id': 'sh02'}, {'id': 'sh03', 'shardParams': {'tags': tags_repl, 'members': [{}, {}]}} ] } self.sh = ShardedCluster(config) self.assertEqual(tags, self.sh.member_info('sh01')['tags']) self.assertEqual([], self.sh.member_info('sh02')['tags']) self.assertEqual(tags_repl, self.sh.member_info('sh03')['tags']) self.sh.cleanup() def test_reset(self): all_hosts = [] # Start a ShardedCluster with 1 router and 1 config server. self.sh = ShardedCluster({}) # Add 1 Server shard and 1 ReplicaSet shard. server_id = self.sh.member_add(params={})['_id'] all_hosts.append(Servers().hostname(server_id)) repl_id = self.sh.member_add(params={'members': [{}, {}, {}]})['_id'] # Shut down the standalone. Servers().command(server_id, 'stop') # Shut down each member of the replica set. server_ids = [m['server_id'] for m in ReplicaSets().members(repl_id)] for s_id in server_ids: Servers().command(s_id, 'stop') all_hosts.append(Servers().hostname(s_id)) # Shut down config server and router. config_id = self.sh.configsvrs[0]['id'] print("config_id=%r" % config_id) all_hosts.append(Servers().hostname(config_id)) router_id = self.sh.routers[0]['id'] print("router_id=%r" % router_id) all_hosts.append(Servers().hostname(router_id)) Servers().command(config_id, 'stop') Servers().command(router_id, 'stop') # Reset the ShardedCluster. self.sh.reset() # Everything is up. for host in all_hosts: # No ConnectionFailure/AutoReconnect. pymongo.MongoClient(host) def test_mongodb_auth_uri(self): self.sh = ShardedCluster({ 'login': '******', 'password': '******', 'routers': [{}, {}], 'shards': [{}] }) self.assertIn('mongodb_auth_uri', self.sh.info()) auth_uri = self.sh.info()['mongodb_auth_uri'] hosts = ','.join(r['hostname'] for r in self.sh.routers) self.assertIn(hosts, auth_uri) self.assertIn('luke:ekul', auth_uri) self.assertIn('authSource=admin', auth_uri) def test_auth_key_without_login(self): self.sh = ShardedCluster({ 'auth_key': 'secret', 'routers': [{}], 'shards': [{}] }) self.assertIsNotNone(self.sh.key_file)
class ShardTestCase(unittest.TestCase): def setUp(self): PortPool().change_range() def tearDown(self): if hasattr(self, 'sh') and self.sh is not None: self.sh.cleanup() def test_len(self): config = {} self.sh = ShardedCluster(config) self.assertEqual(len(self.sh), 0) self.sh.member_add('test01', {}) self.assertEqual(len(self.sh), 1) self.sh.member_add('test02', {}) self.assertEqual(len(self.sh), 2) while self.sh.member_remove('test01')['state'] != 'completed': time.sleep(1) self.assertEqual(len(self.sh), 1) def test_sh_new(self): port = PortPool().port(check=True) config = { 'id': 'shard_cluster_1', 'configsvrs': [{}], 'routers': [{ "port": port }], 'shards': [{ 'id': 'sh01' }, { 'id': 'sh02' }] } self.sh = ShardedCluster(config) c = pymongo.MongoClient(self.sh.router['hostname']) for item in c.admin.command("listShards")['shards']: self.assertTrue(item['_id'] in ('sh01', 'sh02')) def test_sh_new_with_auth(self): port = PortPool().port(check=True) config = { 'id': 'shard_cluster_1', 'auth_key': 'secret', 'login': '******', 'password': '******', 'configsvrs': [{}], 'routers': [{ "port": port }], 'shards': [{ 'id': 'sh01' }, { 'id': 'sh02' }] } self.sh = ShardedCluster(config) c = pymongo.MongoClient(self.sh.router['hostname']) self.assertRaises(pymongo.errors.OperationFailure, c.admin.command, "listShards") c.admin.authenticate('admin', 'adminpass') self.assertTrue(isinstance(c.admin.command("listShards"), dict)) for item in c.admin.command("listShards")['shards']: self.assertTrue(item['_id'] in ('sh01', 'sh02')) def test_cleanup(self): config = { 'id': 'shard_cluster_1', 'configsvrs': [{}], 'routers': [{}], 'shards': [ { 'id': 'sh01' }, { 'id': 'sh02' }, { 'id': 'sh-rs-01', 'shardParams': { 'id': 'rs1', 'members': [{}, {}] } }, ] } self.sh = ShardedCluster(config) self.assertTrue(len(self.sh) == len(config['shards'])) self.sh.cleanup() self.assertTrue(len(self.sh) == 0) def test_configsvrs(self): config = {} self.sh = ShardedCluster(config) self.assertEqual(len(self.sh.configsvrs), 1) self.sh.cleanup() config = {'configsvrs': [{}, {}, {}]} self.sh = ShardedCluster(config) self.assertEqual(len(self.sh.configsvrs), 3) self.sh.cleanup() def test_routers(self): config = {} self.sh = ShardedCluster(config) self.assertEqual(len(self.sh.routers), 1) self.sh.cleanup() config = {'routers': [{}, {}, {}]} self.sh = ShardedCluster(config) self.assertEqual(len(self.sh.routers), 3) self.sh.cleanup() def test_members(self): config = {} self.sh = ShardedCluster(config) self.assertEqual(len(self.sh.members), 0) self.sh.cleanup() config = {'shards': [{}, {}, {}]} self.sh = ShardedCluster(config) self.assertEqual(len(self.sh.members), 3) self.sh.cleanup() def test_router(self): config = {} self.sh = ShardedCluster(config) self.assertTrue(Servers().info( self.sh.router['id'])['statuses']['mongos']) self.sh.cleanup() config = {'routers': [{}, {}, {}]} self.sh = ShardedCluster(config) routers = self.sh.routers hostname = routers[1]['hostname'] _id = routers[1]['id'] # stop routers 0 and 2 Servers().command(routers[0]['id'], 'stop') Servers().command(routers[2]['id'], 'stop') router = self.sh.router self.assertEqual(router['id'], _id) self.assertEqual(router['hostname'], hostname) self.sh.cleanup() def test_router_add(self): config = {} self.sh = ShardedCluster(config) self.assertEqual(len(self.sh.routers), 1) self.sh.router_add({}) self.assertEqual(len(self.sh.routers), 2) self.sh.router_add({}) self.assertEqual(len(self.sh.routers), 3) self.sh.cleanup() def test_router_command(self): config = {'shards': [{}, {}]} self.sh = ShardedCluster(config) result = self.sh.router_command('listShards', is_eval=False) self.assertEqual(result['ok'], 1) self.sh.cleanup() def test_member_add(self): config = {} self.sh = ShardedCluster(config) self.assertEqual(len(self.sh.members), 0) result = self.sh.member_add('test1', {}) self.assertTrue(result.get('isServer', False)) self.assertEqual(result['id'], 'test1') self.assertEqual(len(self.sh.members), 1) result = self.sh.member_add('test2', { 'id': 'rs1', 'members': [{}, {}] }) self.assertFalse(result.get('isServer', False)) self.assertTrue(result.get('isReplicaSet', False)) self.assertEqual(result['id'], 'test2') self.assertEqual(len(self.sh.members), 2) self.sh.cleanup() def test_member_info(self): config = { 'shards': [{ 'id': 'member1' }, { 'id': 'sh-rs-01', 'shardParams': { 'id': 'rs1', 'members': [{}, {}] } }] } self.sh = ShardedCluster(config) info = self.sh.member_info('member1') self.assertEqual(info['id'], 'member1') self.assertTrue(info['isServer']) self.assertTrue('_id' in info) info = self.sh.member_info('sh-rs-01') self.assertEqual(info['id'], 'sh-rs-01') self.assertTrue(info['isReplicaSet']) self.assertTrue('_id' in info) self.sh.cleanup() def test_member_info_with_auth(self): config = { 'auth_key': 'secret', 'login': '******', 'password': '******', 'shards': [{ 'id': 'member1' }, { 'id': 'sh-rs-01', 'shardParams': { 'id': 'rs1', 'members': [{}, {}] } }] } self.sh = ShardedCluster(config) info = self.sh.member_info('member1') self.assertEqual(info['id'], 'member1') self.assertTrue(info['isServer']) self.assertTrue('_id' in info) info = self.sh.member_info('sh-rs-01') self.assertEqual(info['id'], 'sh-rs-01') self.assertTrue(info['isReplicaSet']) self.assertTrue('_id' in info) self.sh.cleanup() def test_member_remove(self): config = { 'shards': [{ 'id': 'member1' }, { 'id': 'member2' }, { 'id': 'sh-rs-01', 'shardParams': { 'id': 'rs1', 'members': [{}, {}] } }] } self.sh = ShardedCluster(config) self.assertEqual(len(self.sh.members), 3) # remove member-host result = self.sh.member_remove('member1') self.assertEqual(len(self.sh.members), 3) self.assertEqual(result['state'], 'started') self.assertEqual(result['shard'], 'member1') time.sleep(5) result = self.sh.member_remove('member1') self.assertEqual(result['state'], 'completed') self.assertEqual(len(self.sh.members), 2) self.assertEqual(result['shard'], 'member1') # remove member-replicaset result = self.sh.member_remove('sh-rs-01') self.assertEqual(len(self.sh.members), 2) self.assertEqual(result['state'], 'started') self.assertEqual(result['shard'], 'sh-rs-01') time.sleep(7) result = self.sh.member_remove('sh-rs-01') self.assertEqual(result['state'], 'completed') self.assertEqual(len(self.sh.members), 1) self.assertEqual(result['shard'], 'sh-rs-01') self.sh.cleanup() def test_info(self): config = { 'configsvrs': [{}, {}, {}], 'routers': [{}, {}, {}], 'shards': [{}, {}] } self.sh = ShardedCluster(config) info = self.sh.info() self.assertTrue('shards' in info) self.assertTrue('configsvrs' in info) self.assertTrue('routers' in info) self.assertEqual(len(info['shards']), 2) self.assertEqual(len(info['configsvrs']), 3) self.assertEqual(len(info['routers']), 3) self.sh.cleanup() def test_tagging(self): if SERVER_VERSION < (2, 2, 0): raise SkipTest( "mongodb v{version} doesn't support shard tagging".format( version='.'.join(map(str, SERVER_VERSION)))) tags = ['tag1', 'tag2'] tags_repl = ['replTag'] config = { 'configsvrs': [{}], 'routers': [{}], 'shards': [{ 'id': 'sh01', 'shardParams': { 'tags': tags } }, { 'id': 'sh02' }, { 'id': 'sh03', 'shardParams': { 'tags': tags_repl, 'members': [{}, {}] } }] } self.sh = ShardedCluster(config) self.assertEqual(tags, self.sh.member_info('sh01')['tags']) self.assertEqual([], self.sh.member_info('sh02')['tags']) self.assertEqual(tags_repl, self.sh.member_info('sh03')['tags']) self.sh.cleanup() def test_reset(self): all_hosts = [] # Start a ShardedCluster with 1 router and 1 config server. self.sh = ShardedCluster({}) # Add 1 Server shard and 1 ReplicaSet shard. server_id = self.sh.member_add(params={})['_id'] all_hosts.append(Servers().hostname(server_id)) repl_id = self.sh.member_add(params={'members': [{}, {}, {}]})['_id'] # Shut down the standalone. Servers().command(server_id, 'stop') # Shut down each member of the replica set. server_ids = [m['server_id'] for m in ReplicaSets().members(repl_id)] for s_id in server_ids: Servers().command(s_id, 'stop') all_hosts.append(Servers().hostname(s_id)) # Shut down config server and router. config_id = self.sh.configsvrs[0]['id'] print("config_id=%r" % config_id) if self.sh.uses_rs_configdb: all_hosts.append(ReplicaSets().info(config_id)['mongodb_uri']) for member in ReplicaSets().members(config_id): Servers().command(member['server_id'], 'stop') else: all_hosts.append(Servers().hostname(config_id)) Servers().command(config_id, 'stop') router_id = self.sh.routers[0]['id'] print("router_id=%r" % router_id) all_hosts.append(Servers().hostname(router_id)) Servers().command(router_id, 'stop') # Reset the ShardedCluster. self.sh.reset() # Everything is up. for host in all_hosts: # No ConnectionFailure/AutoReconnect. pymongo.MongoClient(host) def test_mongodb_auth_uri(self): self.sh = ShardedCluster({ 'login': '******', 'password': '******', 'routers': [{}, {}], 'shards': [{}] }) self.assertIn('mongodb_auth_uri', self.sh.info()) auth_uri = self.sh.info()['mongodb_auth_uri'] hosts = ','.join(r['hostname'] for r in self.sh.routers) self.assertIn(hosts, auth_uri) self.assertIn('luke:ekul', auth_uri) self.assertIn('authSource=admin', auth_uri) def test_auth_key_without_login(self): self.sh = ShardedCluster({ 'auth_key': 'secret', 'routers': [{}], 'shards': [{}] }) self.assertIsNotNone(self.sh.key_file)
class ShardSSLTestCase(SSLTestCase): @classmethod def setUpClass(cls): if SERVER_VERSION >= (3, 1, 2): cls.x509_configsvrs = [{ 'members': [{ 'procParams': { 'clusterAuthMode': 'x509' } }] }] else: cls.x509_configsvrs = [{'clusterAuthMode': 'x509'}] def setUp(self): self.sh = None PortPool().change_range() def tearDown(self): if self.sh is not None: self.sh.cleanup() def test_ssl_auth(self): if SERVER_VERSION < (2, 4): raise SkipTest("Need to be able to set 'authenticationMechanisms' " "parameter to test.") shard_params = { 'shardParams': { 'procParams': { 'clusterAuthMode': 'x509', 'setParameter': { 'authenticationMechanisms': 'MONGODB-X509' } } } } config = { 'login': TEST_SUBJECT, 'authSource': '$external', 'configsvrs': self.x509_configsvrs, 'routers': [{ 'clusterAuthMode': 'x509' }], 'shards': [shard_params, shard_params], 'sslParams': { 'sslCAFile': certificate('ca.pem'), 'sslPEMKeyFile': certificate('server.pem'), 'sslMode': 'requireSSL', 'sslClusterFile': certificate('cluster_cert.pem'), 'sslAllowInvalidCertificates': True } } # Should not raise an Exception. self.sh = ShardedCluster(config) # Should create an extra user. No raise on authenticate. host = self.sh.router['hostname'] client = pymongo.MongoClient(host, ssl_certfile=DEFAULT_CLIENT_CERT, ssl_cert_reqs=ssl.CERT_NONE) client['$external'].authenticate(DEFAULT_SUBJECT, mechanism='MONGODB-X509') # Should create the user we requested. No raise on authenticate. client = pymongo.MongoClient(host, ssl_certfile=certificate('client.pem'), ssl_cert_reqs=ssl.CERT_NONE) client['$external'].authenticate(TEST_SUBJECT, mechanism='MONGODB-X509') def test_scram_with_ssl(self): proc_params = {'procParams': {'clusterAuthMode': 'x509'}} config = { 'login': '******', 'password': '******', 'configsvrs': self.x509_configsvrs, 'routers': [{ 'clusterAuthMode': 'x509' }], 'shards': [{ 'shardParams': proc_params }, { 'shardParams': { 'members': [proc_params] } }], 'sslParams': { 'sslCAFile': certificate('ca.pem'), 'sslPEMKeyFile': certificate('server.pem'), 'sslMode': 'requireSSL', 'sslClusterFile': certificate('cluster_cert.pem'), 'sslAllowInvalidCertificates': True } } # Should not raise an Exception. self.sh = ShardedCluster(config) time.sleep(1) # Should create the user we requested. No raise on authenticate. host = self.sh.router['hostname'] client = pymongo.MongoClient(host, ssl_certfile=certificate('client.pem'), ssl_cert_reqs=ssl.CERT_NONE) client.admin.authenticate('luke', 'ekul') # This should be the only user. self.assertEqual(len(client.admin.command('usersInfo')['users']), 1) self.assertFalse(client['$external'].command('usersInfo')['users']) def test_ssl(self): config = { 'configsvrs': [{}], 'routers': [{}], 'shards': [{}, { 'shardParams': { 'members': [{}] } }], 'sslParams': { 'sslCAFile': certificate('ca.pem'), 'sslPEMKeyFile': certificate('server.pem'), 'sslMode': 'requireSSL', 'sslClusterFile': certificate('cluster_cert.pem'), 'sslAllowInvalidCertificates': True } } # Should not raise an Exception. self.sh = ShardedCluster(config) # Server should require SSL. host = self.sh.router['hostname'] with self.assertRaises(pymongo.errors.ConnectionFailure): connected(pymongo.MongoClient(host)) # This shouldn't raise. connected( pymongo.MongoClient(host, ssl_certfile=certificate('client.pem'), ssl_cert_reqs=ssl.CERT_NONE)) def test_mongodb_auth_uri(self): if SERVER_VERSION < (2, 4): raise SkipTest("Need to be able to set 'authenticationMechanisms' " "parameter to test.") shard_params = { 'shardParams': { 'procParams': { 'clusterAuthMode': 'x509', 'setParameter': { 'authenticationMechanisms': 'MONGODB-X509' } } } } config = { 'login': TEST_SUBJECT, 'authSource': '$external', 'configsvrs': self.x509_configsvrs, 'routers': [{ 'clusterAuthMode': 'x509' }], 'shards': [shard_params, shard_params], 'sslParams': { 'sslCAFile': certificate('ca.pem'), 'sslPEMKeyFile': certificate('server.pem'), 'sslMode': 'requireSSL', 'sslClusterFile': certificate('cluster_cert.pem'), 'sslAllowInvalidCertificates': True } } self.sh = ShardedCluster(config) self.assertIn('mongodb_auth_uri', self.sh.info()) auth_uri = self.sh.info()['mongodb_auth_uri'] hosts = ','.join(r['hostname'] for r in self.sh.routers) self.assertIn(hosts, auth_uri) self.assertIn(TEST_SUBJECT, auth_uri) self.assertIn('authSource=$external', auth_uri) self.assertIn('authMechanism=MONGODB-X509', auth_uri)