synapse 2.195.0__py311-none-any.whl → 2.196.0__py311-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of synapse might be problematic. Click here for more details.

Files changed (46) hide show
  1. synapse/axon.py +72 -5
  2. synapse/common.py +23 -0
  3. synapse/cortex.py +1 -0
  4. synapse/daemon.py +1 -0
  5. synapse/lib/aha.py +159 -4
  6. synapse/lib/cell.py +133 -8
  7. synapse/lib/jsonstor.py +2 -1
  8. synapse/lib/modelrev.py +5 -1
  9. synapse/lib/nexus.py +13 -6
  10. synapse/lib/reflect.py +4 -5
  11. synapse/lib/snap.py +14 -7
  12. synapse/lib/stormlib/aha.py +351 -1
  13. synapse/lib/stormlib/utils.py +37 -0
  14. synapse/lib/stormtypes.py +124 -6
  15. synapse/lib/version.py +2 -2
  16. synapse/models/base.py +3 -0
  17. synapse/models/infotech.py +55 -16
  18. synapse/models/orgs.py +14 -10
  19. synapse/models/risk.py +23 -10
  20. synapse/models/transport.py +8 -3
  21. synapse/telepath.py +12 -0
  22. synapse/tests/test_axon.py +23 -0
  23. synapse/tests/test_common.py +28 -0
  24. synapse/tests/test_datamodel.py +8 -0
  25. synapse/tests/test_lib_aha.py +241 -0
  26. synapse/tests/test_lib_cell.py +61 -0
  27. synapse/tests/test_lib_jsonstor.py +1 -0
  28. synapse/tests/test_lib_modelrev.py +6 -0
  29. synapse/tests/test_lib_nexus.py +24 -2
  30. synapse/tests/test_lib_stormlib_aha.py +188 -0
  31. synapse/tests/test_lib_stormlib_utils.py +14 -0
  32. synapse/tests/test_lib_stormtypes.py +90 -3
  33. synapse/tests/test_model_base.py +2 -0
  34. synapse/tests/test_model_infotech.py +28 -1
  35. synapse/tests/test_model_orgs.py +2 -0
  36. synapse/tests/test_model_risk.py +2 -0
  37. synapse/tests/test_model_transport.py +1 -0
  38. synapse/tests/test_telepath.py +26 -0
  39. synapse/tests/test_tools_aha.py +192 -0
  40. synapse/tools/aha/mirror.py +193 -0
  41. synapse/tools/changelog.py +32 -27
  42. {synapse-2.195.0.dist-info → synapse-2.196.0.dist-info}/METADATA +1 -1
  43. {synapse-2.195.0.dist-info → synapse-2.196.0.dist-info}/RECORD +46 -43
  44. {synapse-2.195.0.dist-info → synapse-2.196.0.dist-info}/LICENSE +0 -0
  45. {synapse-2.195.0.dist-info → synapse-2.196.0.dist-info}/WHEEL +0 -0
  46. {synapse-2.195.0.dist-info → synapse-2.196.0.dist-info}/top_level.txt +0 -0
@@ -828,6 +828,33 @@ class AhaTest(s_test.SynTest):
828
828
  async with await s_telepath.openurl(url) as prox:
829
829
  self.fail(f'Connected to an expired clone URL {url}') # pragma: no cover
830
830
 
831
+ async def test_lib_aha_mirrors(self):
832
+
833
+ async with self.getTestAha() as aha:
834
+ async with await s_base.Base.anit() as base:
835
+ with self.getTestDir() as dirn:
836
+ user = 'synuser'
837
+ dirn00 = s_common.genpath(dirn, 'cell00')
838
+ dirn01 = s_common.genpath(dirn, 'cell01')
839
+
840
+ core00 = await base.enter_context(self.addSvcToAha(aha, '00.cortex', s_cortex.Cortex, dirn=dirn00,
841
+ provinfo={'conf': {'aha:user': user}}))
842
+ self.eq(core00.conf.get('aha:user'), user)
843
+
844
+ core01 = await base.enter_context(self.addSvcToAha(aha, '01.cortex', s_cortex.Cortex, dirn=dirn01,
845
+ conf={'axon': 'aha://cortex...'},
846
+ provinfo={'conf': {'aha:user': user}}))
847
+ self.eq(core01.conf.get('aha:user'), user)
848
+
849
+ async with aha.getLocalProxy() as ahaproxy:
850
+ self.eq(None, await ahaproxy.getAhaSvcMirrors('99.bogus'))
851
+ self.len(1, await ahaproxy.getAhaSvcMirrors('00.cortex.synapse'))
852
+ self.nn(await ahaproxy.getAhaServer(host=aha._getDnsName(), port=aha.sockaddr[1]))
853
+
854
+ todo = s_common.todo('getCellInfo')
855
+ res = await asyncio.wait_for(await aha.callAhaSvcApi('00.cortex.synapse', todo, timeout=3), 3)
856
+ self.nn(res)
857
+
831
858
  async def test_aha_httpapi(self):
