synapse 2.195.1__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 (45) 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 +4 -1
  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 +118 -0
  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_stormlib_aha.py +188 -0
  30. synapse/tests/test_lib_stormlib_utils.py +14 -0
  31. synapse/tests/test_lib_stormtypes.py +90 -3
  32. synapse/tests/test_model_base.py +2 -0
  33. synapse/tests/test_model_infotech.py +28 -1
  34. synapse/tests/test_model_orgs.py +2 -0
  35. synapse/tests/test_model_risk.py +2 -0
  36. synapse/tests/test_model_transport.py +1 -0
  37. synapse/tests/test_telepath.py +26 -0
  38. synapse/tests/test_tools_aha.py +192 -0
  39. synapse/tools/aha/mirror.py +193 -0
  40. synapse/tools/changelog.py +32 -27
  41. {synapse-2.195.1.dist-info → synapse-2.196.0.dist-info}/METADATA +1 -1
  42. {synapse-2.195.1.dist-info → synapse-2.196.0.dist-info}/RECORD +45 -42
  43. {synapse-2.195.1.dist-info → synapse-2.196.0.dist-info}/LICENSE +0 -0
  44. {synapse-2.195.1.dist-info → synapse-2.196.0.dist-info}/WHEEL +0 -0
  45. {synapse-2.195.1.dist-info → synapse-2.196.0.dist-info}/top_level.txt +0 -0
@@ -1417,6 +1417,36 @@ class ItModule(s_module.CoreModule):
1417
1417
  'deprecated': True,
1418
1418
  'doc': 'Deprecated. Please use risk:vuln:cve:references.'}),
1419
1419
 
1420
+ ('nist:nvd:source', ('ou:name', {}), {
1421
+ 'doc': 'The name of the organization which reported the vulnerability to NIST.'}),
1422
+
1423
+ ('nist:nvd:published', ('time', {}), {
1424
+ 'doc': 'The date the vulnerability was first published in the NVD.'}),
1425
+
1426
+ ('nist:nvd:modified', ('time', {"ismax": True}), {
1427
+ 'doc': 'The date the vulnerability was last modified in the NVD.'}),
1428
+
1429
+ ('cisa:kev:name', ('str', {}), {
1430
+ 'doc': 'The name of the vulnerability according to the CISA KEV database.'}),
1431
+
1432
+ ('cisa:kev:desc', ('str', {}), {
1433
+ 'doc': 'The description of the vulnerability according to the CISA KEV database.'}),
1434
+
1435
+ ('cisa:kev:action', ('str', {}), {
1436
+ 'doc': 'The action to mitigate the vulnerability according to the CISA KEV database.'}),
1437
+
1438
+ ('cisa:kev:vendor', ('ou:name', {}), {
1439
+ 'doc': 'The vendor name listed in the CISA KEV database.'}),
1440
+
1441
+ ('cisa:kev:product', ('it:prod:softname', {}), {
1442
+ 'doc': 'The product name listed in the CISA KEV database.'}),
1443
+
1444
+ ('cisa:kev:added', ('time', {}), {
1445
+ 'doc': 'The date the vulnerability was added to the CISA KEV database.'}),
1446
+
1447
+ ('cisa:kev:duedate', ('time', {}), {
1448
+ 'doc': 'The date the action is due according to the CISA KEV database.'}),
1449
+
1420
1450
  )),
1421
1451
  ('it:sec:cpe', {}, (
1422
1452
  ('v2_2', ('it:sec:cpe:v2_2', {}), {
@@ -2248,29 +2278,34 @@ class ItModule(s_module.CoreModule):
2248
2278
  'doc': 'Software architecture.',
2249
2279
  }),
2250
2280
  ('released', ('time', {}), {
2251
- 'doc': 'Timestamp for when this version of the software was released.',
2252
- }),
2281
+ 'doc': 'Timestamp for when this version of the software was released.'}),
2282
+
2253
2283
  ('semver', ('it:semver', {}), {
2254
- 'doc': 'System normalized semantic version number.',
2255
- }),
2284
+ 'doc': 'System normalized semantic version number.'}),
2285
+
2256
2286
  ('semver:major', ('int', {}), {
2257
- 'doc': 'Version major number.',
2258
- }),
2287
+ 'deprecated': True,
2288
+ 'doc': 'Deprecated. Please use semver range queries.'}),
2289
+
2259
2290
  ('semver:minor', ('int', {}), {
2260
- 'doc': 'Version minor number.',
2261
- }),
2291
+ 'deprecated': True,
2292
+ 'doc': 'Deprecated. Please use semver range queries.'}),
2293
+
2262
2294
  ('semver:patch', ('int', {}), {
2263
- 'doc': 'Version patch number.',
2264
- }),
2295
+ 'deprecated': True,
2296
+ 'doc': 'Deprecated. Please use semver range queries.'}),
2297
+
2265
2298
  ('semver:pre', ('str', {}), {
2266
- 'doc': 'Semver prerelease string.',
2267
- }),
2299
+ 'deprecated': True,
2300
+ 'doc': 'Deprecated.'}),
2301
+
2268
2302
  ('semver:build', ('str', {}), {
2269
- 'doc': 'Semver build string.',
2270
- }),
2303
+ 'deprecated': True,
2304
+ 'doc': 'Deprecated.'}),
2305
+
2271
2306
  ('url', ('inet:url', {}), {
2272
- 'doc': 'URL where a specific version of the software is available from.',
2273
- }),
2307
+ 'doc': 'URL where a specific version of the software is available from.'}),
2308
+
2274
2309
  )),
