synapse 2.160.0__py311-none-any.whl → 2.162.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 (71) hide show
  1. synapse/cortex.py +12 -7
  2. synapse/daemon.py +7 -2
  3. synapse/lib/agenda.py +8 -2
  4. synapse/lib/aha.py +4 -4
  5. synapse/lib/ast.py +3 -3
  6. synapse/lib/cell.py +20 -1
  7. synapse/lib/hiveauth.py +1 -1
  8. synapse/lib/httpapi.py +5 -0
  9. synapse/lib/layer.py +21 -1
  10. synapse/lib/nexus.py +9 -5
  11. synapse/lib/node.py +3 -4
  12. synapse/lib/rstorm.py +16 -0
  13. synapse/lib/schemas.py +2 -1
  14. synapse/lib/snap.py +20 -11
  15. synapse/lib/storm.py +19 -3
  16. synapse/lib/stormhttp.py +14 -2
  17. synapse/lib/stormlib/easyperm.py +5 -2
  18. synapse/lib/stormlib/gen.py +119 -44
  19. synapse/lib/stormlib/stix.py +6 -3
  20. synapse/lib/stormlib/vault.py +32 -15
  21. synapse/lib/stormtypes.py +187 -21
  22. synapse/lib/trigger.py +2 -0
  23. synapse/lib/version.py +2 -2
  24. synapse/lib/view.py +42 -10
  25. synapse/models/inet.py +9 -0
  26. synapse/models/infotech.py +28 -26
  27. synapse/models/orgs.py +3 -0
  28. synapse/models/proj.py +9 -2
  29. synapse/models/risk.py +32 -0
  30. synapse/telepath.py +6 -2
  31. synapse/tests/files/rstorm/testsvc.py +8 -1
  32. synapse/tests/files/stormpkg/testpkg.yaml +4 -0
  33. synapse/tests/test_axon.py +4 -4
  34. synapse/tests/test_cortex.py +66 -8
  35. synapse/tests/test_daemon.py +19 -0
  36. synapse/tests/test_lib_agenda.py +8 -0
  37. synapse/tests/test_lib_aha.py +18 -3
  38. synapse/tests/test_lib_ast.py +38 -16
  39. synapse/tests/test_lib_cell.py +3 -0
  40. synapse/tests/test_lib_grammar.py +4 -4
  41. synapse/tests/test_lib_httpapi.py +59 -0
  42. synapse/tests/test_lib_nexus.py +63 -0
  43. synapse/tests/test_lib_rstorm.py +38 -2
  44. synapse/tests/test_lib_snap.py +10 -0
  45. synapse/tests/test_lib_storm.py +61 -20
  46. synapse/tests/test_lib_stormhttp.py +21 -21
  47. synapse/tests/test_lib_stormlib_auth.py +3 -3
  48. synapse/tests/test_lib_stormlib_cell.py +1 -1
  49. synapse/tests/test_lib_stormlib_cortex.py +50 -2
  50. synapse/tests/test_lib_stormlib_gen.py +77 -0
  51. synapse/tests/test_lib_stormlib_json.py +2 -2
  52. synapse/tests/test_lib_stormlib_macro.py +1 -1
  53. synapse/tests/test_lib_stormlib_modelext.py +37 -37
  54. synapse/tests/test_lib_stormlib_oauth.py +20 -20
  55. synapse/tests/test_lib_stormlib_stix.py +3 -1
  56. synapse/tests/test_lib_stormlib_vault.py +1 -1
  57. synapse/tests/test_lib_stormtypes.py +159 -47
  58. synapse/tests/test_lib_stormwhois.py +1 -1
  59. synapse/tests/test_lib_trigger.py +11 -11
  60. synapse/tests/test_lib_view.py +23 -1
  61. synapse/tests/test_model_crypto.py +1 -1
  62. synapse/tests/test_model_inet.py +6 -0
  63. synapse/tests/test_model_orgs.py +2 -1
  64. synapse/tests/test_model_proj.py +6 -0
  65. synapse/tests/test_model_risk.py +10 -0
  66. synapse/tests/test_tools_storm.py +1 -1
  67. {synapse-2.160.0.dist-info → synapse-2.162.0.dist-info}/METADATA +5 -3
  68. {synapse-2.160.0.dist-info → synapse-2.162.0.dist-info}/RECORD +71 -71
  69. {synapse-2.160.0.dist-info → synapse-2.162.0.dist-info}/LICENSE +0 -0
  70. {synapse-2.160.0.dist-info → synapse-2.162.0.dist-info}/WHEEL +0 -0
  71. {synapse-2.160.0.dist-info → synapse-2.162.0.dist-info}/top_level.txt +0 -0
synapse/models/proj.py CHANGED
@@ -52,8 +52,11 @@ class ProjectModule(s_module.CoreModule):
52
52
  'doc': 'A collection of tickets related to a topic.',
53
53
  }),
54
54
  ('proj:ticket', ('guid', {}), {
55
- 'doc': 'A ticket in a ticketing system.',
56
- }),
55
+ 'doc': 'A ticket in a ticketing system.'}),
56
+
57
+ ('proj:project:type:taxonomy', ('taxonomy', {}), {
58
+ 'doc': 'A type taxonomy for projects.'}),
59
+
57
60
  ('proj:sprint', ('guid', {}), {
58
61
  'doc': 'A timeboxed period to complete a set amount of work.',
59
62
  }),
