synapse 2.192.0__py311-none-any.whl → 2.194.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.
- synapse/common.py +15 -0
- synapse/cortex.py +19 -25
- synapse/datamodel.py +6 -3
- synapse/exc.py +6 -1
- synapse/lib/agenda.py +17 -6
- synapse/lib/ast.py +242 -97
- synapse/lib/auth.py +1 -0
- synapse/lib/cell.py +31 -85
- synapse/lib/cli.py +20 -11
- synapse/lib/parser.py +5 -1
- synapse/lib/snap.py +44 -15
- synapse/lib/storm.lark +16 -1
- synapse/lib/storm.py +40 -21
- synapse/lib/storm_format.py +1 -0
- synapse/lib/stormctrl.py +88 -6
- synapse/lib/stormlib/cache.py +6 -2
- synapse/lib/stormlib/json.py +5 -2
- synapse/lib/stormlib/scrape.py +1 -1
- synapse/lib/stormlib/stix.py +8 -8
- synapse/lib/stormtypes.py +32 -5
- synapse/lib/version.py +2 -2
- synapse/lib/view.py +20 -3
- synapse/models/geopol.py +1 -0
- synapse/models/geospace.py +1 -0
- synapse/models/inet.py +20 -1
- synapse/models/infotech.py +24 -6
- synapse/models/orgs.py +7 -2
- synapse/models/person.py +15 -4
- synapse/models/risk.py +19 -2
- synapse/models/telco.py +10 -3
- synapse/tests/test_axon.py +6 -6
- synapse/tests/test_cortex.py +133 -14
- synapse/tests/test_exc.py +4 -0
- synapse/tests/test_lib_agenda.py +282 -2
- synapse/tests/test_lib_aha.py +13 -6
- synapse/tests/test_lib_ast.py +301 -10
- synapse/tests/test_lib_auth.py +6 -7
- synapse/tests/test_lib_cell.py +71 -1
- synapse/tests/test_lib_grammar.py +14 -0
- synapse/tests/test_lib_layer.py +1 -1
- synapse/tests/test_lib_lmdbslab.py +3 -3
- synapse/tests/test_lib_storm.py +273 -55
- synapse/tests/test_lib_stormctrl.py +65 -0
- synapse/tests/test_lib_stormhttp.py +5 -5
- synapse/tests/test_lib_stormlib_auth.py +5 -5
- synapse/tests/test_lib_stormlib_cache.py +38 -6
- synapse/tests/test_lib_stormlib_json.py +20 -0
- synapse/tests/test_lib_stormlib_modelext.py +3 -3
- synapse/tests/test_lib_stormlib_scrape.py +6 -6
- synapse/tests/test_lib_stormlib_spooled.py +1 -1
- synapse/tests/test_lib_stormlib_xml.py +5 -5
- synapse/tests/test_lib_stormtypes.py +54 -57
- synapse/tests/test_lib_view.py +1 -1
- synapse/tests/test_model_base.py +1 -2
- synapse/tests/test_model_geopol.py +4 -0
- synapse/tests/test_model_geospace.py +6 -0
- synapse/tests/test_model_inet.py +43 -5
- synapse/tests/test_model_infotech.py +10 -1
- synapse/tests/test_model_orgs.py +17 -2
- synapse/tests/test_model_person.py +23 -1
- synapse/tests/test_model_risk.py +13 -0
- synapse/tests/test_tools_healthcheck.py +4 -4
- synapse/tests/test_tools_storm.py +95 -0
- synapse/tests/test_utils.py +17 -18
- synapse/tests/test_utils_getrefs.py +1 -1
- synapse/tests/utils.py +0 -35
- synapse/tools/changelog.py +6 -4
- synapse/tools/storm.py +1 -1
- synapse/utils/getrefs.py +14 -3
- synapse/vendor/cpython/lib/http/__init__.py +0 -0
- synapse/vendor/cpython/lib/http/cookies.py +59 -0
- synapse/vendor/cpython/lib/test/test_http_cookies.py +49 -0
- {synapse-2.192.0.dist-info → synapse-2.194.0.dist-info}/METADATA +6 -6
- {synapse-2.192.0.dist-info → synapse-2.194.0.dist-info}/RECORD +77 -73
- {synapse-2.192.0.dist-info → synapse-2.194.0.dist-info}/WHEEL +1 -1
- {synapse-2.192.0.dist-info → synapse-2.194.0.dist-info}/LICENSE +0 -0
- {synapse-2.192.0.dist-info → synapse-2.194.0.dist-info}/top_level.txt +0 -0
synapse/tests/test_axon.py
CHANGED
|
@@ -990,12 +990,12 @@ bar baz",vv
|
|
|
990
990
|
self.isinstance(resp.get('err'), tuple)
|
|
991
991
|
|
|
992
992
|
q = f'''
|
|
993
|
-
$fields =
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
)
|
|
993
|
+
$fields = ([
|
|
994
|
+
{{'name':'file', 'sha256':$sha256, 'filename':'file'}},
|
|
995
|
+
{{'name':'zip_password', 'value':'test'}},
|
|
996
|
+
{{'name':'dict', 'value':{{'foo':'bar'}} }},
|
|
997
|
+
{{'name':'bytes', 'value':$bytes}}
|
|
998
|
+
])
|
|
999
999
|
$resp = $lib.inet.http.post("https://127.0.0.1:{port}/api/v1/pushfile",
|
|
1000
1000
|
fields=$fields, ssl_verify=(0))
|
|
1001
1001
|
return($resp)
|
synapse/tests/test_cortex.py
CHANGED
|
@@ -440,7 +440,7 @@ class CortexTest(s_t_utils.SynTest):
|
|
|
440
440
|
'interfaces': ['lookup'],
|
|
441
441
|
'storm': '''
|
|
442
442
|
function lookup(tokens) {
|
|
443
|
-
$looks =
|
|
443
|
+
$looks = ()
|
|
444
444
|
for $token in $tokens { $looks.append( (inet:fqdn, $token) ) }
|
|
445
445
|
return($looks)
|
|
446
446
|
}
|
|
@@ -484,7 +484,7 @@ class CortexTest(s_t_utils.SynTest):
|
|
|
484
484
|
self.len(0, mods)
|
|
485
485
|
self.len(0, core.modsbyiface.get('lookup'))
|
|
486
486
|
|
|
487
|
-
|
|
487
|
+
core.loadStormPkg(pkgdef)
|
|
488
488
|
|
|
489
489
|
mods = await core.getStormIfaces('lookup')
|
|
490
490
|
self.len(1, mods)
|
|
@@ -513,7 +513,7 @@ class CortexTest(s_t_utils.SynTest):
|
|
|
513
513
|
vals = [r async for r in core.view.callStormIface('boom', todo)]
|
|
514
514
|
self.eq((), vals)
|
|
515
515
|
|
|
516
|
-
|
|
516
|
+
core._dropStormPkg(pkgdef)
|
|
517
517
|
self.none(core.modsbyiface.get('lookup'))
|
|
518
518
|
|
|
519
519
|
mods = await core.getStormIfaces('lookup')
|
|
@@ -558,7 +558,7 @@ class CortexTest(s_t_utils.SynTest):
|
|
|
558
558
|
nodes = await core.nodes('foo@bar.com foo@bar.com', opts={'mode': 'lookup'})
|
|
559
559
|
self.eq(['inet:email', 'inet:email'], [n.ndef[0] for n in nodes])
|
|
560
560
|
|
|
561
|
-
|
|
561
|
+
core.loadStormPkg(pkgdef)
|
|
562
562
|
self.len(1, await core.getStormIfaces('search'))
|
|
563
563
|
|
|
564
564
|
todo = s_common.todo('search', ('foo@bar.com',))
|
|
@@ -679,7 +679,7 @@ class CortexTest(s_t_utils.SynTest):
|
|
|
679
679
|
# functions that don't return a generator
|
|
680
680
|
storm = '''
|
|
681
681
|
function x() {
|
|
682
|
-
$lst =
|
|
682
|
+
$lst = ()
|
|
683
683
|
[ ou:org=* ou:org=* +#cat ]
|
|
684
684
|
$lst.append($node)
|
|
685
685
|
fini { return($lst) }
|
|
@@ -692,7 +692,7 @@ class CortexTest(s_t_utils.SynTest):
|
|
|
692
692
|
|
|
693
693
|
storm = '''
|
|
694
694
|
function x() {
|
|
695
|
-
$lst =
|
|
695
|
+
$lst = ()
|
|
696
696
|
[ ou:org=* ou:org=* +#dog ]
|
|
697
697
|
$lst.append($node)
|
|
698
698
|
fini { return($lst) }
|
|
@@ -974,7 +974,7 @@ class CortexTest(s_t_utils.SynTest):
|
|
|
974
974
|
await core.nodes('media:news -(refs)> $(10)')
|
|
975
975
|
|
|
976
976
|
self.eq(1, await core.callStorm('''
|
|
977
|
-
$list =
|
|
977
|
+
$list = ()
|
|
978
978
|
for $edge in $lib.view.get().getEdges() { $list.append($edge) }
|
|
979
979
|
return($list.size())
|
|
980
980
|
'''))
|
|
@@ -982,7 +982,7 @@ class CortexTest(s_t_utils.SynTest):
|
|
|
982
982
|
# check that auto-deleting a node's edges works
|
|
983
983
|
await core.nodes('media:news | delnode')
|
|
984
984
|
self.eq(0, await core.callStorm('''
|
|
985
|
-
$list =
|
|
985
|
+
$list = ()
|
|
986
986
|
for $edge in $lib.view.get().getEdges() { $list.append($edge) }
|
|
987
987
|
return($list.size())
|
|
988
988
|
'''))
|
|
@@ -1017,7 +1017,7 @@ class CortexTest(s_t_utils.SynTest):
|
|
|
1017
1017
|
self.eq(('1', '2'), retn)
|
|
1018
1018
|
|
|
1019
1019
|
with self.raises(s_exc.StormRuntimeError):
|
|
1020
|
-
q = '$foo
|
|
1020
|
+
q = '$foo=() $bar=$foo.index(10) return ( $bar )'
|
|
1021
1021
|
await proxy.callStorm(q)
|
|
1022
1022
|
|
|
1023
1023
|
with self.raises(s_exc.SynErr) as cm:
|
|
@@ -1033,6 +1033,26 @@ class CortexTest(s_t_utils.SynTest):
|
|
|
1033
1033
|
self.eq(cm.exception.get('hehe'), 'haha')
|
|
1034
1034
|
self.eq(cm.exception.get('key'), 1)
|
|
1035
1035
|
|
|
1036
|
+
# We convert StormLoopCtrl and StormGenrCtrl into StormRuntimeError
|
|
1037
|
+
opts = {'vars': {'i': 2}}
|
|
1038
|
+
q = 'if ($i = 2) { break }'
|
|
1039
|
+
with self.raises(s_exc.StormRuntimeError) as cm:
|
|
1040
|
+
await core.callStorm(q, opts=opts)
|
|
1041
|
+
self.eq(cm.exception.get('mesg'),
|
|
1042
|
+
'Loop control statement "break" used outside of a loop.')
|
|
1043
|
+
|
|
1044
|
+
q = 'if ($i = 2) { continue }'
|
|
1045
|
+
with self.raises(s_exc.StormRuntimeError) as cm:
|
|
1046
|
+
await core.callStorm(q, opts=opts)
|
|
1047
|
+
self.eq(cm.exception.get('mesg'),
|
|
1048
|
+
'Loop control statement "continue" used outside of a loop.')
|
|
1049
|
+
|
|
1050
|
+
q = 'if ($i = 2) { stop }'
|
|
1051
|
+
with self.raises(s_exc.StormRuntimeError) as cm:
|
|
1052
|
+
await core.callStorm(q, opts=opts)
|
|
1053
|
+
self.eq(cm.exception.get('mesg'),
|
|
1054
|
+
'Generator control statement "stop" used outside of a generator function.')
|
|
1055
|
+
|
|
1036
1056
|
with self.getAsyncLoggerStream('synapse.lib.view', 'callStorm cancelled') as stream:
|
|
1037
1057
|
async with core.getLocalProxy() as proxy:
|
|
1038
1058
|
|
|
@@ -1069,7 +1089,7 @@ class CortexTest(s_t_utils.SynTest):
|
|
|
1069
1089
|
self.eq('ok', retn.get('status'))
|
|
1070
1090
|
self.eq('asdf', retn['result'])
|
|
1071
1091
|
|
|
1072
|
-
body = {'query': '$foo
|
|
1092
|
+
body = {'query': '$foo=() $bar=$foo.index(10) return ( $bar )'}
|
|
1073
1093
|
async with sess.get(f'https://localhost:{port}/api/v1/storm/call', json=body) as resp:
|
|
1074
1094
|
retn = await resp.json()
|
|
1075
1095
|
self.eq('err', retn.get('status'))
|
|
@@ -1081,7 +1101,7 @@ class CortexTest(s_t_utils.SynTest):
|
|
|
1081
1101
|
retn = await resp.json()
|
|
1082
1102
|
self.eq('err', retn.get('status'))
|
|
1083
1103
|
self.eq('StormExit', retn.get('code'))
|
|
1084
|
-
self.eq('', retn.get('mesg'))
|
|
1104
|
+
self.eq('StormExit: ', retn.get('mesg'))
|
|
1085
1105
|
|
|
1086
1106
|
# No body
|
|
1087
1107
|
async with sess.get(f'https://localhost:{port}/api/v1/storm/call') as resp:
|
|
@@ -1760,7 +1780,7 @@ class CortexTest(s_t_utils.SynTest):
|
|
|
1760
1780
|
self.len(1, nodes)
|
|
1761
1781
|
self.eq(set(nodes[0].tags.keys()), {'foo', 'bar', 'bar.baz'})
|
|
1762
1782
|
|
|
1763
|
-
nodes = await wcore.nodes('$foo
|
|
1783
|
+
nodes = await wcore.nodes('$foo=(["foo", "bar.baz"]) [test:int=4 +#$foo]')
|
|
1764
1784
|
self.len(1, nodes)
|
|
1765
1785
|
self.eq(set(nodes[0].tags.keys()), {'foo', 'bar', 'bar.baz'})
|
|
1766
1786
|
|
|
@@ -3499,6 +3519,97 @@ class CortexBasicTest(s_t_utils.SynTest):
|
|
|
3499
3519
|
for node in nodes:
|
|
3500
3520
|
self.nn(node.getTag('hehe'))
|
|
3501
3521
|
|
|
3522
|
+
# Break and Continue cannot cross function boundaries and will instead raise a catchable StormRuntimeError
|
|
3523
|
+
keywords = ('break', 'continue')
|
|
3524
|
+
base_func_q = '''
|
|
3525
|
+
function inner(v) {
|
|
3526
|
+
if ( $v = 2 ) {
|
|
3527
|
+
KEYWORD
|
|
3528
|
+
}
|
|
3529
|
+
return ( $v )
|
|
3530
|
+
}
|
|
3531
|
+
$N = (5)
|
|
3532
|
+
|
|
3533
|
+
for $valu in $lib.range($N) {
|
|
3534
|
+
$lib.print(`{$inner($valu)}/{$N}`)
|
|
3535
|
+
}
|
|
3536
|
+
'''
|
|
3537
|
+
func_catch_q = '''
|
|
3538
|
+
function inner(v) {
|
|
3539
|
+
if ( $v = 2 ) {
|
|
3540
|
+
KEYWORD
|
|
3541
|
+
}
|
|
3542
|
+
return ( $v )
|
|
3543
|
+
}
|
|
3544
|
+
$N = (5)
|
|
3545
|
+
try {
|
|
3546
|
+
for $valu in $lib.range($N) {
|
|
3547
|
+
$lib.print(`{$inner($valu)}/{$N}`)
|
|
3548
|
+
}
|
|
3549
|
+
} catch StormRuntimeError as err {
|
|
3550
|
+
$lib.print(`caught: {$err.mesg}`)
|
|
3551
|
+
}
|
|
3552
|
+
'''
|
|
3553
|
+
for keyword in keywords:
|
|
3554
|
+
q = base_func_q.replace('KEYWORD', keyword)
|
|
3555
|
+
msgs = await core.stormlist(q)
|
|
3556
|
+
self.stormIsInPrint('1/5', msgs)
|
|
3557
|
+
self.stormNotInPrint('2/5', msgs)
|
|
3558
|
+
self.stormIsInErr(f'function inner - Loop control statement "{keyword}" used outside of a loop.',
|
|
3559
|
+
msgs)
|
|
3560
|
+
|
|
3561
|
+
q = func_catch_q.replace('KEYWORD', keyword)
|
|
3562
|
+
msgs = await core.stormlist(q)
|
|
3563
|
+
self.stormIsInPrint('1/5', msgs)
|
|
3564
|
+
self.stormNotInPrint('2/5', msgs)
|
|
3565
|
+
self.stormIsInPrint(f'function inner - Loop control statement "{keyword}" used outside of a loop.',
|
|
3566
|
+
msgs)
|
|
3567
|
+
|
|
3568
|
+
# The toplevel use of the keywords will convert them into StormRuntimeError in the message stream
|
|
3569
|
+
# but prevent them from being caught.
|
|
3570
|
+
base_top_q = '''
|
|
3571
|
+
$N = (5)
|
|
3572
|
+
for $j in $lib.range($N) {
|
|
3573
|
+
if ($j = 2) { break }
|
|
3574
|
+
$lib.print(`{$j}/{$N}`)
|
|
3575
|
+
}
|
|
3576
|
+
if ($j = 2) {
|
|
3577
|
+
KEYWORD
|
|
3578
|
+
}
|
|
3579
|
+
'''
|
|
3580
|
+
top_catch_q = '''
|
|
3581
|
+
$N = (5)
|
|
3582
|
+
for $j in $lib.range($N) {
|
|
3583
|
+
if ($j = 2) { break }
|
|
3584
|
+
$lib.print(`{$j}/{$N}`)
|
|
3585
|
+
}
|
|
3586
|
+
try {
|
|
3587
|
+
if ($j = 2) {
|
|
3588
|
+
KEYWORD
|
|
3589
|
+
}
|
|
3590
|
+
} catch StormRuntimeError as err {
|
|
3591
|
+
$lib.print(`caught: {$err.mesg}`)
|
|
3592
|
+
}
|
|
3593
|
+
'''
|
|
3594
|
+
for keyword in keywords:
|
|
3595
|
+
q = base_top_q.replace('KEYWORD', keyword)
|
|
3596
|
+
msgs = await core.stormlist(q)
|
|
3597
|
+
self.stormIsInPrint('1/5', msgs)
|
|
3598
|
+
self.stormNotInPrint('2/5', msgs)
|
|
3599
|
+
self.stormIsInErr(f'Loop control statement "{keyword}" used outside of a loop.',
|
|
3600
|
+
msgs)
|
|
3601
|
+
errname = [m[1][0] for m in msgs if m[0] == 'err'][0]
|
|
3602
|
+
self.eq(errname, 'StormRuntimeError')
|
|
3603
|
+
|
|
3604
|
+
q = top_catch_q.replace('KEYWORD', keyword)
|
|
3605
|
+
msgs = await core.stormlist(q)
|
|
3606
|
+
self.stormIsInPrint('1/5', msgs)
|
|
3607
|
+
self.stormNotInPrint('2/5', msgs)
|
|
3608
|
+
self.stormIsInErr(f'Loop control statement "{keyword}" used outside of a loop.',
|
|
3609
|
+
msgs)
|
|
3610
|
+
errname = [m[1][0] for m in msgs if m[0] == 'err'][0]
|
|
3611
|
+
self.eq(errname, 'StormRuntimeError')
|
|
3612
|
+
|
|
3502
3613
|
async def test_storm_varcall(self):
|
|
3503
3614
|
|
|
3504
3615
|
async with self.getTestCore() as core:
|
|
@@ -5119,6 +5230,14 @@ class CortexBasicTest(s_t_utils.SynTest):
|
|
|
5119
5230
|
self.eq(('inet:fqdn', 'nest.com'), nodes[0].ndef)
|
|
5120
5231
|
self.eq(('inet:fqdn', 'nest.com'), nodes[1].ndef)
|
|
5121
5232
|
|
|
5233
|
+
with self.raises(s_exc.StormRuntimeError) as err:
|
|
5234
|
+
await core.nodes('[ it:dev:int=1 ] for $n in $node.value() { }')
|
|
5235
|
+
self.isin("'int' object is not iterable: 1", err.exception.errinfo.get('mesg'))
|
|
5236
|
+
|
|
5237
|
+
with self.raises(s_exc.StormRuntimeError) as err:
|
|
5238
|
+
await core.nodes('for $n in { .created return($node) } { }')
|
|
5239
|
+
self.isin("'node' object is not iterable", err.exception.errinfo.get('mesg'))
|
|
5240
|
+
|
|
5122
5241
|
async def test_storm_whileloop(self):
|
|
5123
5242
|
|
|
5124
5243
|
async with self.getTestCore() as core:
|
|
@@ -5460,7 +5579,7 @@ class CortexBasicTest(s_t_utils.SynTest):
|
|
|
5460
5579
|
self.len(1, nodes)
|
|
5461
5580
|
|
|
5462
5581
|
async def test_storm_order(self):
|
|
5463
|
-
q = '''[test:str=foo :hehe=bar] $tvar
|
|
5582
|
+
q = '''[test:str=foo :hehe=bar] $tvar=() $tvar.append(1) $tvar.append(:hehe) $lib.print($lib.str.join('', $tvar)) '''
|
|
5464
5583
|
async with self.getTestCore() as core:
|
|
5465
5584
|
mesgs = await core.stormlist(q)
|
|
5466
5585
|
self.stormIsInPrint('1bar', mesgs)
|
|
@@ -5684,7 +5803,7 @@ class CortexBasicTest(s_t_utils.SynTest):
|
|
|
5684
5803
|
|
|
5685
5804
|
url02 = core02.getLocalUrl()
|
|
5686
5805
|
opts = {'vars': {'url01': url01, 'url02': url02}}
|
|
5687
|
-
strim = 'return($lib.cell.trimNexsLog(consumers
|
|
5806
|
+
strim = 'return($lib.cell.trimNexsLog(consumers=($url01, $url02), timeout=$lib.null))'
|
|
5688
5807
|
|
|
5689
5808
|
await core00.nodes('[ inet:ipv4=11.0.0.0/28 ]')
|
|
5690
5809
|
ips00 = await core00.count('inet:ipv4')
|
synapse/tests/test_exc.py
CHANGED
|
@@ -16,6 +16,7 @@ class ExcTest(s_t_utils.SynTest):
|
|
|
16
16
|
def test_basic(self):
|
|
17
17
|
e = s_exc.SynErr(mesg='words', foo='bar')
|
|
18
18
|
self.eq(e.get('foo'), 'bar')
|
|
19
|
+
self.eq(e.items(), {'mesg': 'words', 'foo': 'bar'})
|
|
19
20
|
self.eq("SynErr: foo='bar' mesg='words'", str(e))
|
|
20
21
|
e.set('hehe', 1234)
|
|
21
22
|
e.set('foo', 'words')
|
|
@@ -27,6 +28,9 @@ class ExcTest(s_t_utils.SynTest):
|
|
|
27
28
|
e.setdefault('defv', 2)
|
|
28
29
|
self.eq("SynErr: defv=1 foo='words' hehe=1234 mesg='words'", str(e))
|
|
29
30
|
|
|
31
|
+
e.update({'foo': 'newwords', 'bar': 'baz'})
|
|
32
|
+
self.eq("SynErr: bar='baz' defv=1 foo='newwords' hehe=1234 mesg='words'", str(e))
|
|
33
|
+
|
|
30
34
|
self.eq(e.errname, 'SynErr')
|
|
31
35
|
|
|
32
36
|
e2 = s_exc.BadTypeValu(mesg='haha')
|
synapse/tests/test_lib_agenda.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import time
|
|
1
2
|
import asyncio
|
|
2
3
|
import hashlib
|
|
3
4
|
import datetime
|
|
@@ -361,7 +362,9 @@ class AgendaTest(s_t_utils.SynTest):
|
|
|
361
362
|
|
|
362
363
|
appt = await agenda.get(guid)
|
|
363
364
|
self.eq(appt.isrunning, False)
|
|
364
|
-
self.
|
|
365
|
+
self.isin("raised exception StormRaise: errname='OmgWtfBbq'", appt.lastresult)
|
|
366
|
+
self.isin("highlight={'hash': '6736b8252d9413221a9b693b2b19cf53'", appt.lastresult)
|
|
367
|
+
self.isin("mesg='boom'", appt.lastresult)
|
|
365
368
|
|
|
366
369
|
# Test setting the global enable/disable flag
|
|
367
370
|
await agenda.delete(guid)
|
|
@@ -438,7 +441,7 @@ class AgendaTest(s_t_utils.SynTest):
|
|
|
438
441
|
await self.asyncraises(s_exc.DupIden, core.addCronJob(cdef))
|
|
439
442
|
await core.delCronJob(viewiden)
|
|
440
443
|
|
|
441
|
-
self.nn(core.getAuthGate(viewiden))
|
|
444
|
+
self.nn(await core.getAuthGate(viewiden))
|
|
442
445
|
|
|
443
446
|
async def test_agenda_persistence(self):
|
|
444
447
|
''' Test we can make/change/delete appointments and they are persisted to storage '''
|
|
@@ -824,6 +827,159 @@ class AgendaTest(s_t_utils.SynTest):
|
|
|
824
827
|
data = stream.read()
|
|
825
828
|
self.isin("_Appt.edits() Invalid attribute received: invalid = 'newp'", data)
|
|
826
829
|
|
|
830
|
+
async def test_agenda_promotions(self):
|
|
831
|
+
# Adjust this knob for the number of cron jobs you want to test. Below
|
|
832
|
+
# are some average run times from my dev box
|
|
833
|
+
# 100 -> ~15s
|
|
834
|
+
# 250 -> ~18s
|
|
835
|
+
# 500 -> ~22s
|
|
836
|
+
# 5000 -> ~88s
|
|
837
|
+
NUMJOBS = 100
|
|
838
|
+
|
|
839
|
+
async with self.getTestAha() as aha:
|
|
840
|
+
|
|
841
|
+
conf00 = {
|
|
842
|
+
'aha:provision': await aha.addAhaSvcProv('00.cortex')
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
async with self.getTestCore(conf=conf00) as core00:
|
|
846
|
+
self.false(core00.conf.get('mirror'))
|
|
847
|
+
|
|
848
|
+
msgs = await core00.stormlist('[it:dev:str=foo]')
|
|
849
|
+
self.stormHasNoWarnErr(msgs)
|
|
850
|
+
|
|
851
|
+
# Forward wind agenda to two minutes past the hour so we don't hit any weird timing windows
|
|
852
|
+
tick = core00.agenda._getNowTick()
|
|
853
|
+
now = time.gmtime(int(tick))
|
|
854
|
+
diff = (60 - now.tm_min) * 60
|
|
855
|
+
core00.agenda._addTickOff(diff + 120)
|
|
856
|
+
|
|
857
|
+
# Add NUMJOBS cron jobs that starts every hour
|
|
858
|
+
q = '''
|
|
859
|
+
for $ii in $lib.range($numjobs) {
|
|
860
|
+
cron.add --name `CRON{$ii}` --hour +1 { $lib.time.sleep(90) }
|
|
861
|
+
}
|
|
862
|
+
'''
|
|
863
|
+
opts = {'vars': {'numjobs': NUMJOBS}}
|
|
864
|
+
await core00.callStorm(q, opts=opts)
|
|
865
|
+
|
|
866
|
+
prov01 = {'mirror': '00.cortex'}
|
|
867
|
+
conf01 = {
|
|
868
|
+
'aha:provision': await aha.addAhaSvcProv('01.cortex', provinfo=prov01),
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
async with self.getTestCore(conf=conf01) as core01:
|
|
872
|
+
# Advance the ticks so the cronjob starts sooner
|
|
873
|
+
core00.agenda._addTickOff(3600)
|
|
874
|
+
|
|
875
|
+
# Sync agenda ticks
|
|
876
|
+
diff = core00.agenda._getNowTick() - core01.agenda._getNowTick()
|
|
877
|
+
core01.agenda._addTickOff(diff)
|
|
878
|
+
|
|
879
|
+
mesgs = []
|
|
880
|
+
async for mesg in core00.behold():
|
|
881
|
+
mesgs.append(mesg)
|
|
882
|
+
if len(mesgs) >= NUMJOBS:
|
|
883
|
+
break
|
|
884
|
+
|
|
885
|
+
for mesg in mesgs:
|
|
886
|
+
self.eq(mesg['event'], 'cron:start')
|
|
887
|
+
|
|
888
|
+
# Inspect crons and tasks
|
|
889
|
+
crons00 = await core00.callStorm('return($lib.cron.list())')
|
|
890
|
+
self.len(NUMJOBS, crons00)
|
|
891
|
+
# isrunning is synced via nexus so it should be true for both cortexes
|
|
892
|
+
for cron in crons00:
|
|
893
|
+
self.true(cron.get('isrunning'))
|
|
894
|
+
|
|
895
|
+
cronidens = [k['iden'] for k in crons00]
|
|
896
|
+
|
|
897
|
+
await core01.sync()
|
|
898
|
+
|
|
899
|
+
crons01 = await core01.callStorm('return($lib.cron.list())')
|
|
900
|
+
self.len(NUMJOBS, crons01)
|
|
901
|
+
# isrunning is synced via nexus so it should be true for both cortexes
|
|
902
|
+
for cron in crons01:
|
|
903
|
+
self.true(cron.get('isrunning'))
|
|
904
|
+
|
|
905
|
+
tasks00 = await core00.callStorm('return($lib.ps.list())')
|
|
906
|
+
# 101 tasks: one for the main task and NUMJOBS for the cronjob instances
|
|
907
|
+
self.len(NUMJOBS + 1, tasks00)
|
|
908
|
+
self.eq(tasks00[0]['info']['query'], '[it:dev:str=foo]')
|
|
909
|
+
for idx, task in enumerate(tasks00):
|
|
910
|
+
if idx == 0:
|
|
911
|
+
continue
|
|
912
|
+
|
|
913
|
+
self.isin(task['info']['iden'], cronidens)
|
|
914
|
+
self.eq(task['info']['query'], '$lib.time.sleep(90)')
|
|
915
|
+
|
|
916
|
+
# No tasks running on the follower
|
|
917
|
+
tasks01 = await core01.callStorm('return($lib.ps.list())')
|
|
918
|
+
self.len(0, tasks01)
|
|
919
|
+
|
|
920
|
+
with self.getLoggerStream('synapse.lib.agenda', mesg='name=CRON99') as stream:
|
|
921
|
+
# Promote and inspect cortex status
|
|
922
|
+
await core01.promote(graceful=True)
|
|
923
|
+
self.false(core00.isactive)
|
|
924
|
+
self.true(core01.isactive)
|
|
925
|
+
|
|
926
|
+
stream.seek(0)
|
|
927
|
+
data = stream.read()
|
|
928
|
+
for ii in range(NUMJOBS):
|
|
929
|
+
self.isin(f' name=CRON{ii} with result "cancelled" took ', data)
|
|
930
|
+
|
|
931
|
+
# Sync the (now) follower so the isrunning status gets updated to false on both cortexes
|
|
932
|
+
await core00.sync()
|
|
933
|
+
|
|
934
|
+
crons00 = await core00.callStorm('return($lib.cron.list())')
|
|
935
|
+
self.len(NUMJOBS, crons00)
|
|
936
|
+
for cron in crons00:
|
|
937
|
+
self.false(cron.get('isrunning'))
|
|
938
|
+
|
|
939
|
+
crons01 = await core01.callStorm('return($lib.cron.list())')
|
|
940
|
+
self.len(NUMJOBS, crons01)
|
|
941
|
+
for cron in crons01:
|
|
942
|
+
self.false(cron.get('isrunning'))
|
|
943
|
+
|
|
944
|
+
# Bump the ticks on core01 so the cron jobs start
|
|
945
|
+
core01.agenda._addTickOff(3600)
|
|
946
|
+
|
|
947
|
+
mesgs = []
|
|
948
|
+
async for mesg in core01.behold():
|
|
949
|
+
mesgs.append(mesg)
|
|
950
|
+
if len(mesgs) >= NUMJOBS:
|
|
951
|
+
break
|
|
952
|
+
|
|
953
|
+
for mesg in mesgs:
|
|
954
|
+
self.eq(mesg['event'], 'cron:start')
|
|
955
|
+
|
|
956
|
+
# Sync the follower to get the latest isrunning status
|
|
957
|
+
await core00.sync()
|
|
958
|
+
|
|
959
|
+
crons00 = await core00.callStorm('return($lib.cron.list())')
|
|
960
|
+
self.len(NUMJOBS, crons00)
|
|
961
|
+
# Cronjobs are running so true on both cortexes
|
|
962
|
+
for cron in crons00:
|
|
963
|
+
self.true(cron.get('isrunning'))
|
|
964
|
+
|
|
965
|
+
crons01 = await core01.callStorm('return($lib.cron.list())')
|
|
966
|
+
self.len(NUMJOBS, crons01)
|
|
967
|
+
# Cronjobs are running so true on both cortexes
|
|
968
|
+
for cron in crons01:
|
|
969
|
+
self.true(cron.get('isrunning'))
|
|
970
|
+
|
|
971
|
+
tasks00 = await core00.callStorm('return($lib.ps.list())')
|
|
972
|
+
# This task is the main task from before promotion
|
|
973
|
+
self.len(1, tasks00)
|
|
974
|
+
self.eq(tasks00[0]['info']['query'], '[it:dev:str=foo]')
|
|
975
|
+
|
|
976
|
+
tasks01 = await core01.callStorm('return($lib.ps.list())')
|
|
977
|
+
# The cronjob instances are the only tasks
|
|
978
|
+
self.len(NUMJOBS, tasks01)
|
|
979
|
+
for task in tasks01:
|
|
980
|
+
self.isin(task['info']['iden'], cronidens)
|
|
981
|
+
self.eq(task['info']['query'], '$lib.time.sleep(90)')
|
|
982
|
+
|
|
827
983
|
async def test_cron_kill(self):
|
|
828
984
|
async with self.getTestCore() as core:
|
|
829
985
|
|
|
@@ -941,3 +1097,127 @@ class AgendaTest(s_t_utils.SynTest):
|
|
|
941
1097
|
self.eq(cdef01.get('lastresult'), 'cancelled')
|
|
942
1098
|
self.gt(cdef00['laststarttime'], 0)
|
|
943
1099
|
self.eq(cdef00['laststarttime'], cdef01['laststarttime'])
|
|
1100
|
+
|
|
1101
|
+
async def test_agenda_graceful_promotion_with_running_cron(self):
|
|
1102
|
+
|
|
1103
|
+
async with self.getTestAha() as aha:
|
|
1104
|
+
|
|
1105
|
+
conf00 = {
|
|
1106
|
+
'aha:provision': await aha.addAhaSvcProv('00.cortex')
|
|
1107
|
+
}
|
|
1108
|
+
|
|
1109
|
+
async with self.getTestCore(conf=conf00) as core00:
|
|
1110
|
+
self.false(core00.conf.get('mirror'))
|
|
1111
|
+
|
|
1112
|
+
q = '''
|
|
1113
|
+
while((true)) {
|
|
1114
|
+
$lib.log.error('I AM A ERROR LOG MESSAGE')
|
|
1115
|
+
$lib.time.sleep(6)
|
|
1116
|
+
}
|
|
1117
|
+
'''
|
|
1118
|
+
msgs = await core00.stormlist('cron.at --now $q', opts={'vars': {'q': q}})
|
|
1119
|
+
self.stormHasNoWarnErr(msgs)
|
|
1120
|
+
|
|
1121
|
+
crons00 = await core00.callStorm('return($lib.cron.list())')
|
|
1122
|
+
self.len(1, crons00)
|
|
1123
|
+
|
|
1124
|
+
prov01 = {'mirror': '00.cortex'}
|
|
1125
|
+
conf01 = {
|
|
1126
|
+
'aha:provision': await aha.addAhaSvcProv('01.cortex', provinfo=prov01),
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1129
|
+
async with self.getTestCore(conf=conf01) as core01:
|
|
1130
|
+
|
|
1131
|
+
with self.getAsyncLoggerStream('synapse.storm.log', 'I AM A ERROR LOG MESSAGE') as stream:
|
|
1132
|
+
self.true(await stream.wait(timeout=6))
|
|
1133
|
+
|
|
1134
|
+
cron = await core00.callStorm('return($lib.cron.list())')
|
|
1135
|
+
self.len(1, cron)
|
|
1136
|
+
self.true(cron[0].get('isrunning'))
|
|
1137
|
+
|
|
1138
|
+
await core01.promote(graceful=True)
|
|
1139
|
+
|
|
1140
|
+
self.false(core00.isactive)
|
|
1141
|
+
self.true(core01.isactive)
|
|
1142
|
+
|
|
1143
|
+
await core00.sync()
|
|
1144
|
+
|
|
1145
|
+
cron00 = await core00.callStorm('return($lib.cron.list())')
|
|
1146
|
+
self.len(1, cron00)
|
|
1147
|
+
self.false(cron00[0].get('isrunning'))
|
|
1148
|
+
self.eq(cron00[0].get('lasterrs')[0], 'aborted')
|
|
1149
|
+
|
|
1150
|
+
cron01 = await core01.callStorm('return($lib.cron.list())')
|
|
1151
|
+
self.len(1, cron01)
|
|
1152
|
+
self.false(cron01[0].get('isrunning'))
|
|
1153
|
+
self.eq(cron01[0].get('lasterrs')[0], 'aborted')
|
|
1154
|
+
|
|
1155
|
+
async def test_agenda_force_promotion_with_running_cron(self):
|
|
1156
|
+
|
|
1157
|
+
async with self.getTestAha() as aha:
|
|
1158
|
+
|
|
1159
|
+
conf00 = {
|
|
1160
|
+
'aha:provision': await aha.addAhaSvcProv('00.cortex')
|
|
1161
|
+
}
|
|
1162
|
+
|
|
1163
|
+
async with self.getTestCore(conf=conf00) as core00:
|
|
1164
|
+
self.false(core00.conf.get('mirror'))
|
|
1165
|
+
|
|
1166
|
+
q = '''
|
|
1167
|
+
while((true)) {
|
|
1168
|
+
$lib.log.error('I AM A ERROR LOG MESSAGE')
|
|
1169
|
+
$lib.time.sleep(6)
|
|
1170
|
+
}
|
|
1171
|
+
'''
|
|
1172
|
+
msgs = await core00.stormlist('cron.at --now $q', opts={'vars': {'q': q}})
|
|
1173
|
+
self.stormHasNoWarnErr(msgs)
|
|
1174
|
+
|
|
1175
|
+
crons00 = await core00.callStorm('return($lib.cron.list())')
|
|
1176
|
+
self.len(1, crons00)
|
|
1177
|
+
|
|
1178
|
+
prov01 = {'mirror': '00.cortex'}
|
|
1179
|
+
conf01 = {
|
|
1180
|
+
'aha:provision': await aha.addAhaSvcProv('01.cortex', provinfo=prov01),
|
|
1181
|
+
}
|
|
1182
|
+
|
|
1183
|
+
async with self.getTestCore(conf=conf01) as core01:
|
|
1184
|
+
|
|
1185
|
+
cron = await core00.callStorm('return($lib.cron.list())')
|
|
1186
|
+
self.len(1, cron)
|
|
1187
|
+
self.true(cron[0].get('isrunning'))
|
|
1188
|
+
|
|
1189
|
+
await core01.promote(graceful=False)
|
|
1190
|
+
|
|
1191
|
+
self.true(core00.isactive)
|
|
1192
|
+
self.true(core01.isactive)
|
|
1193
|
+
|
|
1194
|
+
cron01 = await core01.callStorm('return($lib.cron.list())')
|
|
1195
|
+
self.len(1, cron01)
|
|
1196
|
+
self.false(cron01[0].get('isrunning'))
|
|
1197
|
+
self.eq(cron01[0].get('lasterrs')[0], 'aborted')
|
|
1198
|
+
|
|
1199
|
+
async def test_agenda_clear_running_none_nexttime(self):
|
|
1200
|
+
|
|
1201
|
+
async with self.getTestCore() as core:
|
|
1202
|
+
|
|
1203
|
+
cdef = {
|
|
1204
|
+
'creator': core.auth.rootuser.iden,
|
|
1205
|
+
'iden': s_common.guid(),
|
|
1206
|
+
'storm': '$lib.log.info("test")',
|
|
1207
|
+
'reqs': {},
|
|
1208
|
+
'incunit': 'minute',
|
|
1209
|
+
'incvals': 1
|
|
1210
|
+
}
|
|
1211
|
+
await core.addCronJob(cdef)
|
|
1212
|
+
|
|
1213
|
+
appt = core.agenda.appts[cdef['iden']]
|
|
1214
|
+
self.true(appt in core.agenda.apptheap)
|
|
1215
|
+
|
|
1216
|
+
appt.isrunning = True
|
|
1217
|
+
appt.nexttime = None
|
|
1218
|
+
|
|
1219
|
+
await core.agenda.clearRunningStatus()
|
|
1220
|
+
self.false(appt in core.agenda.apptheap)
|
|
1221
|
+
|
|
1222
|
+
crons = await core.callStorm('return($lib.cron.list())')
|
|
1223
|
+
self.len(1, crons)
|
synapse/tests/test_lib_aha.py
CHANGED
|
@@ -59,7 +59,7 @@ class AhaTest(s_test.SynTest):
|
|
|
59
59
|
self.len(ahacount, await proxy0.getAhaUrls())
|
|
60
60
|
self.len(ahacount, await proxy0.getAhaServers())
|
|
61
61
|
|
|
62
|
-
purl = await proxy0.addAhaClone(zoinks)
|
|
62
|
+
purl = await proxy0.addAhaClone(zoinks, port=0)
|
|
63
63
|
|
|
64
64
|
conf1 = {'clone': purl}
|
|
65
65
|
async with self.getTestAha(conf=conf1, dirn=dir1) as aha1:
|
|
@@ -574,7 +574,7 @@ class AhaTest(s_test.SynTest):
|
|
|
574
574
|
}
|
|
575
575
|
s_common.yamlsave(axonconf, axonpath, 'cell.yaml')
|
|
576
576
|
|
|
577
|
-
argv = (axonpath, '--auth-passwd', 'rootbeer')
|
|
577
|
+
argv = (axonpath, '--auth-passwd', 'rootbeer', '--https', '0')
|
|
578
578
|
async with await s_axon.Axon.initFromArgv(argv) as axon:
|
|
579
579
|
|
|
580
580
|
# opts were copied through successfully
|
|
@@ -1161,7 +1161,8 @@ class AhaTest(s_test.SynTest):
|
|
|
1161
1161
|
aconf = {
|
|
1162
1162
|
'aha:name': 'aha',
|
|
1163
1163
|
'aha:network': networkname,
|
|
1164
|
-
'
|
|
1164
|
+
'dmon:listen': f'ssl://aha.{networkname}:0',
|
|
1165
|
+
'provision:listen': f'ssl://aha.{networkname}:0',
|
|
1165
1166
|
}
|
|
1166
1167
|
name = aconf.get('aha:name')
|
|
1167
1168
|
netw = aconf.get('aha:network')
|
|
@@ -1300,11 +1301,17 @@ class AhaTest(s_test.SynTest):
|
|
|
1300
1301
|
conf = {
|
|
1301
1302
|
'aha:network': 'synapse',
|
|
1302
1303
|
'dns:name': 'here.loop.vertex.link',
|
|
1304
|
+
'dmon:listen': 'ssl://0.0.0.0:0?hostname=here.loop.vertex.link&ca=synapse',
|
|
1303
1305
|
}
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
+
|
|
1307
|
+
orig = s_aha.AhaCell._getProvListen
|
|
1308
|
+
def _getProvListen(_self):
|
|
1309
|
+
ret = orig(_self)
|
|
1310
|
+
self.eq(ret, 'ssl://0.0.0.0:27272?hostname=here.loop.vertex.link')
|
|
1311
|
+
return 'ssl://0.0.0.0:0?hostname=here.loop.vertex.link'
|
|
1312
|
+
|
|
1313
|
+
with mock.patch('synapse.lib.aha.AhaCell._getProvListen', _getProvListen):
|
|
1306
1314
|
async with self.getTestCell(s_aha.AhaCell, conf=conf) as aha:
|
|
1307
|
-
self.true(await stream.wait(timeout=6))
|
|
1308
1315
|
# And the URL works with our listener :)
|
|
1309
1316
|
provurl = await aha.addAhaUserEnroll('bob.grey')
|
|
1310
1317
|
async with await s_telepath.openurl(provurl) as prox:
|