832
859
 
833
860
  async with self.getTestAha() as aha:
@@ -905,6 +932,10 @@ class AhaTest(s_test.SynTest):
905
932
  info = await resp.json()
906
933
  self.eq(info.get('status'), 'err')
907
934
  self.eq(info.get('code'), 'SchemaViolation')
935
+ async with sess.post(url, json={'name': 'doom' * 16}) as resp:
936
+ info = await resp.json()
937
+ self.eq(info.get('status'), 'err')
938
+ self.eq(info.get('code'), 'BadArg')
908
939
 
909
940
  # Not an admin
910
941
  await aha.addUser('lowuser', passwd='lowuser')
@@ -1093,6 +1124,35 @@ class AhaTest(s_test.SynTest):
1093
1124
  self.stormHasNoWarnErr(msgs)
1094
1125
  self.stormIsInPrint('Removed AHA service pool: pool00.synapse', msgs)
1095
1126
 
1127
+ async def test_aha_svc_api_exception(self):
1128
+
1129
+ async with self.getTestAha() as aha:
1130
+
1131
+ async def mockGetAhaSvcProxy(*args, **kwargs):
1132
+ raise s_exc.SynErr(mesg='proxy error')
1133
+
1134
+ aha.getAhaSvcProxy = mockGetAhaSvcProxy
1135
+ name = '00.cortex.synapse'
1136
+ todo = ('bogus', (), {})
1137
+ retn = await asyncio.wait_for(await aha.callAhaSvcApi(name, todo), 3)
1138
+
1139
+ self.false(retn[0])
1140
+ self.eq('SynErr', retn[1].get('err'))
1141
+ self.eq('proxy error', retn[1].get('errinfo').get('mesg'))
1142
+
1143
+ bad_info = {
1144
+ 'urlinfo': {
1145
+ 'host': 'nonexistent.host',
1146
+ 'port': 12345,
1147
+ 'scheme': 'ssl'
1148
+ }
1149
+ }
1150
+
1151
+ await aha.addAhaSvc(name, bad_info)
1152
+ async for ok, info in aha.callAhaPeerGenr(name, ('nonexistent.method', (), {})):
1153
+ self.false(ok)
1154
+ self.isin('err', info)
1155
+
1096
1156
  async def test_aha_reprovision(self):
1097
1157
 
1098
1158
  with self.withNexusReplay() as stack:
@@ -1317,3 +1377,184 @@ class AhaTest(s_test.SynTest):
1317
1377
  async with await s_telepath.openurl(provurl) as prox:
1318
1378
  info = await prox.getUserInfo()
1319
1379
  self.eq(info.get('aha:user'), 'bob.grey')