@@ -70,11 +73,15 @@ class ProjectModule(s_module.CoreModule):
70
73
 
71
74
  'forms': (
72
75
 
76
+ ('proj:project:type:taxonomy', {}, {}),
73
77
  ('proj:project', {}, (
74
78
 
75
79
  ('name', ('str', {'lower': True, 'onespace': True}), {
76
80
  'doc': 'The project name.'}),
77
81
 
82
+ ('type', ('proj:project:type:taxonomy', {}), {
83
+ 'doc': 'The project type.'}),
84
+
78
85
  ('desc', ('str', {}), {
79
86
  'disp': {'hint': 'text'},
80
87
  'doc': 'The project description.'}),
synapse/models/risk.py CHANGED
@@ -23,6 +23,15 @@ class CvssV3(s_types.Str):
23
23
  mesg = exc.get('mesg')
24
24
  raise s_exc.BadTypeValu(name=self.name, valu=text, mesg=mesg) from None
25
25
 
26
+ alertstatus = (
27
+ (0, 'new'),
28
+ (10, 'enrichment'),
29
+ (20, 'todo'),
30
+ (30, 'analysis'),
31
+ (40, 'remediation'),
32
+ (50, 'done'),
33
+ )
34
+
26
35
  class RiskModule(s_module.CoreModule):
27
36
 
28
37
  def getModelDefs(self):
@@ -281,17 +290,31 @@ class RiskModule(s_module.CoreModule):
281
290
 
282
291
  )),
283
292
  ('risk:mitigation', {}, (
293
+
284
294
  ('vuln', ('risk:vuln', {}), {
285
295
  'doc': 'The vulnerability that this mitigation addresses.'}),
296
+
286
297
  ('name', ('str', {}), {
287
298
  'doc': 'A brief name for this risk mitigation.'}),
299
+
288
300
  ('desc', ('str', {}), {
289
301
  'disp': {'hint': 'text'},
290
302
  'doc': 'A description of the mitigation approach for the vulnerability.'}),
303
+
291
304
  ('software', ('it:prod:softver', {}), {
292
305
  'doc': 'A software version which implements a fix for the vulnerability.'}),
306
+
293
307
  ('hardware', ('it:prod:hardware', {}), {
294
308
  'doc': 'A hardware version which implements a fix for the vulnerability.'}),
309
+
310
+ ('reporter', ('ou:org', {}), {
311
+ 'doc': 'The organization reporting on the mitigation.'}),
312
+
313
+ ('reporter:name', ('ou:name', {}), {
314
+ 'doc': 'The name of the organization reporting on the mitigation.'}),
315
+
316
+ ('tag', ('syn:tag', {}), {
317
+ 'doc': 'The tag used to annotate nodes which have the mitigation in place.'}),
295
318
  )),
296
319
  ('risk:vulnname', {}, ()),
297
320
  ('risk:vuln:type:taxonomy', {}, ()),
@@ -598,6 +621,9 @@ class RiskModule(s_module.CoreModule):
598
621
  'disp': {'hint': 'text'},
599
622
  'doc': 'A free-form description / overview of the alert.'}),
600
623
 
624
+ ('status', ('int', {'enums': alertstatus}), {
625
+ 'doc': 'The status of the alert.'}),
626
+
601
627
  ('benign', ('bool', {}), {
602
628
  'doc': 'Set to true if the alert has been confirmed benign. Set to false if malicious.'}),
603
629
 
@@ -611,6 +637,12 @@ class RiskModule(s_module.CoreModule):
611
637
  'ex': 'benign.false_positive',
612
638
  'doc': 'A verdict about why the alert is malicious or benign, as a taxonomy entry.'}),
613
639
 
640
+ ('assignee', ('syn:user', {}), {
641
+ 'doc': 'The Synapse user who is assigned to investigate the alert.'}),
642
+
643
+ ('ext:assignee', ('ps:contact', {}), {
644
+ 'doc': 'The alert assignee contact information from an external system.'}),
645
+
614
646
  ('engine', ('it:prod:softver', {}), {
615
647
  'doc': 'The software that generated the alert.'}),
616
648
 
synapse/telepath.py CHANGED
@@ -598,6 +598,7 @@ class Proxy(s_base.Base):
598
598
  self.tasks = {}
599
599
  self.shares = {}
600
600
 
601
+ self._ahainfo = {}
601
602
  self.sharinfo = {}
602
603
  self.methinfo = {}
603
604
 
@@ -902,6 +903,7 @@ class Proxy(s_base.Base):
902
903
  raise s_exc.LinkShutDown(mesg=mesg)
903
904
 
904
905
  self.sess = self.synack[1].get('sess')
906
+ self._ahainfo = self.synack[1].get('ahainfo', {})
905
907
  self.sharinfo = self.synack[1].get('sharinfo', {})
906
908
  self.methinfo = self.sharinfo.get('meths', {})
907
909
 
@@ -1018,6 +1020,9 @@ class Pool(s_base.Base):
1018
1020
  svcinfo = mesg[1].get('svcinfo')
1019
1021
  urlinfo = mergeAhaInfo(self.urlinfo, svcinfo.get('urlinfo', {}))
1020
1022
 