2275
2310
 
2276
2311
  ('it:prod:softlib', {}, (
@@ -2347,6 +2382,10 @@ class ItModule(s_module.CoreModule):
2347
2382
  ('signame', ('it:av:signame', {}), {
2348
2383
  'doc': 'The name of the signature returned by the scanner.'}),
2349
2384
 
2385
+ ('categories', ('array', {'sorted': True, 'uniq': True,
2386
+ 'type': 'str', 'typeopts': {'lower': True, 'onespace': True}}), {
2387
+ 'doc': 'A list of categories for the result returned by the scanner.'}),
2388
+
2350
2389
  ('target:file', ('file:bytes', {}), {
2351
2390
  'doc': 'The file that was scanned to produce the result.'}),
2352
2391
 
synapse/models/orgs.py CHANGED
@@ -1346,23 +1346,27 @@ class OuModule(s_module.CoreModule):
1346
1346
  }),
1347
1347
  )),
1348
1348
  ('ou:contest:result', {}, (
1349
+
1349
1350
  ('contest', ('ou:contest', {}), {
1350
1351
  'ro': True,
1351
- 'doc': 'The contest.',
1352
- }),
1352
+ 'doc': 'The contest that the participant took part in.'}),
1353
+
1353
1354
  ('participant', ('ps:contact', {}), {
1354
1355
  'ro': True,
1355
- 'doc': 'The participant',
1356
- }),
1356
+ 'doc': 'The participant in the contest.'}),
1357
+
1357
1358
  ('rank', ('int', {}), {
1358
- 'doc': 'The rank order of the participant.',
1359
- }),
1359
+ 'doc': "The participant's rank order in the contest."}),
1360
+
1360
1361
  ('score', ('int', {}), {
1361
- 'doc': 'The score of the participant.',
1362
- }),
1362
+ 'doc': "The participant's final score in the contest."}),
1363
+
1364
+ ('period', ('ival', {}), {
1365
+ 'doc': 'The period of time when the participant competed in the contest.'}),
1366
+
1363
1367
  ('url', ('inet:url', {}), {
1364
- 'doc': 'The contest result website URL.',
1365
- }),
1368
+ 'doc': 'The contest result website URL.'}),
1369
+
1366
1370
  )),
1367
1371
  ('ou:enacted:status:taxonomy', {}, ()),
1368
1372
  ('ou:enacted', {}, (
synapse/models/risk.py CHANGED
@@ -492,6 +492,9 @@ class RiskModule(s_module.CoreModule):
492
492
  ('id', ('str', {'strip': True}), {
493
493
  'doc': 'An identifier for the vulnerability.'}),
494
494
 
495
+ ('tag', ('syn:tag', {}), {
496
+ 'doc': 'A tag used to annotate the presence or use of the vulnerability.'}),
497
+
495
498
  ('cve', ('it:sec:cve', {}), {
496
499
  'doc': 'The CVE ID of the vulnerability.'}),
497
500
 
@@ -506,34 +509,44 @@ class RiskModule(s_module.CoreModule):
506
509
  'doc': 'An array of documentation URLs provided by the CVE database.'}),
507
510
 
508
511
  ('nist:nvd:source', ('ou:name', {}), {
509
- 'doc': 'The name of the organization which reported the vulnerability to NIST.'}),
512
+ 'deprecated': True,
513
+ 'doc': 'Deprecated. Please use it:sec:cve:nist:nvd:source.'}),
510
514
 
511
515
  ('nist:nvd:published', ('time', {}), {
512
- 'doc': 'The date the vulnerability was first published in the NVD.'}),
516
+ 'deprecated': True,
517
+ 'doc': 'Deprecated. Please use it:sec:cve:nist:nvd:published.'}),
513
518
 