1380
+
1381
+ async def test_aha_gather(self):
1382
+
1383
+ async with self.getTestAha() as aha:
1384
+
1385
+ async with aha.waiter(3, 'aha:svcadd', timeout=10):
1386
+
1387
+ conf = {'aha:provision': await aha.addAhaSvcProv('00.cell')}
1388
+ cell00 = await aha.enter_context(self.getTestCell(conf=conf))
1389
+
1390
+ conf = {'aha:provision': await aha.addAhaSvcProv('01.cell', {'mirror': 'cell'})}
1391
+ cell01 = await aha.enter_context(self.getTestCell(conf=conf))
1392
+
1393
+ await cell01.sync()
1394
+
1395
+ async with cell01.getLocalProxy() as proxy:
1396
+ self.true(proxy._hasTeleFeat('dynmirror'))
1397
+ self.true(proxy._hasTeleMeth('getNexsIndx'))
1398
+
1399
+ nexsindx = await cell00.getNexsIndx()
1400
+
1401
+ # test the call endpoint
1402
+ todo = s_common.todo('getCellInfo')
1403
+ items = dict([item async for item in aha.callAhaPeerApi(cell00.iden, todo, timeout=3)])
1404
+ self.sorteq(items.keys(), ('00.cell.synapse', '01.cell.synapse'))
1405
+ self.true(all(item[0] for item in items.values()))
1406
+ self.eq(cell00.runid, items['00.cell.synapse'][1]['cell']['run'])
1407
+ self.eq(cell01.runid, items['01.cell.synapse'][1]['cell']['run'])
1408
+
1409
+ todo = s_common.todo('newp')
1410
+ items = dict([item async for item in aha.callAhaPeerApi(cell00.iden, todo, timeout=3)])
1411
+ self.false(any(item[0] for item in items.values()))
1412
+ self.sorteq(items.keys(), ('00.cell.synapse', '01.cell.synapse'))
1413
+
1414
+ # test the genr endpoint
1415
+ reals = [item async for item in cell00.getNexusChanges(0, wait=False)]
1416
+ todo = s_common.todo('getNexusChanges', 0, wait=False)
1417
+ items = [item async for item in aha.callAhaPeerGenr(cell00.iden, todo, timeout=3) if item[1]]
1418
+ self.len(nexsindx * 2, items)
1419
+
1420
+ # ensure we handle down services correctly
1421
+ async with aha.waiter(1, 'aha:svcdown', timeout=10):
1422
+ await cell01.fini()
1423
+
1424
+ # test the call endpoint
1425
+ todo = s_common.todo('getCellInfo')
1426
+ items = dict([item async for item in aha.callAhaPeerApi(cell00.iden, todo, timeout=3)])
1427
+ self.sorteq(items.keys(), ('00.cell.synapse',))
1428
+ self.true(all(item[0] for item in items.values()))
1429
+ self.eq(cell00.runid, items['00.cell.synapse'][1]['cell']['run'])
1430
+
1431
+ # test the genr endpoint
1432
+ todo = s_common.todo('getNexusChanges', 0, wait=False)
1433
+ items = [item async for item in aha.callAhaPeerGenr(cell00.iden, todo, timeout=3) if item[1]]
1434
+ self.len(nexsindx, items)
1435
+ self.true(all(item[1][0] for item in items))
1436
+
1437
+ # test some of the gather API implementations...
1438
+ purl00 = await aha.addAhaSvcProv('0.cell')
1439
+ purl01 = await aha.addAhaSvcProv('1.cell', provinfo={'mirror': '0.cell'})
1440
+
1441
+ cell00 = await aha.enter_context(self.getTestCell(conf={'aha:provision': purl00}))
1442
+ cell01 = await aha.enter_context(self.getTestCell(conf={'aha:provision': purl01}))
1443
+
1444
+ await cell01.sync()
1445
+
1446
+ async def sleep99(cell):
1447
+ await cell.boss.promote('sleep99', cell.auth.rootuser)
1448
+ await cell00.fire('sleep99')
1449
+ await asyncio.sleep(99)
1450
+
1451
+ async with cell00.waiter(2, 'sleep99', timeout=2):
1452
+ task00 = cell00.schedCoro(sleep99(cell00))
1453
+ task01 = cell01.schedCoro(sleep99(cell01))
1454
+
1455
+ proxy = await aha.enter_context(aha.getLocalProxy())
1456
+ tasks = [task async for task in cell00.getTasks(timeout=3)]
1457
+ self.len(2, tasks)
1458
+ self.eq(tasks[0]['service'], '0.cell.synapse')
1459
+ self.eq(tasks[1]['service'], '1.cell.synapse')
1460
+
1461
+ self.eq(tasks[0], await cell00.getTask(tasks[0].get('iden')))
1462
+ self.eq(tasks[1], await cell00.getTask(tasks[1].get('iden')))
1463
+ self.none(await cell00.getTask(tasks[1].get('iden'), peers=False))
1464
+
1465
+ self.true(await cell00.killTask(tasks[0].get('iden')))
1466
+
1467
+ task01 = tasks[1].get('iden')
1468
+ self.false(await cell00.killTask(task01, peers=False))
1469
+
1470
+ self.true(await cell00.killTask(task01))
1471
+
1472
+ self.none(await cell00.getTask(task01))
1473
+ self.false(await cell00.killTask(task01))
1474
+
1475
+ self.none(await cell00.getAhaProxy(feats=(('newp', 9),)))
1476
+
1477
+ async def test_lib_aha_peer_api(self):
1478
+
1479
+ async with self.getTestAha() as aha:
1480
+
1481
+ purl00 = await aha.addAhaSvcProv('0.cell')
1482
+ purl01 = await aha.addAhaSvcProv('1.cell', provinfo={'mirror': '0.cell'})
1483
+ purl02 = await aha.addAhaSvcProv('2.cell', provinfo={'mirror': '0.cell'})
1484
+
1485
+ cell00 = await aha.enter_context(self.getTestCell(conf={'aha:provision': purl00}))
1486
+ cell01 = await aha.enter_context(self.getTestCell(conf={'aha:provision': purl01}))
1487
+ cell02 = await aha.enter_context(self.getTestCell(conf={'aha:provision': purl02}))
1488
+
1489
+ await cell01.sync()
1490
+ await cell02.sync()
1491
+
1492
+ todo = s_common.todo('getCellInfo')
1493
+ items = [item async for item in cell00.callPeerApi(todo)]
1494
+ self.len(2, items)
1495
+
1496
+ async def test_lib_aha_peer_genr(self):
1497
+
1498
+ async with self.getTestAha() as aha:
1499
+
1500
+ purl00 = await aha.addAhaSvcProv('0.cell')
1501
+ purl01 = await aha.addAhaSvcProv('1.cell', provinfo={'mirror': '0.cell'})
1502
+
1503
+ cell00 = await aha.enter_context(self.getTestCell(conf={'aha:provision': purl00}))
1504
+ cell01 = await aha.enter_context(self.getTestCell(conf={'aha:provision': purl01}))
1505
+
1506
+ await cell01.sync()
1507
+
1508
+ todo = s_common.todo('getNexusChanges', 0, wait=False)
1509
+ items = dict([item async for item in cell00.callPeerGenr(todo)])
1510
+ self.len(1, items)
1511
+
1512
+ todo = s_common.todo('getNexusChanges', 0, wait=False)
1513
+ items = dict([item async for item in cell00.callPeerGenr(todo, timeout=2)])
1514
+ self.len(1, items)
1515
+
1516
+ async def test_lib_aha_call_aha_peer_api_isactive(self):
1517
+
1518
+ async with self.getTestAha() as aha0:
1519
+
1520
+ async with aha0.waiter(3, 'aha:svcadd', timeout=10):
1521
+
1522
+ conf = {'aha:provision': await aha0.addAhaSvcProv('00.cell')}
1523
+ cell00 = await aha0.enter_context(self.getTestCell(conf=conf))
1524
+
1525
+ conf = {'aha:provision': await aha0.addAhaSvcProv('01.cell', {'mirror': 'cell'})}
1526
+ cell01 = await aha0.enter_context(self.getTestCell(conf=conf))
1527
+
1528
+ await cell01.sync()
1529
+
1530
+ # test active AHA peer
1531
+ todo = s_common.todo('getCellInfo')
1532
+ items = dict([item async for item in aha0.callAhaPeerApi(cell00.iden, todo, timeout=3)])
1533
+ self.sorteq(items.keys(), ('00.cell.synapse', '01.cell.synapse'))
1534
+
1535
+ todo = s_common.todo('getNexusChanges', 0, wait=False)
1536
+ items = dict([item async for item in aha0.callAhaPeerGenr(cell00.iden, todo, timeout=3)])
1537
+ self.sorteq(items.keys(), ('00.cell.synapse', '01.cell.synapse'))
1538
+
1539
+ async with aha0.getLocalProxy() as proxy0:
1540
+ purl = await proxy0.addAhaClone('01.aha.loop.vertex.link')
1541
+
1542
+ conf1 = {'clone': purl}
1543
+ async with self.getTestAha(conf=conf1) as aha1:
1544
+
1545
+ await aha1.sync()
1546
+
1547
+ self.eq(aha0.iden, aha1.iden)
1548
+ self.nn(aha1.conf.get('mirror'))
1549
+
1550
+ self.true(aha0.isactive)
1551
+ self.false(aha1.isactive)
1552
+
1553
+ # test non-active AHA peer
1554
+ todo = s_common.todo('getCellInfo')
1555
+ items = dict([item async for item in aha1.callAhaPeerApi(cell00.iden, todo, timeout=3)])
1556
+ self.sorteq(items.keys(), ('00.cell.synapse', '01.cell.synapse'))
1557
+
1558
+ todo = s_common.todo('getNexusChanges', 0, wait=False)
1559
+ items = dict([item async for item in aha1.callAhaPeerGenr(cell00.iden, todo, timeout=3)])
1560
+ self.sorteq(items.keys(), ('00.cell.synapse', '01.cell.synapse'))
@@ -784,6 +784,10 @@ class CellTest(s_t_utils.SynTest):
784
784
  cell.VERSION = (1, 2, 3)
