# Tests for mongodb_replica_set ansible module # # How to run these tests: # 1. move this file to playbooks/library # 2. rename mongodb_replica_set to mongodb_replica_set.py # 3. python test_mongodb_replica_set.py import mongodb_replica_set as mrs import unittest, mock from urllib import quote_plus from copy import deepcopy class TestNoPatchingMongodbReplicaSet(unittest.TestCase): def test_host_port_transformation(self): unfixed = { 'members': [ {'host': 'foo.bar'}, {'host': 'bar.baz', 'port': 1234}, {'host': 'baz.bing:54321'} ]} fixed = { 'members': [ {'host': 'foo.bar:27017'}, {'host': 'bar.baz:1234'}, {'host': 'baz.bing:54321'} ]} mrs.fix_host_port(unfixed) self.assertEqual(fixed, unfixed) fixed_2 = deepcopy(fixed) mrs.fix_host_port(fixed_2) self.assertEqual(fixed, fixed_2) def test_member_id_managed(self): new = [ {'host': 'foo.bar', '_id': 1}, {'host': 'bar.baz'}, {'host': 'baz.bing'} ] old = [ {'host': 'baz.bing', '_id': 0} ] fixed = deepcopy(new) mrs.set_member_ids(fixed, old) #test that each id is unique unique_ids = {m['_id'] for m in fixed} self.assertEqual(len(unique_ids), len(new)) #test that it "prefers" the "matching" one in old_members self.assertEqual(fixed[0]['_id'], new[0]['_id']) self.assertEqual(fixed[2]['_id'], old[0]['_id']) self.assertIn('_id', fixed[1]) def test_mongo_uri_escaped(self): host = username = password = auth_database = ':!@#$%/' port = 1234 uri = mrs.get_mongo_uri(host=host, port=port, username=username, password=password, auth_database=auth_database) self.assertEqual(uri, "mongodb://{un}:{pw}@{host}:{port}/{db}".format( un=quote_plus(username), pw=quote_plus(password), host=quote_plus(host), port=port, db=quote_plus(auth_database), )) rs_id = 'a replset id' members = [ {'host': 'foo.bar:1234'}, {'host': 'bar.baz:4321'}, ] old_rs_config = { 'version': 1, '_id': rs_id, 'members': [ {'_id': 0, 'host': 'foo.bar:1234',}, {'_id': 1, 'host': 'bar.baz:4321',}, ] } new_rs_config = { 'version': 2, '_id': rs_id, 'members': [ {'_id': 0, 'host': 'foo.bar:1234',}, {'_id': 1, 'host': 'bar.baz:4321',}, {'_id': 2, 'host': 'baz.bing:27017',}, ] } rs_config = { 'members': [ {'host': 'foo.bar', 'port': 1234,}, {'host': 'bar.baz', 'port': 4321,}, {'host': 'baz.bing', 'port': 27017,}, ] } def init_replset_mock(f): get_replset_initialize_mock = mock.patch.object(mrs, 'get_replset', side_effect=(None, deepcopy(new_rs_config))) initialize_replset_mock = mock.patch.object(mrs, 'initialize_replset') return get_replset_initialize_mock(initialize_replset_mock(f)) def update_replset_mock(f): get_replset_update_mock = mock.patch.object(mrs, 'get_replset', side_effect=(deepcopy(old_rs_config), deepcopy(new_rs_config))) reconfig_replset_mock = mock.patch.object(mrs, 'reconfig_replset') return get_replset_update_mock(reconfig_replset_mock(f)) @mock.patch.object(mrs, 'get_rs_config_id', return_value=rs_id) @mock.patch.object(mrs, 'client', create=True) @mock.patch.object(mrs, 'module', create=True) class TestPatchingMongodbReplicaSet(unittest.TestCase): @update_replset_mock def test_version_managed(self, _1, _2, module, *args): # Version set automatically on initialize mrs.update_replset(deepcopy(rs_config)) new_version = module.exit_json.call_args[1]['config']['version'] self.assertEqual(old_rs_config['version'], new_version - 1) @init_replset_mock def test_doc_id_managed_on_initialize(self, _1, _2, module, *args): #old_rs_config provided by init_replset_mock via mrs.get_replset(). #That returns None on the first call, so it falls through to get_rs_config_id(), #which is also mocked. mrs.update_replset(deepcopy(rs_config)) new_id = module.exit_json.call_args[1]['config']['_id'] self.assertEqual(rs_id, new_id) @update_replset_mock def test_doc_id_managed_on_update(self, _1, _2, module, *args): #old_rs_config provided by update_replset_mock via mrs.get_replset() mrs.update_replset(deepcopy(rs_config)) new_id = module.exit_json.call_args[1]['config']['_id'] self.assertEqual(rs_id, new_id) @init_replset_mock def test_initialize_if_necessary(self, initialize_replset, _2, module, *args): mrs.update_replset(deepcopy(rs_config)) self.assertTrue(initialize_replset.called) #self.assertFalse(reconfig_replset.called) @update_replset_mock def test_reconfig_if_necessary(self, reconfig_replset, _2, module, *args): mrs.update_replset(deepcopy(rs_config)) self.assertTrue(reconfig_replset.called) #self.assertFalse(initialize_replset.called) @update_replset_mock def test_not_changed_when_docs_match(self, _1, _2, module, *args): rs_config = {'members': members} #This way the docs "match", but aren't identical mrs.update_replset(deepcopy(rs_config)) changed = module.exit_json.call_args[1]['changed'] self.assertFalse(changed) @update_replset_mock def test_ignores_magic_given_full_doc(self, _1, _2, module, _3, get_rs_config_id, *args): mrs.update_replset(deepcopy(new_rs_config)) new_doc = module.exit_json.call_args[1]['config'] self.assertEqual(new_doc, new_rs_config) self.assertFalse(get_rs_config_id.called) if __name__ == '__main__': unittest.main()