514
519
  ('nist:nvd:modified', ('time', {"ismax": True}), {
515
- 'doc': 'The date the vulnerability was last modified in the NVD.'}),
520
+ 'deprecated': True,
521
+ 'doc': 'Deprecated. Please use it:sec:cve:nist:nvd:modified.'}),
516
522
 
517
523
  ('cisa:kev:name', ('str', {}), {
518
- 'doc': 'The name of the vulnerability according to the CISA KEV database.'}),
524
+ 'deprecated': True,
525
+ 'doc': 'Deprecated. Please use it:sec:cve:cisa:kev:name.'}),
519
526
 
520
527
  ('cisa:kev:desc', ('str', {}), {
521
- 'doc': 'The description of the vulnerability according to the CISA KEV database.'}),
528
+ 'deprecated': True,
529
+ 'doc': 'Deprecated. Please use it:sec:cve:cisa:kev:desc.'}),
522
530
 
523
531
  ('cisa:kev:action', ('str', {}), {
524
- 'doc': 'The action to mitigate the vulnerability according to the CISA KEV database.'}),
532
+ 'deprecated': True,
533
+ 'doc': 'Deprecated. Please use it:sec:cve:cisa:kev:action.'}),
525
534
 
526
535
  ('cisa:kev:vendor', ('ou:name', {}), {
527
- 'doc': 'The vendor name listed in the CISA KEV database.'}),
536
+ 'deprecated': True,
537
+ 'doc': 'Deprecated. Please use it:sec:cve:cisa:kev:vendor.'}),
528
538
 
529
539
  ('cisa:kev:product', ('it:prod:softname', {}), {
530
- 'doc': 'The product name listed in the CISA KEV database.'}),
540
+ 'deprecated': True,
541
+ 'doc': 'Deprecated. Please use it:sec:cve:cisa:kev:product.'}),
531
542
 
532
543
  ('cisa:kev:added', ('time', {}), {
533
- 'doc': 'The date the vulnerability was added to the CISA KEV database.'}),
544
+ 'deprecated': True,
545
+ 'doc': 'Deprecated. Please use it:sec:cve:cisa:kev:added.'}),
534
546
 
535
547
  ('cisa:kev:duedate', ('time', {}), {
536
- 'doc': 'The date the action is due according to the CISA KEV database.'}),
548
+ 'deprecated': True,
549
+ 'doc': 'Deprecated. Please use it:sec:cve:cisa:kev:duedate.'}),
537
550
 
538
551
  ('cvss:v2', ('cvss:v2', {}), {
539
552
  'doc': 'The CVSS v2 vector for the vulnerability.'}),
@@ -454,21 +454,26 @@ class TransportModule(s_module.CoreModule):
454
454
  ('type', ('transport:sea:vessel:type:taxonomy', {}), {
455
455
  'doc': 'The type of vessel.'}),
456
456
 
457
- # TODO: convert this to an entity:name
458
- ('name', ('str', {'lower': True, 'onespace': True}), {
459
- 'doc': 'The name of the vessel'}),
457
+ ('name', ('entity:name', {}), {
458
+ 'doc': 'The name of the vessel.'}),
459
+
460
460
  ('length', ('geo:dist', {}), {
461
461
  'deprecated': True,
462
462
  'doc': 'Deprecated. Please use :phys:length.'}),
463
+
463
464
  ('beam', ('geo:dist', {}), {
464
465
  'doc': 'The official overall vessel beam'}),
466
+
465
467
  ('flag', ('iso:3166:cc', {}), {
466
468
  'doc': 'The country the vessel is flagged to.'}),
469
+
467
470
  ('mmsi', ('transport:sea:mmsi', {}), {
468
471
  'doc': 'The Maritime Mobile Service Identifier assigned to the vessel.'}),
472
+
469
473
  ('make', ('str', {'lower': True, 'strip': True}), {
470
474
  'deprecated': True,
471
475
  'doc': 'Deprecated. Please use :manufacturer:name.'}),
476
+
472
477
  ('operator', ('ps:contact', {}), {
473
478
  'doc': 'The contact information of the operator.'}),
474
479
  # TODO tonnage / gross tonnage?
synapse/telepath.py CHANGED
@@ -321,6 +321,9 @@ class Aware:
321
321
  '''
322
322
  return self
323
323
 
324
+ async def getTeleFeats(self):
325
+ return {}
326
+
324
327
  def onTeleShare(self, dmon, name):
325
328
  pass
326
329
 
@@ -599,6 +602,8 @@ class Proxy(s_base.Base):
599
602
  self.shares = {}
600
603
 
601
604
  self._ahainfo = {}
605
+ self._features = {}
606
+
602
607
  self.sharinfo = {}
603
608
  self.methinfo = {}
604
609
 
@@ -634,6 +639,12 @@ class Proxy(s_base.Base):
634
639
  self.onfini(fini)
635
640
  self.link.onfini(self.fini)
636
641
 
642
+ def _hasTeleFeat(self, name, vers=1):
643
+ return self._features.get(name, 0) >= vers
644
+
645
+ def _hasTeleMeth(self, name):
646
+ return self.methinfo.get(name) is not None
647
+
637
648
  def _getSynVers(self):
638
649
  '''