785
785
  cell.VERSTRING = '1.2.3'
786
786
 
787
+ cell.features.update({
788
+ 'testvalu': 2
789
+ })
790
+
787
791
  http_info = []
788
792
  host, port = await cell.addHttpsPort(0)
789
793
  http_info.append({'host': host, 'port': port})
@@ -807,6 +811,9 @@ class CellTest(s_t_utils.SynTest):
807
811
  # A Cortex populated cellvers
808
812
  self.isin('cortex:defaults', cnfo.get('cellvers', {}))
809
813
 
814
+ self.eq(info.get('features'), cell.features)
815
+ self.eq(info.get('features', {}).get('testvalu'), 2)
816
+
810
817
  # Defaults aha data is
811
818
  self.eq(cnfo.get('aha'), {'name': None, 'leader': None, 'network': None})
812
819
 
@@ -3294,6 +3301,51 @@ class CellTest(s_t_utils.SynTest):
3294
3301
  await cell00.promote(graceful=True)
3295
3302
  self.isin('02.cell is not the current leader', cm.exception.get('mesg'))
3296
3303
 
3304
+ async def test_cell_get_aha_proxy(self):
3305
+
3306
+ async with self.getTestCell() as cell:
3307
+
3308
+ self.none(await cell.getAhaProxy())
3309
+
3310
+ class MockAhaClient:
3311
+ def __init__(self, proxy=None):
3312
+ self._proxy = proxy
3313
+
3314
+ async def proxy(self, timeout=None):
3315
+ return self._proxy
3316
+
3317
+ with self.getAsyncLoggerStream('synapse.lib.cell', 'AHA client connection failed.') as stream:
3318
+ cell.ahaclient = MockAhaClient()
3319
+ self.none(await cell.getAhaProxy())
3320
+ self.true(await stream.wait(timeout=1))
3321
+
3322
+ class MockProxyHasNot:
3323
+ def _hasTeleFeat(self, name, vers):
3324
+ return False
3325
+
3326
+ cell.ahaclient = MockAhaClient(proxy=MockProxyHasNot())
3327
+ self.none(await cell.getAhaProxy(feats=(('test', 1),)))
3328
+
3329
+ class MockProxyHas:
3330
+ def _hasTeleFeat(self, name, vers):
3331
+ return True
3332
+
3333
+ mock_proxy = MockProxyHas()
3334
+ cell.ahaclient = MockAhaClient(proxy=mock_proxy)
3335
+ self.eq(await cell.getAhaProxy(), mock_proxy)
3336
+ self.eq(await cell.getAhaProxy(feats=(('test', 1),)), mock_proxy)
3337
+
3338
+ async def test_lib_cell_sadaha(self):
3339
+
3340
+ async with self.getTestCell() as cell:
3341
+
3342
+ self.none(await cell.getAhaProxy())
3343
+ cell.ahaclient = await s_telepath.Client.anit('cell:///tmp/newp')
3344
+
3345
+ # coverage for failure of aha client to connect
3346
+ with self.raises(TimeoutError):
3347
+ self.none(await cell.getAhaProxy(timeout=0.1))
3348
+
3297
3349
  async def test_stream_backup_exception(self):
