def test_get_servers_from_scope_more_than_min_quorum( self, mock_get_now, mock_app): mock_get_now.return_value = dt.datetime(2019, 4, 1, tzinfo=dt.timezone.utc) Server.set_initial() servers = [] for i in range(0, 7): s = Server(f'node{i}', port=5000, created_on=old_age) if i == 0: r = Route(s, cost=0) else: r = Route(s, random.choice(servers), cost=i) db.session.add_all([s, r]) servers.append(s) mock_get_now.return_value = dt.datetime(2019, 4, 2, tzinfo=dt.timezone.utc) mock_app.dm.cluster_manager.get_alive.return_value = [ s.id for s in servers ] s62 = Server(f'node72', port=5000) Route(s62, random.choice(servers), cost=6) db.session.add(s62) quorum = get_servers_from_scope(scope=Scope.CATALOG) self.assertEqual(8, len(quorum)) self.assertNotIn(s62, quorum) self.assertIn(s, quorum) self.assertIn(Server.get_current(), quorum)
def setUp(self): self.maxDiff = None """Create and configure a new app instance for each test.""" # create the app with common test config self.app = create_app('test') self.app_context = self.app.app_context() self.app_context.push() self.client = self.app.test_client() self.auth = HTTPBearerAuth( create_access_token('00000000-0000-0000-0000-000000000001')) db.create_all() self.src = Server('source', port=5000, id='00000000-0000-0000-0000-000000000000') self.dst1 = Server('destination1', port=5000, id='00000000-0000-0000-0000-000000000001') self.dst2 = Server('destination2', port=5000, id='00000000-0000-0000-0000-000000000002') self.dst3 = Server('destination3', port=5000, id='00000000-0000-0000-0000-000000000003') db.session.add_all([self.src, self.dst1, self.dst2, self.dst3])
def test_url(self, mock_url, mock_check_host): self.set_servers_and_routes() mock_check_host.return_value = True self.assertEqual(f'https://1.1.1.1:{defaults.DEFAULT_PORT}', self.n1.url()) self.assertEqual(f'https://n2_dns:{defaults.DEFAULT_PORT}', self.n2.url()) self.assertEqual(f'https://n3:8000', self.n3.url()) self.assertEqual(f'https://1.1.1.1:{defaults.DEFAULT_PORT}', self.r1.url()) self.assertEqual(f'https://n2_dns:{defaults.DEFAULT_PORT}', self.r2.url()) mock_url.return_value = '/' self.assertEqual(f'https://1.1.1.1:{defaults.DEFAULT_PORT}/', self.n1.url('api')) mock_url.assert_called_once_with('api') me = Server(name='me', gates=[('127.0.0.1', 5), ('192.168.1.2', 2)], me=True) self.assertEqual(f'https://127.0.0.1:5/', me.url('api')) with mock.patch('dimensigon.domain.entities.server.current_app' ) as mock_current_app: type(mock_current_app.dm.config).http_config = mock.PropertyMock( return_value={'keyfile': 'x'}) me = Server(name='me', gates=[('192.168.1.2', 2)], me=True) self.assertEqual(f'http://192.168.1.2:2/', me.url('api')) s = Server('test', port=8000) with self.assertRaises(errors.UnreachableDestination): s.url()
def test_execute_send_software_no_ssa(self, mock_get): at = ActionTemplate.query.get('00000000-0000-0000-000a-000000000001') soft = Software(name='test', version=1, filename='test.zip') node1 = Server('nodeA', port=5000) db.session.add_all([soft, node1]) mock_get.return_value = Response(code=400) ro = NativeSoftwareSendOperation(code, expected_stdout=at.expected_stdout, expected_stderr=at.expected_stderr, expected_rc=at.expected_rc) cp = ro._execute(dict(input=dict(software=soft.id, server=self.s1.id)), context=self.context) self.assertFalse(cp.success) self.assertEqual(f'{soft.id} has no server association', cp.stderr)
def test_upgrade_catalog_catalog_mismatch(self, mock_lock, mock_entities): mock_lock.return_value.__enter__.return_value = 'applicant' mock_entities.return_value = [('ActionTemplate', ActionTemplate), ('Server', Server)] s = Server('server', last_modified_at=dt.datetime(2019, 4, 1, tzinfo=dt.timezone.utc), port=8000) Route(s, cost=0) at1 = ActionTemplate(id='aaaaaaaa-1234-5678-1234-56781234aaa1', name='mkdir', version=1, action_type=ActionType.SHELL, code='mkdir {dir}', expected_output=None, expected_rc=None, system_kwargs={}, last_modified_at=dt.datetime( 2019, 4, 1, tzinfo=dt.timezone.utc)) at2 = ActionTemplate(id='aaaaaaaa-1234-5678-1234-56781234aaa2', name='rmdir', version=1, action_type=ActionType.SHELL, code='rmdir {dir}', expected_output=None, expected_rc=None, system_kwargs={}, last_modified_at=dt.datetime( 2019, 4, 2, tzinfo=dt.timezone.utc)) responses.add( method='GET', url=re.compile('^' + s.url( 'api_1_0.catalog', data_mark='12345').replace('12345', '')), json={"ActionTemplate": [at1.to_json(), at2.to_json()]}) with self.assertRaises(errors.CatalogMismatch): upgrade_catalog_from_server(s)
def setUp(self): """Create and configure a new self.app instance for each test.""" # create a temporary file to isolate the database for each test # create the self.app with common test config self.app = Flask(__name__) @self.app.route('/', methods=['GET', 'POST']) @securizer def hello(): return request.get_json() or {'msg': 'default response'} @self.app.route('/join', methods=['POST']) @securizer def join(): return {'msg': 'default response'} @self.app.route('/empty', methods=['GET']) @securizer def empty(): return "", 204 @self.app.route('/list', methods=['GET']) @securizer def list(): return [1, 2], 200 self.app.config['SECURIZER'] = True self.app.config['SECURIZER_PLAIN'] = True self.app_context = self.app.app_context() self.app_context.push() self.client = self.app.test_client() db.init_app(self.app) db.create_all() self.d = generate_dimension('test') self.d.current = True self.srv1 = Server(id='bbbbbbbb-1234-5678-1234-56781234bbb1', name='server1', dns_or_ip='192.168.1.9', port=7123, me=True) Route(self.srv1, cost=0) db.session.add_all([self.srv1, self.d]) db.session.commit()
def test_execute_send_software_no_destination_server(self): at = ActionTemplate.query.get('00000000-0000-0000-000a-000000000001') soft = Software(name='test', version='1', filename='test.zip') soft2 = Software(name='test', version='2', filename='test.zip') node1 = Server('nodeA', port=5000) ssa1 = SoftwareServerAssociation(software=soft2, server=node1, path='/') db.session.add_all([soft, soft2, node1, ssa1]) ro = NativeSoftwareSendOperation(code, expected_stdout=at.expected_stdout, expected_stderr=at.expected_stderr, expected_rc=at.expected_rc) cp = ro._execute(dict(input=dict(software='test', server='a')), context=self.context) self.assertFalse(cp.success) self.assertEqual(f"destination server 'a' not found", cp.stderr)
def _fill_database(self): with mock.patch('dimensigon.domain.entities.get_now') as mock_get_now: mock_get_now.return_value = defaults.INITIAL_DATEMARK db.create_all() event.listen(db.session, 'after_commit', receive_after_commit) set_initial(**self.initials) d = Dimension.from_json(self.dim) d.current = True self.s1 = Server('node1', created_on=defaults.INITIAL_DATEMARK, id=self.SERVER, me=True) self.g11 = Gate(id='00000000-0000-0000-0000-000000000011', server=self.s1, port=5000, dns=self.s1.name) self.fill_database() db.session.add_all([d, self.s1]) db.session.commit()
def test__notify_cluster_in(self, mock_get_root_auth, mock_post, mock_get_now): mock_get_root_auth.return_value = 'auth' mock_post.side_effect = [ ntwrk.Response(code=200, msg={ 'cluster': [(1, now.strftime(defaults.DATEMARK_FORMAT), False), (2, now.strftime(defaults.DATEMARK_FORMAT), False)], 'neighbours': [1, 2] }) ] mock_get_now.return_value = now s2 = Server('node2', port=5000) s2.set_route(None, gate=s2.gates[0], cost=0) db.session.add(s2) self.cm._route_initiated = mock.Mock() self.cm._notify_cluster_in() self.cm.main_func() self.assertDictEqual( { 1: _Entry(id=1, keepalive=now, death=False), 2: _Entry(id=2, keepalive=now, death=False) }, self.cm._registry) routes = [s2.route.to_json()] mock_post.assert_called_once_with( s2, 'api_1_0.cluster_in', view_data=dict(server_id=str(self.s1.id)), json=dict(keepalive=now.strftime(defaults.DATEMARK_FORMAT), routes=routes), timeout=10, auth='auth')
def test_upgrade_catalog_no_data(self, mock_lock, mock_entities): mock_lock.return_value.__enter__.return_value = 'applicant' mock_entities.return_value = [('ActionTemplate', ActionTemplate)] s = Server('server', last_modified_at=dt.datetime(2019, 4, 1, tzinfo=dt.timezone.utc)) g = Gate(server=s, port=80) Route(s, cost=0) responses.add( method='GET', url=re.compile('^' + s.url( 'api_1_0.catalog', data_mark='12345').replace('12345', '')), json={"ActionTemplate": []}) upgrade_catalog_from_server(s) atl = [at.to_json() for at in ActionTemplate.query.all()] self.assertEqual(0, len(atl))
def setUp(self): """Create and configure a new app instance for each test.""" # create the app with common test config super().setUp() self.source_path = '/software' self.filename = 'filename.zip' self.content = b'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789' self.size = len(self.content) self.checksum = hashlib.md5(self.content).hexdigest() self.dest_path = '/dest_repo' self.soft = Software(name='test_software', version=1, filename=self.filename, size=self.size, checksum=self.checksum) self.ssa = SoftwareServerAssociation(software=self.soft, server=self.s1, path=self.source_path) self.node2 = Server('node2', port=5000) db.session.add_all([self.soft, self.ssa, self.node2]) db.session.commit()
def test_get_reachable_servers(self): n1 = Server('n1', port=8000, id='22cd859d-ee91-4079-a112-000000000001') n2 = Server('n2', port=8000, id='22cd859d-ee91-4079-a112-000000000002') n3 = Server('n3', port=8000, id='22cd859d-ee91-4079-a112-000000000003') n3.route = None n4 = Server('n4', port=8000, id='22cd859d-ee91-4079-a112-000000000004') r1 = Server('r1', port=8000, id='22cd859d-ee91-4079-a112-000000000011') Route(destination=n1, cost=0) Route(destination=n2, proxy_server_or_gate=n2.gates[0]) Route(destination=n4) Route(destination=r1, proxy_server_or_gate=n1, cost=1) me = Server('me', port=8000, me=True) db.session.add_all([n1, n2, n3, n4, r1, me]) self.assertListEqual([n1, n2, r1], me.get_reachable_servers()) self.assertListEqual([n2, r1], me.get_reachable_servers(exclude=n1)) self.assertListEqual([n2, r1], me.get_reachable_servers(exclude=n1.id)) self.assertListEqual([r1], me.get_reachable_servers(exclude=[n1.id, n2]))
def test_create_server_dict_gate(self, mock_gate): dest = Server('dest', gates=[{'id': 1}]) mock_gate.from_json.called_once_with({'id': 1})
def test_upgrade_catalog(self, mock_lock, mock_entities, mock_now, mock_tzlocal): mock_lock.return_value.__enter__.return_value = 'applicant' mock_entities.return_value = [('ActionTemplate', ActionTemplate), ('Server', Server), ('Gate', Gate)] mock_now.return_value = dt.datetime(2019, 4, 1, tzinfo=dt.timezone.utc) mock_tzlocal.return_value = dt.timezone.utc at1 = ActionTemplate(id='aaaaaaaa-1234-5678-1234-56781234aaa1', name='mkdir', version=1, action_type=ActionType.SHELL, code='mkdir {dir}', expected_output=None, expected_rc=None, system_kwargs={}) db.session.add(at1) db.session.commit() s = Server(id='aaaaaaaa-1234-5678-1234-56781234bbb1', name='server', last_modified_at=dt.datetime(2019, 4, 1, tzinfo=dt.timezone.utc)) s_json = s.to_json() g = Gate(server=s, port=80, dns='server', last_modified_at=dt.datetime(2019, 4, 1, tzinfo=dt.timezone.utc)) g_json = g.to_json() Route(s, cost=0) at2 = ActionTemplate(id='aaaaaaaa-1234-5678-1234-56781234aaa2', name='rmdir', version=1, action_type=ActionType.SHELL, code='rmdir {dir}', expected_output=None, expected_rc=None, system_kwargs={}, last_modified_at=dt.datetime( 2019, 4, 2, tzinfo=dt.timezone.utc)) at2_json = at2.to_json() del at2 at1_json = at1.to_json() del at1 at1_json['code'] = 'mkdir -p {dir}' responses.add( method='GET', url=re.compile('^' + s.url( 'api_1_0.catalog', data_mark='12345').replace('12345', '')), json={ "ActionTemplate": [at1_json, at2_json], "Server": [s_json], "Gate": [g_json] }) upgrade_catalog_from_server(s) db.session.expire_all() atl = [at.to_json() for at in ActionTemplate.query.all()] self.assertListEqual([at1_json, at2_json], atl) c = Catalog.query.get('ActionTemplate') self.assertEqual(dt.datetime(2019, 4, 2, tzinfo=dt.timezone.utc), c.last_modified_at) at1 = ActionTemplate.query.get('aaaaaaaa-1234-5678-1234-56781234aaa1') self.assertEqual('mkdir -p {dir}', at.code)
def test_create_cmd_from_orchestration(self): at = ActionTemplate(id='aaaaaaaa-1234-5678-1234-aaaaaaaa0001', name='create dir', version=1, action_type=ActionType.SHELL, code='mkdir {{dir}}', expected_stdout='', expected_rc=0, system_kwargs={}) o = Orchestration('Test Orchestration', 1, 'description', id='bbbbbbbb-1234-5678-1234-bbbbbbbb0001') me = Server('me', port=5000, me=True, id='cccccccc-1234-5678-1234-cccccccc0001') remote = Server('remote', port=5000, id='cccccccc-1234-5678-1234-cccccccc0002') db.session.add_all([me, remote, o]) s1 = o.add_step(id='eeeeeeee-1234-5678-1234-eeeeeeee0001', undo=False, action_template=at, parents=[], target=['frontend']) s2 = o.add_step(id='eeeeeeee-1234-5678-1234-eeeeeeee0002', undo=True, action_template=at, parents=[s1], stop_on_error=False, target=[]) s3 = o.add_step(id='eeeeeeee-1234-5678-1234-eeeeeeee0003', undo=False, action_template=at, parents=[s1], stop_on_error=False, stop_undo_on_error=False, target=['frontend']) s4 = o.add_step(id='eeeeeeee-1234-5678-1234-eeeeeeee0004', undo=True, action_template=at, parents=[s3], target=[]) s5 = o.add_step(id='eeeeeeee-1234-5678-1234-eeeeeeee0005', undo=True, action_template=at, parents=[s4], stop_on_error=True, target=[]) s6 = o.add_step(id='eeeeeeee-1234-5678-1234-eeeeeeee0006', undo=True, action_template=at, parents=[s4, s5], target=[]) s7 = o.add_step(id='eeeeeeee-1234-5678-1234-eeeeeeee0007', undo=False, action_template=at, parents=[s3], undo_on_error=False, target=[]) s8 = o.add_step(id='eeeeeeee-1234-5678-1234-eeeeeeee0008', undo=True, action_template=at, parents=[s7], target=[]) s9 = o.add_step(id='eeeeeeee-1234-5678-1234-eeeeeeee0009', undo=False, action_template=at, children=[s2, s3], target=['backend']) cc = create_cmd_from_orchestration(o, Context({'dir': 'C:\\test_folder'}), hosts={ 'all': [me.id, remote.id], 'frontend': [me.id], 'backend': [remote.id] }, executor=None, register=mock.Mock()) c1, c9 = cc._dag.get_nodes_at_level(1) self.assertTupleEqual(('cccccccc-1234-5678-1234-cccccccc0001', 'eeeeeeee-1234-5678-1234-eeeeeeee0001'), c1.id) self.assertIsInstance(c1, Command) self.assertTrue(c1.stop_on_error) self.assertTrue(c1.undo_on_error) self.assertIsNone(c1.stop_undo_on_error) self.assertTupleEqual(('cccccccc-1234-5678-1234-cccccccc0002', 'eeeeeeee-1234-5678-1234-eeeeeeee0009'), c9.id) self.assertIsInstance(c9, ProxyCommand) self.assertTrue(c9.stop_on_error) self.assertTrue(c9.undo_on_error) self.assertIsNone(c9.stop_undo_on_error) c21 = c1.undo_command self.assertTupleEqual(('cccccccc-1234-5678-1234-cccccccc0001', 'eeeeeeee-1234-5678-1234-eeeeeeee0002'), c21.id) self.assertIsInstance(c21, UndoCommand) self.assertFalse(c21.stop_on_error) c22 = c9.undo_command self.assertTupleEqual(('cccccccc-1234-5678-1234-cccccccc0002', 'eeeeeeee-1234-5678-1234-eeeeeeee0002'), c22.id) self.assertIsInstance(c22, ProxyUndoCommand) self.assertFalse(c22.stop_on_error) c3, = cc._dag.get_nodes_at_level(2) self.assertTupleEqual(('cccccccc-1234-5678-1234-cccccccc0001', 'eeeeeeee-1234-5678-1234-eeeeeeee0003'), c3.id) self.assertIsInstance(c3, Command) self.assertFalse(c3.stop_on_error) self.assertTrue(c3.undo_on_error) self.assertFalse(c3.stop_undo_on_error) self.assertTupleEqual(('undo', 'eeeeeeee-1234-5678-1234-eeeeeeee0003'), c3.undo_command.id) self.assertIsInstance(c3.undo_command, CompositeCommand) self.assertFalse(c3.undo_command.stop_on_error) self.assertIsNone(c3.undo_command.stop_undo_on_error) c4, = c3.undo_command._dag.get_nodes_at_level(1) self.assertIsInstance(c4, UndoCommand) self.assertFalse(c4.stop_on_error) c5, = c3.undo_command._dag.get_nodes_at_level(2) self.assertIsInstance(c5, UndoCommand) self.assertTrue(c5.stop_on_error) c6, = c3.undo_command._dag.get_nodes_at_level(3) self.assertIsInstance(c6, UndoCommand) self.assertFalse(c6.stop_on_error) cc7, = cc._dag.get_nodes_at_level(3) self.assertEqual('eeeeeeee-1234-5678-1234-eeeeeeee0007', cc7.id) self.assertIsInstance(cc7, CompositeCommand) self.assertFalse(cc7.stop_on_error) self.assertFalse(cc7.stop_undo_on_error) c71, c72 = cc7._dag.root self.assertTupleEqual(('cccccccc-1234-5678-1234-cccccccc0001', 'eeeeeeee-1234-5678-1234-eeeeeeee0007'), c71.id) self.assertIsInstance(c71, Command) self.assertTrue(c71.stop_on_error) self.assertFalse(c71.undo_on_error) self.assertIsNone(c71.stop_undo_on_error) self.assertTupleEqual(('cccccccc-1234-5678-1234-cccccccc0001', 'eeeeeeee-1234-5678-1234-eeeeeeee0008'), c71.undo_command.id) self.assertIsInstance(c71.undo_command, UndoCommand) self.assertTrue(c71.undo_command.stop_on_error) self.assertTupleEqual(('cccccccc-1234-5678-1234-cccccccc0002', 'eeeeeeee-1234-5678-1234-eeeeeeee0007'), c72.id) self.assertIsInstance(c72, ProxyCommand) self.assertTrue(c72.stop_on_error) self.assertFalse(c72.undo_on_error) self.assertIsNone(c72.stop_undo_on_error) self.assertTupleEqual(('cccccccc-1234-5678-1234-cccccccc0002', 'eeeeeeee-1234-5678-1234-eeeeeeee0008'), c72.undo_command.id) self.assertIsInstance(c72.undo_command, ProxyUndoCommand) self.assertTrue(c72.undo_command.stop_on_error)
def test_to_from_json(self): s = Server('test') g = Gate(server=s, dns='dns', port=8) g_json = g.to_json() self.assertEqual(g.dns, g_json['dns']) self.assertEqual(g.ip, g_json['ip']) self.assertEqual(g.port, g_json['port']) self.assertIsNotNone(g_json['server_id']) # set id to resolve server_id from gate object s = Server('test', id='aaaaaaaa-1234-5678-1234-56781234aaa1') g = Gate(server=s, dns='dns', port=8, id='aaaaaaaa-1234-5678-1234-56781234aaa2') g_json = g.to_json(no_delete=True) self.assertDictEqual( { 'server_id': 'aaaaaaaa-1234-5678-1234-56781234aaa1', 'dns': 'dns', 'ip': None, 'port': 8, 'hidden': False, 'id': 'aaaaaaaa-1234-5678-1234-56781234aaa2' }, g_json) with self.assertRaises(NoResultFound): smashed = Gate.from_json(g_json) s = Server('test2', id='aaaaaaaa-1234-5678-1234-56781234aaa1') db.session.add(s) g_smashed = Gate.from_json(g_json) self.assertIsNot(g, g_smashed) self.assertEqual(g.dns, g_smashed.dns) self.assertEqual(g.ip, g_smashed.ip) self.assertEqual(g.port, g_smashed.port) self.assertIs(s, g_smashed.server) db.session.add(g_smashed) db.session.commit() g_json = g.to_json(no_delete=True) self.assertEqual( { 'id': 'aaaaaaaa-1234-5678-1234-56781234aaa2', 'server_id': 'aaaaaaaa-1234-5678-1234-56781234aaa1', 'dns': 'dns', 'ip': None, 'port': 8, 'hidden': False }, g_json) # check from_json when persisted in database smashed = Gate.from_json(g_json) self.assertIs(g_smashed, smashed) self.assertEqual(g_smashed.server, smashed.server) self.assertEqual(g_smashed.dns, smashed.dns) self.assertEqual(g_smashed.ip, smashed.ip) self.assertEqual(g_smashed.port, smashed.port)
def test_route(self): dest = Server('dest', port=80) proxy = Server('proxy', port=80) r = Route(destination=dest) self.assertEqual(dest, r.destination) self.assertIsNone(r.proxy_server) self.assertIsNone(r.gate) self.assertIsNone(r.cost) # routes defined with a gate ## dest r = Route(destination=dest, proxy_server_or_gate=dest.gates[0]) self.assertEqual(dest, r.destination) self.assertIsNone(r.proxy_server) self.assertEqual(dest.gates[0], r.gate) self.assertEqual(0, r.cost) r = Route(destination=dest, proxy_server_or_gate=dest.gates[0], cost=0) self.assertEqual(dest, r.destination) self.assertIsNone(r.proxy_server) self.assertEqual(dest.gates[0], r.gate) self.assertEqual(0, r.cost) with self.assertRaises(ValueError): r = Route(destination=dest, proxy_server_or_gate=dest.gates[0], cost=1) ## proxy with self.assertRaises(ValueError): Route(destination=dest, proxy_server_or_gate=proxy.gates[0]) with self.assertRaises(ValueError): Route(destination=dest, proxy_server_or_gate=proxy.gates[0], cost=0) r = Route(destination=dest, proxy_server_or_gate=proxy.gates[0], cost=1) self.assertEqual(dest, r.destination) self.assertEqual(proxy, r.proxy_server) self.assertIsNone(r.gate) self.assertEqual(1, r.cost) # routes defined with a proxy server ## dest with self.assertRaises(ValueError): r = Route(destination=dest, proxy_server_or_gate=dest) with self.assertRaises(ValueError): r = Route(destination=dest, proxy_server_or_gate=dest, cost=0) with self.assertRaises(ValueError): r = Route(destination=dest, proxy_server_or_gate=dest, cost=1) ## proxy with self.assertRaises(ValueError): r = Route(destination=dest, proxy_server_or_gate=proxy) with self.assertRaises(ValueError): r = Route(destination=dest, proxy_server_or_gate=proxy, cost=0) r = Route(destination=dest, proxy_server_or_gate=proxy, cost=1) self.assertEqual(dest, r.destination) self.assertEqual(proxy, r.proxy_server) self.assertIsNone(r.gate) self.assertEqual(1, r.cost)