1023
+ if (oldc := self.clients.pop(svcname, None)) is not None:
1024
+ await oldc.fini()
1025
+
1021
1026
  # one-off default user to root
1022
1027
  self.clients[svcname] = await Client.anit(urlinfo, onlink=self._onPoolLink)
1023
1028
  await self.fire('svc:add', **mesg[1])
@@ -1068,7 +1073,6 @@ class Pool(s_base.Base):
1068
1073
  await reset()
1069
1074
 
1070
1075
  async for mesg in ahaproxy.iterPoolTopo(poolname):
1071
-
1072
1076
  hand = self.mesghands.get(mesg[0])
1073
1077
  if hand is None: # pragma: no cover
1074
1078
  logger.warning(f'Unknown AHA pool topography message: {mesg}')
@@ -1078,7 +1082,7 @@ class Pool(s_base.Base):
1078
1082
 
1079
1083
  except Exception as e:
1080
1084
  logger.warning(f'AHA pool topology task restarting: {e}')
1081
- await asyncio.sleep(1)
1085
+ await self.waitfini(timeout=1)
1082
1086
 
1083
1087
  async def proxy(self, timeout=None):
1084
1088
 
@@ -8,10 +8,17 @@ class TestsvcApi(s_cell.CellApi, s_stormsvc.StormSvc):
8
8
  {
9
9
  'name': 'testsvc',
10
10
  'version': (0, 0, 1),
11
+ 'onload': '''
12
+ $lib.time.sleep($lib.globals.get(onload_sleep, 0))
13
+ $lib.globals.set(testsvc, testsvc-done)
14
+ ''',
11
15
  'commands': (
12
16
  {
13
17
  'name': 'testsvc.test',
14
- 'storm': '$lib.print($lib.service.get($cmdconf.svciden).test())',
18
+ 'storm': '''
19
+ $lib.print($lib.service.get($cmdconf.svciden).test())
20
+ $lib.print($lib.globals.get(testsvc))
21
+ ''',
15
22
  },
16
23
  )
17
24
  },
@@ -31,6 +31,10 @@ modules:
31
31
  type: dict
32
32
  desc: A status dictionary.
33
33
 
34
+ onload: |
35
+ $lib.time.sleep($lib.globals.get(onload_sleep, 0))
36
+ $lib.globals.set(testpkg, testpkg-done)
37
+
34
38
  external_modules:
35
39
  - name: testext
36
40
  package: synapse.tests.files
@@ -985,10 +985,10 @@ bar baz",vv
985
985
 