3298
3350
 
3299
3351
  with self.getTestDir() as dirn:
@@ -3356,3 +3408,12 @@ class CellTest(s_t_utils.SynTest):
3356
3408
  with self.raises(s_exc.BackupAlreadyRunning):
3357
3409
  async for _ in proxy.iterNewBackupArchive('newbackup', remove=True):
3358
3410
  pass
3411
+
3412
+ async def test_cell_peer_noaha(self):
3413
+
3414
+ todo = s_common.todo('newp')
3415
+ async with self.getTestCell() as cell:
3416
+ async for item in cell.callPeerApi(todo):
3417
+ pass
3418
+ async for item in cell.callPeerGenr(todo):
3419
+ pass
@@ -116,6 +116,7 @@ class JsonStorTest(s_test.SynTest):
116
116
  self.eq({'hehe': 'haha', 'zip': {}}, await prox.getPathObj('foo/bar'))
117
117
 
118
118
  self.false(await prox.delPathObjProp('newp/newp', 'newp'))
119
+ self.false(await prox.delPathObjProp('foo/bar', 'nested/newp'))
119
120
 
120
121
  await prox.delPathObj('foo/bar')
121
122
  self.none(await prox.getPathObj('foo/bar'))
@@ -1766,3 +1766,9 @@ class ModelRevTest(s_tests.SynTest):
1766
1766
  self.eq('foo bar', nodes[0].get('model'))