639
650
  Helper method to retrieve the remote Synapse version from Proxy.
@@ -906,6 +917,7 @@ class Proxy(s_base.Base):
906
917
 
907
918
  self.sess = self.synack[1].get('sess')
908
919
  self._ahainfo = self.synack[1].get('ahainfo', {})
920
+ self._features = self.synack[1].get('features', {})
909
921
  self.sharinfo = self.synack[1].get('sharinfo', {})
910
922
  self.methinfo = self.sharinfo.get('meths', {})
911
923
 
@@ -4,6 +4,7 @@ import csv
4
4
  import sys
5
5
  import base64
6
6
  import shutil
7
+ import struct
7
8
  import asyncio
8
9
  import hashlib
9
10
  import logging
@@ -489,6 +490,28 @@ bar baz",vv
489
490
  with self.raises(s_exc.BadArg):
490
491
  bytslist = [b async for b in axon.get(sha256, 0, size=0)]
491
492
 
493
+ # test unpack
494
+ intdata = struct.pack('>QQQ', 1, 2, 3)
495
+ size, sha256 = await axon.put(intdata)
496
+ self.eq((1,), await axon.unpack(sha256, '>Q'))
497
+ self.eq((2,), await axon.unpack(sha256, '>Q', offs=8))
498
+ self.eq((3,), await axon.unpack(sha256, '>Q', offs=16))
499
+ self.eq((2, 3), await axon.unpack(sha256, '>QQ', offs=8))
500
+
501
+ fmt = 'Q' * 150_000
502
+ with self.raises(s_exc.BadArg) as cm:
503
+ await axon.unpack(sha256, '>' + fmt)
504
+ self.isin('Struct format would read too much data', cm.exception.get('mesg'))
505
+
506
+ with self.raises(s_exc.BadArg):
507
+ await axon.unpack(sha256, 'not a valid format')
508
+
509
+ with self.raises(s_exc.BadArg):
510
+ await axon.unpack(sha256, 123)
511
+
512
+ with self.raises(s_exc.BadDataValu):
513
+ await axon.unpack(sha256, '>Q', offs=24)
514
+
492
515
  async def test_axon_base(self):
493
516
  async with self.getTestAxon() as axon:
494
517
  self.isin('axon', axon.dmon.shared)
@@ -12,6 +12,34 @@ import synapse.tests.utils as s_t_utils
12
12
  logger = logging.getLogger(__name__)
13
13
 
14
14
  class CommonTest(s_t_utils.SynTest):
15
+
16
+ async def test_waitgenr(self):
17
+
18
+ async def genr():
19
+ yield 10
20
+ raise Exception('omg')
21
+
22
+ rets = [retn async for retn in s_common.waitgenr(genr(), 10)]
23
+
24
+ self.true(rets[0][0])
25
+ self.false(rets[1][0])
26
+
27
+ async def one():
28
+ yield 'item'
29
+
30
+ rets = [retn async for retn in s_common.waitgenr(one(), timeout=1.0)]
31
+ self.eq(rets, [(True, 'item')])
32
+
33
+ async def genr():
34
+ yield 1
35
+ await asyncio.sleep(60)
36
+ yield 2
37
+
38
+ rets = [retn async for retn in s_common.waitgenr(genr(), timeout=0.1)]
39
+ self.eq(rets[0], (True, 1))
40
+ self.false(rets[1][0])
41
+ self.eq(rets[1][1]['err'], 'TimeoutError')
42
+
15
43
  def test_tuplify(self):
16
44
  tv = ['node', [['test:str', 'test'],
17
45
  {'tags': {
@@ -334,3 +334,11 @@ class DataModelTest(s_t_utils.SynTest):
334
334
  self.none(core.model.edge(('meta:rule', 'matches', None)))
335
335
 
336
336
  core.model.delEdge(('meta:rule', 'matches', None))
337
+
338
+ async def test_datamodel_locked_subs(self):
339
+
340
+ async with self.getTestCore() as core:
341
+ await core.setDeprLock('it:prod:softver:semver:major', True)
342
+ nodes = await core.nodes('[ it:prod:softver=* :semver=3.1.0 ]')
343
+ self.none(nodes[0].get('semver:major'))
344
+ self.eq(1, nodes[0].get('semver:minor'))
@@ -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'))