986
986
  q = f'''
987
987
  $fields = $lib.list(
988
- $lib.dict(name=file, sha256=$sha256, filename=file),
989
- $lib.dict(name=zip_password, value=test),
990
- $lib.dict(name=dict, value=$lib.dict(foo=bar)),
991
- $lib.dict(name=bytes, value=$bytes)
988
+ ({{'name':'file', 'sha256':$sha256, 'filename':'file'}}),
989
+ ({{'name':'zip_password', 'value':'test'}}),
990
+ ({{'name':'dict', 'value':({{'foo':'bar'}}) }}),
991
+ ({{'name':'bytes', 'value':$bytes}})
992
992
  )
993
993
  $resp = $lib.inet.http.post("https://127.0.0.1:{port}/api/v1/pushfile",
994
994
  fields=$fields, ssl_verify=(0))
@@ -3947,6 +3947,60 @@ class CortexBasicTest(s_t_utils.SynTest):
3947
3947
  q = '$lib.graph.add(({"name": "foo", "forms": {"newp": {}}}))'
3948
3948
  await self.asyncraises(s_exc.NoSuchForm, core.nodes(q))
3949
3949
 
3950
+ iden = await core.callStorm('''
3951
+ $rules = ({
3952
+ "name": "graph proj",
3953
+ "forms": {
3954
+ "biz:deal": {
3955
+ "pivots": [" --> *", " <-- *"],
3956
+ },
3957
+ "pol:country": {
3958
+ "pivots": ["--> *", "<-- *"],
3959
+ "filters": ["-file:bytes"]
3960
+ },
3961
+ "*": {
3962
+ "pivots": ["-> #"]
3963
+ }
3964
+ },
3965
+ })
3966
+ return($lib.graph.add($rules).iden)
3967
+ ''')
3968
+
3969
+ guids = {
3970
+ 'race': 'cdd9e140d78830fb46d880dd36b62961',
3971
+ 'biz': 'c5352253cb13545205664e088ad210f0',
3972
+ 'orgA': '2e5dcdb52552ca22fa7996158588ea01',
3973
+ 'orgB': '9ea20ce1375d0ff0d16acfe807289a95',
3974
+ 'pol': '111e3b57f9bbf973febe74b1e98e89f8'
3975
+ }
3976
+
3977
+ await core.callStorm('''[
3978
+ (pol:country=$pol
3979
+ :name="some government"
3980
+ :flag=fd0a257397ee841ccd3b6ba76ad59c70310fd402ea3c9392d363f754ddaa67b5
3981
+ <(running)+ { [ pol:race=$race ] }
3982
+ +#some.stuff)
3983
+ (ou:org=$orgA
3984
+ :url=https://foo.bar.com/wat.html)
3985
+ (ou:org=$orgB
3986
+ :url=https://neato.burrito.org/stuff.html
3987
+ +#rep.stuff)
3988
+ (biz:deal=$biz
3989
+ :buyer:org=$orgA
3990
+ :seller:org=$orgB
3991
+ <(seen)+ { pol:country=$pol })
3992
+ ]''', opts={'vars': guids})
3993
+
3994
+ nodes = await core.nodes('biz:deal | $lib.graph.activate($iden)', opts={'vars': {'iden': iden}})
3995
+ self.len(4, nodes)
3996
+ ndefs = set([n.ndef for n in nodes])
3997
+ self.eq(ndefs, set([
3998
+ ('biz:deal', guids['biz']),
3999
+ ('ou:org', guids['orgA']),
4000
+ ('ou:org', guids['orgB']),
4001
+ ('pol:country', guids['pol']),
4002
+ ]))
4003
+
3950
4004
  with self.getTestDir() as dirn:
3951
4005
  async with self.getTestCore(dirn=dirn) as core:
3952
4006
  visi = await core.auth.addUser('visi')
@@ -3974,7 +4028,7 @@ class CortexBasicTest(s_t_utils.SynTest):
3974
4028
  self.len(1, nodes)
3975
4029
  self.eq('baz', nodes[0].ndef[1])
3976
4030
 
3977
- q = '$d = $lib.dict("field 1"=foo, "field 2"=bar) [test:str=$d.\'field 1\']'
4031
+ q = '$d = ({"field 1": "foo", "field 2": "bar"}) [test:str=$d.\'field 1\']'
3978
4032
  nodes = await core.nodes(q)
3979
4033
  self.len(1, nodes)
3980
4034
  self.eq('foo', nodes[0].ndef[1])
@@ -4852,7 +4906,7 @@ class CortexBasicTest(s_t_utils.SynTest):
4852
4906
  pode = podes[0]
4853
4907
  self.true(s_node.tagged(pode, '#foo'))
4854
4908
 
4855
- nodes = await core.nodes('$d = $lib.dict(foo=bar) [test:str=yop +#$d.foo]')
4909
+ nodes = await core.nodes('$d = ({"foo": "bar"}) [test:str=yop +#$d.foo]')
4856
4910
  self.len(1, nodes)
4857
4911
  self.nn(nodes[0].getTag('bar'))
4858
4912
 
@@ -4898,7 +4952,7 @@ class CortexBasicTest(s_t_utils.SynTest):
4898
4952
  pode = podes[0]
4899
4953
  self.true(s_node.tagged(pode, '#timetag'))
4900
4954
 
4901
- nodes = await core.nodes('$d = $lib.dict(foo="") [test:str=yop +?#$d.foo +#tag1]')
4955
+ nodes = await core.nodes('$d = ({"foo": ""}) [test:str=yop +?#$d.foo +#tag1]')
4902
4956
  self.len(1, nodes)
4903
4957
  self.none(nodes[0].getTag('foo.*'))
4904
4958
  self.nn(nodes[0].getTag('tag1'))
@@ -4937,7 +4991,7 @@ class CortexBasicTest(s_t_utils.SynTest):
4937
4991
  self.eq([n.ndef[0] for n in nodes], [*['test:str', 'inet:ipv4'] * 3])
4938
4992
 
4939
4993
  # non-runsafe iteration over a dictionary
4940
- q = '''$dict=$lib.dict(key1=valu1, key2=valu2) [(test:str=test1) (test:str=test2)]
4994
+ q = '''$dict=({"key1": "valu1", "key2": "valu2"}) [(test:str=test1) (test:str=test2)]
4941
4995
  for ($key, $valu) in $dict {
4942
4996
  [:hehe=$valu]
4943
4997
  }
@@ -4950,14 +5004,14 @@ class CortexBasicTest(s_t_utils.SynTest):
4950
5004
  self.eq(node.get('hehe'), 'valu2')
4951
5005
 
4952
5006
  # None values don't yield anything
4953
- q = '''$foo = $lib.dict()
5007
+ q = '''$foo = ({})
4954
5008
  for $name in $foo.bar { [ test:str=$name ] }
4955
5009
  '''
4956
5010
  nodes = await core.nodes(q)
4957
5011
  self.len(0, nodes)
4958
5012
 
4959
5013
  # Even with a inbound node, zero loop iterations will not yield inbound nodes.
4960
- q = '''test:str=test1 $foo = $lib.dict()
5014
+ q = '''test:str=test1 $foo = ({})
4961
5015
  for $name in $foo.bar { [ test:str=$name ] }
4962
5016
  '''
4963
5017
  nodes = await core.nodes(q)
@@ -8005,6 +8059,9 @@ class CortexBasicTest(s_t_utils.SynTest):
8005
8059
  self.true(core01.isactive)
8006
8060
  self.false(core00.isactive)
8007
8061
 
8062
+ # Let the mirror reconnect
8063
+ self.true(await asyncio.wait_for(core01.stormpool.ready.wait(), timeout=12))
8064
+
8008
8065
  with self.getLoggerStream('synapse') as stream:
8009
8066
  self.true(await core01.callStorm('inet:asn=0 return($lib.true)'))
8010
8067
 
@@ -8013,11 +8070,12 @@ class CortexBasicTest(s_t_utils.SynTest):
8013
8070
  self.isin('Offloading Storm query', data)
8014
8071
  self.notin('Timeout waiting for query mirror', data)
8015
8072
 
8016
- waiter = core01.stormpool.waiter('svc:del', 1)
8017
- msgs = await core01.stormlist('aha.pool.svc.del pool00... 01.core...')
8073
+ waiter = core01.stormpool.waiter(1, 'svc:del')
8074
+ msgs = await core01.stormlist('aha.pool.svc.del pool00... 01.core...', opts={'mirror': False})
8018
8075
  self.stormHasNoWarnErr(msgs)
8019
8076
  self.stormIsInPrint('AHA service (01.core...) removed from service pool (pool00.loop.vertex.link)', msgs)
8020
8077
 
8078
+ # TODO: this wait should not return None
8021
8079
  await waiter.wait(timeout=3)
8022
8080
  with self.getLoggerStream('synapse') as stream:
8023
8081
  msgs = await alist(core01.storm('inet:asn=0'))
@@ -56,6 +56,25 @@ class DaemonTest(s_t_utils.SynTest):
56
56
  async with await s_telepath.openurl(f'tcp://127.0.0.1:{port}/foo') as foo:
57
57
  pass
58
58
 
59
+ async def test_dmon_ahainfo(self):
60
+
61
+ async with await s_daemon.Daemon.anit() as dmon:
62
+
63
+ host, port = await dmon.listen('tcp://127.0.0.1:0')
64
+ dmon.share('*', Foo())
65
+
66
+ async with await s_telepath.openurl(f'tcp://127.0.0.1:{port}') as proxy:
67
+ self.eq(proxy._ahainfo, {})
68
+
69
+ ahainfo = {'name': 'test.loop.vertex.link'}
70
+ async with await s_daemon.Daemon.anit(ahainfo=ahainfo) as dmon:
71
+
72
+ host, port = await dmon.listen('tcp://127.0.0.1:0')
73
+ dmon.share('*', Foo())
74
+
75
+ async with await s_telepath.openurl(f'tcp://127.0.0.1:{port}') as proxy:
76
+ self.eq(proxy._ahainfo, ahainfo)
77
+
59
78
  class SvcApi(s_cell.CellApi, s_stormsvc.StormSvc):
60
79
  _storm_svc_name = 'foo'
61
80
  _storm_svc_pkgs = ( # type: ignore
@@ -346,9 +346,11 @@ class AgendaTest(s_t_utils.SynTest):
346
346
  adef = await agenda.add(cdef)
347
347
  guid = adef.get('iden')
348
348
 
349
+ strt = await core.nexsroot.index()
349
350
  # bypass the API because it would actually syntax check
350
351
  unixtime += 60
351
352
  self.eq((11, 'boom'), await asyncio.wait_for(core.callStorm('return($lib.queue.gen(visi).pop(wait=$lib.true))'), timeout=5))
353
+ await core.nexsroot.waitOffs(strt + 5)
352
354
 
353
355
  appt = await agenda.get(guid)
354
356
  self.eq(appt.isrunning, False)
@@ -399,6 +401,8 @@ class AgendaTest(s_t_utils.SynTest):
399
401
  await agenda.add(cdef)
400
402
 
401
403
  # Lock user and advance time
404
+ strt = await core.nexsroot.index()
405
+
402
406
  await visi.setLocked(True)
403
407
 
404
408
  with self.getLoggerStream('synapse.lib.agenda', 'locked') as stream:
@@ -408,6 +412,8 @@ class AgendaTest(s_t_utils.SynTest):
408
412
  while not stream.wait(0.1):
409
413
  await asyncio.sleep(0)
410
414
 
415
+ await core.nexsroot.waitOffs(strt + 4)
416
+
411
417
  self.eq(2, appt.startcount)
412
418
 
413
419
  async def test_agenda_persistence(self):
@@ -579,6 +585,7 @@ class AgendaTest(s_t_utils.SynTest):
579
585
  jobs = await core.callStorm('return($lib.cron.list())')
580
586
  self.len(1, jobs)
581
587
  self.eq(defview.iden, jobs[0]['view'])
588
+ self.nn(jobs[0].get('created'))
582
589
 
583
590
  core.agenda._addTickOff(60)
584
591
  retn = await core.callStorm('return($lib.queue.get(testq).get())', opts=asfail)
@@ -799,6 +806,7 @@ class AgendaTest(s_t_utils.SynTest):
799
806
 
800
807
  nodes = await core01.nodes('syn:cron')
801
808
  self.len(1, nodes)
809
+ self.nn(nodes[0].props.get('.created'))
802
810
  self.eq(nodes[0].props.get('name'), 'foo')
803
811
  self.eq(nodes[0].props.get('doc'), 'bar')
804
812
 
@@ -248,6 +248,11 @@ class AhaTest(s_test.SynTest):
248
248
  }
249
249
  async with self.getTestCryo(conf=conf) as cryo:
250
250
 
251
+ info = await cryo.getCellInfo()
252
+ cnfo = info.get('cell')
253
+ anfo = cnfo.get('aha')
254
+ self.eq(cnfo.get('aha'), {'name': '0.cryo', 'leader': 'cryo', 'network': 'foo'})
255
+
251
256
  await cryo.auth.rootuser.setPasswd('secret')
252
257
 
253
258
  await wait01.wait(timeout=2)
@@ -1160,7 +1165,14 @@ class AhaTest(s_test.SynTest):
1160
1165
 
1161
1166
  async with await s_telepath.open('aha://pool00...') as pool:
1162
1167
 
1163
- waiter = pool.waiter('svc:add', 2)
1168
+ replay = s_common.envbool('SYNDEV_NEXUS_REPLAY')
1169
+ nevents = 5 if replay else 3
1170
+
1171
+ waiter = pool.waiter(nevents, 'svc:add')
1172
+
1173
+ msgs = await core00.stormlist('aha.pool.svc.add pool00... 01...')
1174
+ self.stormHasNoWarnErr(msgs)
1175
+ self.stormIsInPrint('AHA service (01...) added to service pool (pool00.loop.vertex.link)', msgs)
1164
1176
 
1165
1177
  msgs = await core00.stormlist('aha.pool.svc.add pool00... 01...')
1166
1178
  self.stormHasNoWarnErr(msgs)
@@ -1179,12 +1191,15 @@ class AhaTest(s_test.SynTest):
1179
1191
  self.eq(core00.auth.rootuser.iden, poolinfo['services']['00.loop.vertex.link']['creator'])
1180
1192
  self.eq(core00.auth.rootuser.iden, poolinfo['services']['01.loop.vertex.link']['creator'])
1181
1193
 
1194
+ for client in pool.clients.values():
1195
+ await client.proxy(timeout=3)
1196
+
1182
1197
  proxy00 = await pool.proxy(timeout=3)
1183
1198
  run00 = await (await pool.proxy(timeout=3)).getCellRunId()
1184
1199
  run01 = await (await pool.proxy(timeout=3)).getCellRunId()
1185
1200
  self.ne(run00, run01)
1186
1201
 
1187
- waiter = pool.waiter('pool:reset', 1)
1202
+ waiter = pool.waiter(1, 'pool:reset')
1188
1203
 
1189
1204
  ahaproxy = await pool.aha.proxy()
1190
1205
  await ahaproxy.fini()
@@ -1192,7 +1207,7 @@ class AhaTest(s_test.SynTest):
1192
1207
  await waiter.wait(timeout=3)
1193
1208
 
1194
1209
  # wait for the pool to be notified of the topology change
1195
- waiter = pool.waiter('svc:del', 1)
1210
+ waiter = pool.waiter(1, 'svc:del')
1196
1211
 
1197
1212
  msgs = await core00.stormlist('aha.pool.svc.del pool00... 00...')
1198
1213
  self.stormHasNoWarnErr(msgs)
@@ -495,7 +495,7 @@ class AstTest(s_test.SynTest):
495
495
  self.none(await core.callStorm('$foo = $lib.null return($foo.bar.baz)'))
496
496
 
497
497
  q = '''
498
- $d = $lib.dict(foo=bar, bar=baz, baz=biz)
498
+ $d = ({"foo": "bar", "bar": "baz", "baz": "biz"})
499
499
  for ($key, $val) in $d {
500
500
  [ test:str=$d.$key ]
501
501
  }
@@ -506,7 +506,7 @@ class AstTest(s_test.SynTest):
506
506
  self.eq(set(['bar', 'baz', 'biz']), reprs)
507
507
 
508
508
  q = '''
509
- $data = $lib.dict(foo=$lib.dict(bar=$lib.dict(woot=final)))
509
+ $data = ({"foo": ({"bar": ({"woot": "final"}) }) })
510
510
  $varkey=woot
511
511
  [ test:str=$data.foo.bar.$varkey ]
512
512
  '''
@@ -520,11 +520,11 @@ class AstTest(s_test.SynTest):
520
520
 
521
521
  $f = var
522
522
  $g = tar
523
- $de = $lib.dict(car=$f, zar=$g)
524
- $dd = $lib.dict(mar=$de)
525
- $dc = $lib.dict(bar=$dd)
526
- $db = $lib.dict(var=$dc)
527
- $foo = $lib.dict(woot=$db)
523
+ $de = ({"car": $f, "zar": $g})
524
+ $dd = ({"mar": $de})
525
+ $dc = ({"bar": $dd})
526
+ $db = ({"var": $dc})
527
+ $foo = ({"woot": $db})
528
528
  [ test:str=$foo.woot.var.$bar.mar.$car ]
529
529
  '''
530
530
  nodes = await core.nodes(q)
@@ -532,7 +532,7 @@ class AstTest(s_test.SynTest):
532
532
  self.eq('var', nodes[0].repr())
533
533
 
534
534
  q = '''
535
- $data = $lib.dict('vertex project'=foobar)
535
+ $data = ({'vertex project': 'foobar'})
536
536
  $"spaced key" = 'vertex project'
537
537
  [ test:str = $data.$"spaced key" ]
538
538
  '''
@@ -541,7 +541,7 @@ class AstTest(s_test.SynTest):
541
541
  self.eq('foobar', nodes[0].repr())
542
542
 
543
543
  q = '''
544
- $data = $lib.dict('bar baz'=woot)
544
+ $data = ({'bar baz': "woot"})
545
545
  $'new key' = 'bar baz'
546
546
  [ test:str=$data.$'new key' ]
547
547
  '''
@@ -550,9 +550,9 @@ class AstTest(s_test.SynTest):
550
550
  self.eq('woot', nodes[0].repr())
551
551
 
552
552
  q = '''
553
- $bottom = $lib.dict(lastkey=synapse)
554
- $subdata = $lib.dict('bar baz'=$bottom)
555
- $data = $lib.dict(vertex=$subdata)
553
+ $bottom = ({"lastkey": "synapse"})
554
+ $subdata = ({'bar baz': $bottom})
555
+ $data = ({"vertex": $subdata})
556
556
  $'new key' = 'bar baz'
557
557
  $'over key' = vertex
558
558
  [ test:str=$data.$'over key'.$"new key".lastkey ]
@@ -562,7 +562,7 @@ class AstTest(s_test.SynTest):
562
562
  self.eq('synapse', nodes[0].repr())
563
563
 
564
564
  q = '''
565
- $data = $lib.dict(foo=bar)
565
+ $data = ({"foo": "bar"})
566
566
  $key = nope
567
567
  [ test:str=$data.$key ]
568
568
  '''
@@ -1850,7 +1850,7 @@ class AstTest(s_test.SynTest):
1850
1850
 
1851
1851
  q = '''
1852
1852
  $x = asdf
1853
- $y = $lib.dict()
1853
+ $y = ({})
1854
1854
 
1855
1855
  $y.foo = bar
1856
1856
  $y."baz faz" = hehe
@@ -1870,7 +1870,7 @@ class AstTest(s_test.SynTest):
1870
1870
  self.eq(nodes[5].ndef[1], 'qwer')
1871
1871
 
1872
1872
  # non-runtsafe test
1873
- q = '''$dict = $lib.dict()
1873
+ q = '''$dict = ({})
1874
1874
  [(test:str=key1 :hehe=val1) (test:str=key2 :hehe=val2)]
1875
1875
  $key=$node.value()
1876
1876
  $dict.$key=:hehe
@@ -2822,7 +2822,7 @@ class AstTest(s_test.SynTest):
2822
2822
  mesgs = await core.stormlist(q, opts={'vars': {'ret': 'foo'}})
2823
2823
  self.stormIsInErr('Cannot find name [squeeeeeee]', mesgs)
2824
2824
 
2825
- q = '$ret=$lib.dict(bar=$ret)'
2825
+ q = '$ret=({"bar": $ret})'
2826
2826
  mesgs = await core.stormlist(q)
2827
2827
  self.stormIsInErr('Missing variable: ret', mesgs)
2828
2828
 
@@ -3441,6 +3441,14 @@ class AstTest(s_test.SynTest):
3441
3441
  self.len(1, nodes)
3442
3442
  self.eq(nodes[0].ndef, ('test:str', 'test2'))
3443
3443
 
3444
+ q = '''
3445
+ $foo = bar
3446
+ $q = ${ $lib.print($foo) }
3447
+ for $x in $q { $lib.print(bar) }
3448
+ '''
3449
+ msgs = await core.stormlist(q)
3450
+ self.stormIsInPrint('bar', msgs)
3451
+
3444
3452
  # Should produce the same results in a macro sub-runtime
3445
3453
  async with self.getTestCore() as core:
3446
3454
  nodes = await core.nodes('[test:str=test1]')
@@ -3480,6 +3488,20 @@ class AstTest(s_test.SynTest):
3480
3488
  self.len(1, nodes)
3481
3489
  self.eq(nodes[0].ndef, ('test:str', 'test2'))
3482
3490
 
3491
+ q = '''
3492
+ $q = ${
3493
+ $foo = bar
3494
+ $q = ${ $lib.print($foo) }
3495
+ for $x in $q { $lib.print(bar) }
3496
+ }
3497
+ $lib.macro.set(test, $q)
3498
+ return($lib.true)
3499
+ '''
3500
+ self.true(await core.callStorm(q))
3501
+
3502
+ msgs = await core.stormlist('macro.exec test')
3503
+ self.stormIsInPrint('bar', msgs)
3504
+
3483
3505
  async def test_ast_subq_runtsafety(self):
3484
3506
 
3485
3507
  async with self.getTestCore() as core:
@@ -559,6 +559,9 @@ class CellTest(s_t_utils.SynTest):
559
559
  # A Cortex populated cellvers
560
560
  self.isin('cortex:defaults', cnfo.get('cellvers', {}))
561
561
 
562
+ # Defaults aha data is
563
+ self.eq(cnfo.get('aha'), {'name': None, 'leader': None, 'network': None})
564
+
562
565
  # Synapse information
563
566
  self.eq(snfo.get('version'), s_version.version)
564
567
  self.eq(snfo.get('verstring'), s_version.verstring),
@@ -119,7 +119,7 @@ Queries = [
119
119
  '#test.bar -#test <+- *',
120
120
  '#test.bar -#test <- *',
121
121
  '$bar=5.5.5.5 [ inet:ipv4=$bar ]',
122
- '$blah = $lib.dict(foo=vertex.link) [ inet:fqdn=$blah.foo ]',
122
+ '$blah = ({"foo": "vertex.link"}) [ inet:fqdn=$blah.foo ]',
123
123
  '($tick, $tock) = .seen',
124
124
  '.created',
125
125
  '.created<2010',
@@ -585,7 +585,7 @@ Queries = [
585
585
  ''' [(ou:org=c71cd602f73af5bed208da21012fdf54 :loc=us )]''',
586
586
  'function x(y, z) { return ($( $x - $y ) ) }',
587
587
  'function echo(arg, arg2=default) { return ($arg) }',
588
- '$name = asdf $foo = $lib.dict() $foo.bar = asdf $foo."bar baz" = asdf $foo.$name = asdf',
588
+ '$name = asdf $foo = ({}) $foo.bar = asdf $foo."bar baz" = asdf $foo.$name = asdf',
589
589
  '[test:str=a] switch $node.form() { hehe: {[+#baz]} }',
590
590
  '[test:str=a] switch $woot { hehe: {[+#baz]} }',
591
591
  '[test:str=c] switch $woot { hehe: {[+#baz]} *: {[+#jaz]} }',
@@ -830,7 +830,7 @@ _ParseResults = [
830
830
  'Query: [LiftTag: [TagName: [Const: test, Const: bar]], FiltOper: [Const: -, TagCond: [TagMatch: [Const: test]]], PivotIn: [], isjoin=True]',
831
831
  'Query: [LiftTag: [TagName: [Const: test, Const: bar]], FiltOper: [Const: -, TagCond: [TagMatch: [Const: test]]], PivotIn: [], isjoin=False]',
832
832
  'Query: [SetVarOper: [Const: bar, Const: 5.5.5.5], EditNodeAdd: [FormName: [Const: inet:ipv4], Const: =, VarValue: [Const: bar]]]',
833
- 'Query: [SetVarOper: [Const: blah, FuncCall: [VarDeref: [VarValue: [Const: lib], Const: dict], CallArgs: [], CallKwargs: [CallKwarg: [Const: foo, Const: vertex.link]]]], EditNodeAdd: [FormName: [Const: inet:fqdn], Const: =, VarDeref: [VarValue: [Const: blah], Const: foo]]]',
833
+ 'Query: [SetVarOper: [Const: blah, DollarExpr: [ExprDict: [Const: foo, Const: vertex.link]]], EditNodeAdd: [FormName: [Const: inet:fqdn], Const: =, VarDeref: [VarValue: [Const: blah], Const: foo]]]',
834
834
  "Query: [VarListSetOper: [VarList: ['tick', 'tock'], UnivPropValue: [UnivProp: [Const: .seen]]]]",
835
835
  'Query: [LiftProp: [Const: .created]]',
836
836
  'Query: [LiftPropBy: [Const: .created, Const: <, Const: 2010]]',
@@ -1241,7 +1241,7 @@ _ParseResults = [
1241
1241
  'Query: [EditParens: [EditNodeAdd: [FormName: [Const: ou:org], Const: =, Const: c71cd602f73af5bed208da21012fdf54], EditPropSet: [RelProp: [Const: loc], Const: =, Const: us]]]',
1242
1242
  'Query: [Function: [Const: x, FuncArgs: [Const: y, Const: z], Query: [Return: [DollarExpr: [ExprNode: [VarValue: [Const: x], Const: -, VarValue: [Const: y]]]]]]]',
1243
1243
  'Query: [Function: [Const: echo, FuncArgs: [Const: arg, CallKwarg: [Const: arg2, Const: default]], Query: [Return: [VarValue: [Const: arg]]]]]',
1244
- 'Query: [SetVarOper: [Const: name, Const: asdf], SetVarOper: [Const: foo, FuncCall: [VarDeref: [VarValue: [Const: lib], Const: dict], CallArgs: [], CallKwargs: []]], SetItemOper: [VarValue: [Const: foo], Const: bar, Const: asdf], SetItemOper: [VarValue: [Const: foo], Const: bar baz, Const: asdf], SetItemOper: [VarValue: [Const: foo], VarValue: [Const: name], Const: asdf]]',
1244
+ 'Query: [SetVarOper: [Const: name, Const: asdf], SetVarOper: [Const: foo, DollarExpr: [ExprDict: []]], SetItemOper: [VarValue: [Const: foo], Const: bar, Const: asdf], SetItemOper: [VarValue: [Const: foo], Const: bar baz, Const: asdf], SetItemOper: [VarValue: [Const: foo], VarValue: [Const: name], Const: asdf]]',
1245
1245
  'Query: [EditNodeAdd: [FormName: [Const: test:str], Const: =, Const: a], SwitchCase: [FuncCall: [VarDeref: [VarValue: [Const: node], Const: form], CallArgs: [], CallKwargs: []], CaseEntry: [Const: hehe, SubQuery: [Query: [EditTagAdd: [TagName: [Const: baz]]]]]]]',
1246
1246
  'Query: [EditNodeAdd: [FormName: [Const: test:str], Const: =, Const: a], SwitchCase: [VarValue: [Const: woot], CaseEntry: [Const: hehe, SubQuery: [Query: [EditTagAdd: [TagName: [Const: baz]]]]]]]',
1247
1247
  'Query: [EditNodeAdd: [FormName: [Const: test:str], Const: =, Const: c], SwitchCase: [VarValue: [Const: woot], CaseEntry: [Const: hehe, SubQuery: [Query: [EditTagAdd: [TagName: [Const: baz]]]]], CaseEntry: [SubQuery: [Query: [EditTagAdd: [TagName: [Const: jaz]]]]]]]',