1767
1767
  nodes = await core.nodes('transport:sea:vessel')
1768
1768
  self.eq('foo bar', nodes[0].get('model'))
1769
+
1770
+ async def test_modelrev_0_2_33(self):
1771
+ async with self.getRegrCore('model-0.2.33') as core:
1772
+ nodes = await core.nodes('entity:name')
1773
+ self.len(1, nodes)
1774
+ self.eq('foo bar', nodes[0].repr())
@@ -318,7 +318,7 @@ class NexusTest(s_t_utils.SynTest):
318
318
  cell01.nexsiden = 'newp'
319
319
  with self.raises(s_exc.NoSuchIden) as cm:
320
320
  await cell01.sync()
321
- self.eq(cm.exception.get('mesg'), 'No Nexus Pusher with iden newp.')
321
+ self.eq(cm.exception.get('mesg'), "No Nexus Pusher with iden newp event='sync' args=() kwargs={}")
322
322
 
323
323
  self.none(await cell00.nexsroot.nexslog.last())
324
324
  self.none(await cell01.nexsroot.nexslog.last())
@@ -331,7 +331,7 @@ class NexusTest(s_t_utils.SynTest):
331
331
 
332
332
  with self.raises(s_exc.NoSuchName) as cm:
333
333
  await cell01._push('newp')
334
- self.eq(cm.exception.get('mesg'), 'No Nexus handler for event newp.')
334
+ self.eq(cm.exception.get('mesg'), 'No event handler for event newp args=() kwargs={}')
335
335
 
336
336
  self.eq(0, (await cell00.nexsroot.nexslog.last())[0])
337
337
  self.eq(0, (await cell01.nexsroot.nexslog.last())[0])
@@ -379,3 +379,25 @@ class NexusTest(s_t_utils.SynTest):
379
379
  self.isin(mesg, data)
380
380
 
381
381
  self.true(restarted)
382
+
383
+ async def test_pusher_race(self):
384
+
385
+ evnt = asyncio.Event()
386
+
387
+ async with self.getTestCore() as core:
388
+ orig = core._nexshands['view:delwithlayer'][0]
389
+
390
+ async def holdlock(self, viewiden, layriden, nexsitem, newparent=None):
391
+ evnt.set()
392
+ await asyncio.sleep(1)
393
+ await orig(self, viewiden, layriden, nexsitem, newparent=newparent)
394
+
395
+ core._nexshands['view:delwithlayer'] = (holdlock, True)
396
+
397
+ forkiden = await core.callStorm('return($lib.view.get().fork().iden)')
398
+
399
+ core.schedCoro(core.delViewWithLayer(forkiden))
400
+ await asyncio.wait_for(evnt.wait(), timeout=10)
401
+
402
+ with self.raises(s_exc.NoSuchIden):
403
+ await core.nodes('[ it:dev:str=foo ]', opts={'view': forkiden})
@@ -6,6 +6,8 @@ import synapse.lib.cell as s_cell
6
6
 
7
7
  import synapse.tests.utils as s_test
8
8
 
9
+ import unittest.mock as mock
10
+
9
11
  class AhaLibTest(s_test.SynTest):
10
12
 
11
13
  async def test_stormlib_aha_basics(self):
@@ -193,3 +195,189 @@ Connection information:
193
195
 
194
196
  with self.raises(s_exc.NoSuchName):
195
197
  await core00.callStorm('$lib.aha.del(axon...)')
198
+
199
+ async def test_stormlib_aha_mirror(self):
200
+
201
+ async with self.getTestAha() as aha:
202
+
203
+ with self.getTestDir() as dirn:
204
+
205
+ dirn00 = s_common.genpath(dirn, 'cell00')
206
+ dirn01 = s_common.genpath(dirn, 'cell01')
207
+ dirn02 = s_common.genpath(dirn, 'cell02')
208
+
209
+ async with aha.waiter(3, 'aha:svcadd', timeout=10):
210
+
211
+ cell00 = await aha.enter_context(self.addSvcToAha(aha, '00.cell', s_cell.Cell, dirn=dirn00))
212
+ cell01 = await aha.enter_context(self.addSvcToAha(aha, '01.cell', s_cell.Cell, dirn=dirn01,
213
+ provinfo={'mirror': 'cell'}))
214
+ core00 = await aha.enter_context(self.addSvcToAha(aha, 'core', s_cortex.Cortex, dirn=dirn02))
215
+ await cell01.sync()
216
+
217
+ # PeerGenr
218
+ resp = await core00.callStorm('''
219
+ $resps = $lib.list()
220
+ $todo = $lib.utils.todo('getTasks')
221
+ for ($name, $info) in $lib.aha.callPeerGenr(cell..., $todo) {
222
+ $resps.append(($name, $info))
223
+ }
224
+ return($resps)
225
+ ''')
226
+ self.len(0, resp)
227
+
228
+ resp = await core00.callStorm('''
229
+ $resps = $lib.list()
230
+ $todo = $lib.utils.todo('getNexusChanges', (0), wait=(false))
231
+ for ($name, $info) in $lib.aha.callPeerGenr(cell..., $todo) {
232
+ $resps.append(($name, $info))
233
+ }
234
+ return($resps)
235
+ ''')
236
+ self.len(4, resp)
237
+
238
+ cell00_rid = (await cell00.getCellInfo())['cell']['run']
239
+ resp = await core00.callStorm('''
240
+ $resps = $lib.list()
241
+ $todo = $lib.utils.todo('getNexusChanges', (0), wait=(false))
242
+ for $info in $lib.aha.callPeerGenr(cell..., $todo, skiprun=$skiprun) {
243
+ $resps.append($info)
244
+ }
245
+ return($resps)
246
+ ''', opts={'vars': {'skiprun': cell00_rid}})
247
+ self.len(2, resp)
248
+
249
+ await self.asyncraises(s_exc.NoSuchName, core00.callStorm('''
250
+ $todo = $lib.utils.todo('getTasks')
251
+ $lib.aha.callPeerGenr(null, $todo)
252
+ '''))
253
+
254
+ # PeerApi
255
+ resp = await core00.callStorm('''
256
+ $resps = $lib.list()
257
+ $todo = $lib.utils.todo('getCellInfo')
258
+ for ($name, $info) in $lib.aha.callPeerApi(cell..., $todo) {
259
+ $resps.append(($name, $info))
260
+ }
261
+ return($resps)
262
+ ''')
263
+ self.len(2, resp)
264
+ self.eq(resp[0][0], '00.cell.synapse')
265
+ self.eq(resp[0][1][0], True)
266
+ self.isinstance(resp[0][1][1], dict)
267
+
268
+ resp = await core00.callStorm('''
269
+ $resps = $lib.list()
270
+ $todo = $lib.utils.todo(getCellInfo)
271
+ for ($name, $info) in $lib.aha.callPeerApi(cell..., $todo) {
272
+ $resps.append(($name, $info))
273
+ }
274
+ return($resps)
275
+ ''')
276
+ self.len(2, resp)
277
+
278
+ resp = await core00.callStorm('''
279
+ $resps = $lib.list()
280
+ $todo = $lib.utils.todo(getCellInfo)
281
+ for ($name, $info) in $lib.aha.callPeerApi(cell..., $todo, skiprun=$skiprun) {
282
+ $resps.append(($name, $info))
283
+ }
284
+ return($resps)
285
+ ''', opts={'vars': {'skiprun': cell00_rid}})
286
+ self.len(1, resp)
287
+
288
+ resp = await core00.callStorm('''
289
+ $resps = $lib.list()
290
+ $todo = $lib.utils.todo('getCellInfo')
291
+ for ($name, $info) in $lib.aha.callPeerApi(cell..., $todo, timeout=(10)) {
292
+ $resps.append(($name, $info))
293
+ }
294
+ return($resps)
295
+ ''')
296
+ self.len(2, resp)
297
+
298
+ await self.asyncraises(s_exc.NoSuchName, core00.callStorm('''
299
+ $todo = $lib.utils.todo('getCellInfo')
300
+ $lib.aha.callPeerApi(newp..., $todo)
301
+ '''))
302
+
303
+ await self.asyncraises(s_exc.NoSuchName, core00.callStorm('''
304
+ $todo = $lib.utils.todo('getCellInfo')
305
+ $lib.aha.callPeerApi(null, $todo)
306
+ '''))
307
+
308
+ await self.asyncraises(s_exc.NoSuchMeth, core00.callStorm('''
309
+ $todo = $lib.utils.todo('bogusMethod')
310
+ for $info in $lib.aha.callPeerApi(cell..., $todo) {
311
+ ($ok, $info) = $info.1
312
+ if (not $ok) {
313
+ $lib.raise($info.err, $info.errmsg)
314
+ }
315
+ }
316
+ '''))
317
+
318
+ await aha.addAhaSvc('noiden.cell', info={'urlinfo': {'scheme': 'tcp',
319
+ 'host': '0.0.0.0',
320
+ 'port': '3030'}},
321
+ network='synapse')
322
+ await self.asyncraises(s_exc.NoSuchName, core00.callStorm('''
323
+ $todo = $lib.utils.todo('getTasks')
324
+ $lib.aha.callPeerGenr(noiden.cell..., $todo)
325
+ '''))
326
+ await self.asyncraises(s_exc.NoSuchName, core00.callStorm('''
327
+ $todo = $lib.utils.todo('getCellInfo')
328
+ $lib.aha.callPeerApi(noiden.cell..., $todo)
329
+ '''))
330
+
331
+ msgs = await core00.stormlist('aha.svc.mirror')
332
+ self.stormIsInPrint('Service Mirror Groups:', msgs)
333
+ self.stormIsInPrint('cell.synapse', msgs)
334
+ self.stormIsInPrint('00.cell.synapse', msgs)
335
+ self.stormIsInPrint('01.cell.synapse', msgs)
336
+ self.stormIsInPrint('Group Status: In Sync', msgs)
337
+
338
+ msgs = await core00.stormlist('aha.svc.mirror --timeout 30')
339
+ self.stormIsInPrint('Service Mirror Groups:', msgs)
340
+ self.stormIsInPrint('Group Status: In Sync', msgs)
341
+
342
+ async def mockCellInfo():
343
+ return {
344
+ 'cell': {'ready': True, 'nexsindx': 10, 'uplink': None},
345
+ 'synapse': {'verstring': '2.190.0'},
346
+ }
347
+
348
+ async def mockOutOfSyncCellInfo():
349
+ return {
350
+ 'cell': {'ready': True, 'nexsindx': 5, 'uplink': cell00.iden},
351
+ 'synapse': {'verstring': '2.190.0'},
352
+ }
353
+
354
+ with mock.patch.object(cell00, 'getCellInfo', mockCellInfo):
355
+ with mock.patch.object(cell01, 'getCellInfo', mockOutOfSyncCellInfo):
356
+ async def mock_call_aha(*args, **kwargs):
357
+ todo = args[1]
358
+ if todo[0] == 'waitNexsOffs':
359
+ yield ('00.cell.synapse', (True, True))
360
+ yield ('01.cell.synapse', (True, True))
361
+ elif todo[0] == 'getCellInfo':
362
+ if not hasattr(mock_call_aha, 'called'):
363
+ mock_call_aha.called = True
364
+ yield ('00.cell.synapse', (True, await mockCellInfo()))
365
+ yield ('01.cell.synapse', (True, await mockOutOfSyncCellInfo()))
366
+ else:
367
+ yield ('00.cell.synapse', (True, await mockCellInfo()))
368
+ yield ('01.cell.synapse', (True, await mockCellInfo()))
369
+
370
+ with mock.patch.object(aha, 'callAhaPeerApi', mock_call_aha):
371
+ msgs = await core00.stormlist('aha.svc.mirror --wait')
372
+ self.stormIsInPrint('Group Status: Out of Sync', msgs)
373
+ self.stormIsInPrint('Updated status:', msgs)
374
+ self.stormIsInPrint('Group Status: In Sync', msgs)
375
+
376
+ with mock.patch.object(cell00, 'getCellInfo', mockCellInfo):
377
+ with mock.patch.object(cell01, 'getCellInfo', mockOutOfSyncCellInfo):
378
+ msgs = await core00.stormlist('aha.svc.mirror --timeout 1')
379
+ self.stormIsInPrint('Group Status: Out of Sync', msgs)
380
+
381
+ await aha.delAhaSvc('00.cell', network='synapse')
382
+ msgs = await core00.stormlist('aha.svc.mirror')
383
+ self.stormNotInPrint('Service Mirror Groups:', msgs)
@@ -0,0 +1,14 @@
1
+ import synapse.exc as s_exc
2
+ import synapse.tests.utils as s_test
3
+
4
+ class UtilsTest(s_test.SynTest):
5
+
6
+ async def test_lib_stormlib_utils_todo(self):
7
+
8
+ async with self.getTestCore() as core:
9
+
10
+ valu = await core.callStorm('return($lib.utils.todo(foo))')
11
+ self.eq(valu, ('foo', (), {}))
12
+
13
+ valu = await core.callStorm('return($lib.utils.todo(fooName, arg1, arg2, keyword=bar, anotherkeyword=hehe))')
14
+ self.eq(valu, ('fooName', ('arg1', 'arg2'), {'keyword': 'bar', 'anotherkeyword': 'hehe'}))