synapse 2.184.0__py311-none-any.whl → 2.185.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/cortex.py +1 -1
- synapse/datamodel.py +41 -6
- synapse/lib/ast.py +82 -21
- synapse/lib/auth.py +13 -0
- synapse/lib/cell.py +13 -0
- synapse/lib/modules.py +1 -0
- synapse/lib/parser.py +1 -0
- synapse/lib/snap.py +1 -0
- synapse/lib/storm.lark +12 -6
- synapse/lib/storm.py +45 -9
- synapse/lib/storm_format.py +1 -0
- synapse/lib/stormlib/stix.py +14 -5
- synapse/lib/stormtypes.py +64 -36
- synapse/lib/version.py +2 -2
- synapse/models/doc.py +93 -0
- synapse/models/infotech.py +2 -1
- synapse/models/media.py +0 -1
- synapse/models/orgs.py +26 -3
- synapse/models/proj.py +56 -36
- synapse/models/syn.py +64 -6
- synapse/tests/test_cortex.py +39 -1
- synapse/tests/test_lib_cell.py +44 -1
- synapse/tests/test_lib_grammar.py +2 -0
- synapse/tests/test_lib_storm.py +54 -1
- synapse/tests/test_lib_stormlib_stix.py +3 -2
- synapse/tests/test_model_doc.py +51 -0
- synapse/tests/test_model_orgs.py +41 -0
- synapse/tests/test_model_syn.py +43 -0
- synapse/tests/test_tools_promote.py +67 -0
- synapse/tools/promote.py +14 -1
- {synapse-2.184.0.dist-info → synapse-2.185.0.dist-info}/METADATA +5 -10
- {synapse-2.184.0.dist-info → synapse-2.185.0.dist-info}/RECORD +35 -32
- {synapse-2.184.0.dist-info → synapse-2.185.0.dist-info}/LICENSE +0 -0
- {synapse-2.184.0.dist-info → synapse-2.185.0.dist-info}/WHEEL +0 -0
- {synapse-2.184.0.dist-info → synapse-2.185.0.dist-info}/top_level.txt +0 -0
synapse/tests/test_cortex.py
CHANGED
|
@@ -108,6 +108,7 @@ class CortexTest(s_t_utils.SynTest):
|
|
|
108
108
|
await core00.handoff(core00.getLocalUrl())
|
|
109
109
|
|
|
110
110
|
self.false((await core00.getCellInfo())['cell']['uplink'])
|
|
111
|
+
self.none((await core00.getCellInfo())['cell']['mirror'])
|
|
111
112
|
|
|
112
113
|
# provision with the new hostname and mirror config
|
|
113
114
|
provinfo = {'mirror': '00.cortex'}
|
|
@@ -130,10 +131,13 @@ class CortexTest(s_t_utils.SynTest):
|
|
|
130
131
|
self.true(await s_coro.event_wait(core01.nexsroot.miruplink, timeout=2))
|
|
131
132
|
self.false((await core00.getCellInfo())['cell']['uplink'])
|
|
132
133
|
self.true((await core01.getCellInfo())['cell']['uplink'])
|
|
134
|
+
self.none((await core00.getCellInfo())['cell']['mirror'])
|
|
135
|
+
self.eq((await core01.getCellInfo())['cell']['mirror'], 'aha://root@00.cortex...')
|
|
133
136
|
|
|
134
137
|
outp = s_output.OutPutStr()
|
|
135
138
|
argv = ('--svcurl', core01.getLocalUrl())
|
|
136
|
-
await s_tools_promote.main(argv, outp=outp) # this is a graceful promotion
|
|
139
|
+
ret = await s_tools_promote.main(argv, outp=outp) # this is a graceful promotion
|
|
140
|
+
self.eq(ret, 0)
|
|
137
141
|
|
|
138
142
|
self.true(core01.isactive)
|
|
139
143
|
self.false(core00.isactive)
|
|
@@ -141,6 +145,10 @@ class CortexTest(s_t_utils.SynTest):
|
|
|
141
145
|
self.true(await s_coro.event_wait(core00.nexsroot.miruplink, timeout=2))
|
|
142
146
|
self.true((await core00.getCellInfo())['cell']['uplink'])
|
|
143
147
|
self.false((await core01.getCellInfo())['cell']['uplink'])
|
|
148
|
+
# Note: The following mirror may change when SYN-7659 is addressed and greater
|
|
149
|
+
# control over the topology update is available during the promotion process.
|
|
150
|
+
self.eq((await core00.getCellInfo())['cell']['mirror'], 'aha://01.cortex.synapse')
|
|
151
|
+
self.none((await core01.getCellInfo())['cell']['mirror'])
|
|
144
152
|
|
|
145
153
|
mods00 = s_common.yamlload(core00.dirn, 'cell.mods.yaml')
|
|
146
154
|
mods01 = s_common.yamlload(core01.dirn, 'cell.mods.yaml')
|
|
@@ -2942,6 +2950,36 @@ class CortexTest(s_t_utils.SynTest):
|
|
|
2942
2950
|
with self.raises(s_exc.NoSuchProp):
|
|
2943
2951
|
await core.nodes('inet:ipv4 +:asn::_pivo::notaprop')
|
|
2944
2952
|
|
|
2953
|
+
await core.nodes('[ou:org=* :hq={[ps:contact=* :email=a@v.lk]}]')
|
|
2954
|
+
await core.nodes('[ou:org=* :hq={[ps:contact=* :email=b@v.lk]}]')
|
|
2955
|
+
await core.nodes('[ou:org=* :hq={[ps:contact=* :email=c@v.lk]}]')
|
|
2956
|
+
await core.nodes('[ou:org=* :hq={[ps:contact=* :emails=(a@v.lk, b@v.lk)]}]')
|
|
2957
|
+
await core.nodes('[ou:org=* :hq={[ps:contact=* :emails=(c@v.lk, d@v.lk)]}]')
|
|
2958
|
+
await core.nodes('[ou:org=* :hq={[ps:contact=* :emails=(a@v.lk, d@v.lk)]}]')
|
|
2959
|
+
|
|
2960
|
+
nodes = await core.nodes('ou:org:hq::email::user=a')
|
|
2961
|
+
self.len(1, nodes)
|
|
2962
|
+
for node in nodes:
|
|
2963
|
+
self.eq('ou:org', node.ndef[0])
|
|
2964
|
+
|
|
2965
|
+
nodes = await core.nodes('ou:org:hq::email::user*in=(a, b)')
|
|
2966
|
+
self.len(2, nodes)
|
|
2967
|
+
for node in nodes:
|
|
2968
|
+
self.eq('ou:org', node.ndef[0])
|
|
2969
|
+
|
|
2970
|
+
nodes = await core.nodes('ou:org:hq::emails*[=a@v.lk]')
|
|
2971
|
+
self.len(2, nodes)
|
|
2972
|
+
for node in nodes:
|
|
2973
|
+
self.eq('ou:org', node.ndef[0])
|
|
2974
|
+
|
|
2975
|
+
nodes = await core.nodes('ou:org:hq::emails*[in=(a@v.lk, c@v.lk)]')
|
|
2976
|
+
self.len(3, nodes)
|
|
2977
|
+
for node in nodes:
|
|
2978
|
+
self.eq('ou:org', node.ndef[0])
|
|
2979
|
+
|
|
2980
|
+
with self.raises(s_exc.NoSuchProp):
|
|
2981
|
+
nodes = await core.nodes('ou:org:hq::email::newp=a')
|
|
2982
|
+
|
|
2945
2983
|
class CortexBasicTest(s_t_utils.SynTest):
|
|
2946
2984
|
'''
|
|
2947
2985
|
The tests that are unlikely to break with different types of layers installed
|
synapse/tests/test_lib_cell.py
CHANGED
|
@@ -8,7 +8,6 @@ import signal
|
|
|
8
8
|
import socket
|
|
9
9
|
import asyncio
|
|
10
10
|
import tarfile
|
|
11
|
-
import warnings
|
|
12
11
|
import collections
|
|
13
12
|
import multiprocessing
|
|
14
13
|
|
|
@@ -751,6 +750,7 @@ class CellTest(s_t_utils.SynTest):
|
|
|
751
750
|
self.ge(cnfo.get('nexsindx'), 0)
|
|
752
751
|
self.true(cnfo.get('active'))
|
|
753
752
|
self.false(cnfo.get('uplink'))
|
|
753
|
+
self.none(cnfo.get('mirror', True))
|
|
754
754
|
# A Cortex populated cellvers
|
|
755
755
|
self.isin('cortex:defaults', cnfo.get('cellvers', {}))
|
|
756
756
|
|
|
@@ -3151,3 +3151,46 @@ class CellTest(s_t_utils.SynTest):
|
|
|
3151
3151
|
self.isin(cell.long_lived_slab.fini, cell._fini_funcs)
|
|
3152
3152
|
slabs = [s for s in cell.tofini if isinstance(s, s_lmdbslab.Slab) and s.lenv.path() == cell.short_slab_path]
|
|
3153
3153
|
self.len(0, slabs)
|
|
3154
|
+
|
|
3155
|
+
async def test_lib_cell_promote_schism_prevent(self):
|
|
3156
|
+
|
|
3157
|
+
async with self.getTestAha() as aha:
|
|
3158
|
+
async with await s_base.Base.anit() as base:
|
|
3159
|
+
with self.getTestDir() as dirn:
|
|
3160
|
+
dirn00 = s_common.genpath(dirn, '00.cell')
|
|
3161
|
+
dirn01 = s_common.genpath(dirn, '01.cell')
|
|
3162
|
+
dirn02 = s_common.genpath(dirn, '02.cell')
|
|
3163
|
+
|
|
3164
|
+
cell00 = await base.enter_context(self.addSvcToAha(aha, '00.cell', s_cell.Cell, dirn=dirn00))
|
|
3165
|
+
cell01 = await base.enter_context(self.addSvcToAha(aha, '01.cell', s_cell.Cell, dirn=dirn01,
|
|
3166
|
+
provinfo={'mirror': 'cell'}))
|
|
3167
|
+
cell02 = await base.enter_context(self.addSvcToAha(aha, '02.cell', s_cell.Cell, dirn=dirn02,
|
|
3168
|
+
provinfo={'mirror': 'cell'}))
|
|
3169
|
+
|
|
3170
|
+
self.true(cell00.isactive)
|
|
3171
|
+
self.false(cell01.isactive)
|
|
3172
|
+
self.false(cell02.isactive)
|
|
3173
|
+
await cell02.sync()
|
|
3174
|
+
|
|
3175
|
+
with self.raises(s_exc.BadState) as cm:
|
|
3176
|
+
await cell01.handoff('some://url')
|
|
3177
|
+
self.isin('01.cell is not the current leader', cm.exception.get('mesg'))
|
|
3178
|
+
|
|
3179
|
+
# Note: The following behavior may change when SYN-7659 is addressed and greater
|
|
3180
|
+
# control over the topology update is available during the promotion process.
|
|
3181
|
+
# Promote 02.cell -> Promote 01.cell -> Promote 00.cell -> BadState exception
|
|
3182
|
+
await cell02.promote(graceful=True)
|
|
3183
|
+
self.false(cell00.isactive)
|
|
3184
|
+
self.false(cell01.isactive)
|
|
3185
|
+
self.true(cell02.isactive)
|
|
3186
|
+
await cell02.sync()
|
|
3187
|
+
|
|
3188
|
+
await cell01.promote(graceful=True)
|
|
3189
|
+
self.false(cell00.isactive)
|
|
3190
|
+
self.true(cell01.isactive)
|
|
3191
|
+
self.false(cell02.isactive)
|
|
3192
|
+
await cell02.sync()
|
|
3193
|
+
|
|
3194
|
+
with self.raises(s_exc.BadState) as cm:
|
|
3195
|
+
await cell00.promote(graceful=True)
|
|
3196
|
+
self.isin('02.cell is not the current leader', cm.exception.get('mesg'))
|
|
@@ -727,6 +727,7 @@ Queries = [
|
|
|
727
727
|
'$p="names" ps:contact:name=foo [ :$p?-=bar ]',
|
|
728
728
|
'$pvar=stuff test:arrayprop +:$pvar*[=neato]',
|
|
729
729
|
'$pvar=ints test:arrayprop +:$pvar*[=$othervar]',
|
|
730
|
+
'$foo = ({"foo": ${ inet:fqdn }})',
|
|
730
731
|
]
|
|
731
732
|
|
|
732
733
|
# Generated with print_parse_list below
|
|
@@ -1356,6 +1357,7 @@ _ParseResults = [
|
|
|
1356
1357
|
'Query: [SetVarOper: [Const: p, Const: names], LiftPropBy: [Const: ps:contact:name, Const: =, Const: foo], EditPropSet: [RelProp: [VarValue: [Const: p]], Const: ?-=, Const: bar]]',
|
|
1357
1358
|
'Query: [SetVarOper: [Const: pvar, Const: stuff], LiftProp: [Const: test:arrayprop], FiltOper: [Const: +, ArrayCond: [RelProp: [VarValue: [Const: pvar]], Const: =, Const: neato]]]',
|
|
1358
1359
|
'Query: [SetVarOper: [Const: pvar, Const: ints], LiftProp: [Const: test:arrayprop], FiltOper: [Const: +, ArrayCond: [RelProp: [VarValue: [Const: pvar]], Const: =, VarValue: [Const: othervar]]]]',
|
|
1360
|
+
'Query: [SetVarOper: [Const: foo, DollarExpr: [ExprDict: [Const: foo, EmbedQuery: inet:fqdn]]]]',
|
|
1359
1361
|
]
|
|
1360
1362
|
|
|
1361
1363
|
class GrammarTest(s_t_utils.SynTest):
|
synapse/tests/test_lib_storm.py
CHANGED
|
@@ -147,6 +147,20 @@ class StormTest(s_t_utils.SynTest):
|
|
|
147
147
|
retn = await core.callStorm('return(({"foo": "bar", "baz": 10 , }))')
|
|
148
148
|
self.eq(retn, {'foo': 'bar', 'baz': 10})
|
|
149
149
|
|
|
150
|
+
q = '''
|
|
151
|
+
$foo = ({"bar": ${[inet:fqdn=foo.com]}})
|
|
152
|
+
for $n in $foo.bar { return($n.repr()) }
|
|
153
|
+
'''
|
|
154
|
+
retn = await core.callStorm(q)
|
|
155
|
+
self.eq(retn, 'foo.com')
|
|
156
|
+
|
|
157
|
+
q = '''
|
|
158
|
+
$foo = ([${[inet:fqdn=foo.com]}])
|
|
159
|
+
for $n in $foo.0 { return($n.repr()) }
|
|
160
|
+
'''
|
|
161
|
+
retn = await core.callStorm(q)
|
|
162
|
+
self.eq(retn, 'foo.com')
|
|
163
|
+
|
|
150
164
|
with self.raises(s_exc.BadSyntax):
|
|
151
165
|
await core.callStorm('return((["foo" "foo"]))')
|
|
152
166
|
|
|
@@ -612,6 +626,12 @@ class StormTest(s_t_utils.SynTest):
|
|
|
612
626
|
''')
|
|
613
627
|
self.eq((0, 'haha'), await core.callStorm('return($lib.queue.get(bar).get())'))
|
|
614
628
|
|
|
629
|
+
await core.nodes('$foo = (foo,) background ${ $foo.append(bar) $lib.queue.get(bar).put($foo) }')
|
|
630
|
+
self.eq((1, ['foo', 'bar']), await core.callStorm('return($lib.queue.get(bar).get(1))'))
|
|
631
|
+
|
|
632
|
+
await core.nodes('$foo = ([["foo"]]) background ${ $foo.0.append(bar) $lib.queue.get(bar).put($foo) }')
|
|
633
|
+
self.eq((2, [['foo', 'bar']]), await core.callStorm('return($lib.queue.get(bar).get(2))'))
|
|
634
|
+
|
|
615
635
|
with self.raises(s_exc.StormRuntimeError):
|
|
616
636
|
await core.nodes('[ ou:org=*] $text = $node.repr() | background $text')
|
|
617
637
|
|
|
@@ -3586,7 +3606,7 @@ class StormTest(s_t_utils.SynTest):
|
|
|
3586
3606
|
'quickly became his weapon of choice.'])
|
|
3587
3607
|
pars.help()
|
|
3588
3608
|
helptext = '\n'.join(pars.mesgs)
|
|
3589
|
-
self.isin('default
|
|
3609
|
+
self.isin('default:\n [', helptext)
|
|
3590
3610
|
|
|
3591
3611
|
pars = s_storm.Parser()
|
|
3592
3612
|
pars.add_argument('--ques', nargs='?')
|
|
@@ -3771,6 +3791,27 @@ class StormTest(s_t_utils.SynTest):
|
|
|
3771
3791
|
opts = pars.parse_args(['faz', '--cat', 'cam', 'cool'])
|
|
3772
3792
|
self.nn(opts)
|
|
3773
3793
|
|
|
3794
|
+
pars = s_storm.Parser()
|
|
3795
|
+
pars.add_argument('--baz', nargs=3, help='''
|
|
3796
|
+
This is the top line, nothing special.
|
|
3797
|
+
This is my second line with sublines that should have some leading spaces:
|
|
3798
|
+
subline 1: this is a line which has three spaces.
|
|
3799
|
+
subline 2: this is another line with five leading spaces.
|
|
3800
|
+
subline 3: yet another line with only two leading spaces.
|
|
3801
|
+
subline 4: this line has one space and is long which should wrap around because it exceeds the default display width.
|
|
3802
|
+
This is the final line with no leading spaces.''')
|
|
3803
|
+
pars.add_argument('--taz', type='bool', default=True, help='Taz option')
|
|
3804
|
+
pars.help()
|
|
3805
|
+
self.eq(' --baz <baz> : This is the top line, nothing special.', pars.mesgs[5])
|
|
3806
|
+
self.eq(' This is my second line with sublines that should have some leading spaces:', pars.mesgs[6])
|
|
3807
|
+
self.eq(' subline 1: this is a line which has three spaces.', pars.mesgs[7])
|
|
3808
|
+
self.eq(' subline 2: this is another line with five leading spaces.', pars.mesgs[8])
|
|
3809
|
+
self.eq(' subline 3: yet another line with only two leading spaces.', pars.mesgs[9])
|
|
3810
|
+
self.eq(' subline 4: this line has one space and is long which should wrap around because it', pars.mesgs[10])
|
|
3811
|
+
self.eq(' exceeds the default display width.', pars.mesgs[11])
|
|
3812
|
+
self.eq(' This is the final line with no leading spaces.', pars.mesgs[12])
|
|
3813
|
+
self.eq(' --taz <taz> : Taz option (default: True)', pars.mesgs[13])
|
|
3814
|
+
|
|
3774
3815
|
async def test_storm_cmd_help(self):
|
|
3775
3816
|
|
|
3776
3817
|
async with self.getTestCore() as core:
|
|
@@ -5085,3 +5126,15 @@ class StormTest(s_t_utils.SynTest):
|
|
|
5085
5126
|
''')
|
|
5086
5127
|
|
|
5087
5128
|
self.none(await core.callStorm('return($lib.queue.gen(haha).get().1)'))
|
|
5129
|
+
|
|
5130
|
+
await core.nodes('''
|
|
5131
|
+
$foo = (foo,)
|
|
5132
|
+
$query = ${
|
|
5133
|
+
$foo.append(bar)
|
|
5134
|
+
$lib.queue.gen(hoho).put($foo)
|
|
5135
|
+
$lib.dmon.del($auto.iden)
|
|
5136
|
+
}
|
|
5137
|
+
$lib.dmon.add($query)
|
|
5138
|
+
''')
|
|
5139
|
+
|
|
5140
|
+
self.eq(['foo', 'bar'], await core.callStorm('return($lib.queue.gen(hoho).get().1)'))
|
|
@@ -55,6 +55,7 @@ class StormLibStixTest(s_test.SynTest):
|
|
|
55
55
|
async def test_stormlib_libstix(self, conf=None):
|
|
56
56
|
|
|
57
57
|
async with self.getTestCore(conf=conf) as core:
|
|
58
|
+
visi = await core.auth.addUser('visi')
|
|
58
59
|
opts = {'vars': {
|
|
59
60
|
'ind': '6ba7d8500964902bf2e03126ed0f6cb1',
|
|
60
61
|
'news': '840b9b003a765020705ea8d203a7659c',
|
|
@@ -228,9 +229,9 @@ class StormLibStixTest(s_test.SynTest):
|
|
|
228
229
|
opts = {'vars': {'config': config}}
|
|
229
230
|
await core.callStorm('$lib.stix.export.bundle(config=$config)', opts=opts)
|
|
230
231
|
|
|
231
|
-
with self.raises(s_exc.
|
|
232
|
+
with self.raises(s_exc.AuthDeny):
|
|
232
233
|
config = {'maxsize': 10000000}
|
|
233
|
-
opts = {'vars': {'config': config}}
|
|
234
|
+
opts = {'user': visi.iden, 'vars': {'config': config}}
|
|
234
235
|
await core.callStorm('$lib.stix.export.bundle(config=$config)', opts=opts)
|
|
235
236
|
|
|
236
237
|
with self.raises(s_exc.NoSuchForm):
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import synapse.tests.utils as s_tests
|
|
2
|
+
|
|
3
|
+
class DocModelTest(s_tests.SynTest):
|
|
4
|
+
|
|
5
|
+
async def test_model_doc(self):
|
|
6
|
+
|
|
7
|
+
async with self.getTestCore() as core:
|
|
8
|
+
|
|
9
|
+
nodes = await core.nodes('''
|
|
10
|
+
[ doc:policy=*
|
|
11
|
+
:id=V-41
|
|
12
|
+
:name="Rule 41"
|
|
13
|
+
:text="If you can AAAAAAAA..."
|
|
14
|
+
:file=*
|
|
15
|
+
:created=20241018
|
|
16
|
+
:updated=20241018
|
|
17
|
+
:author={[ ps:contact=* :name=visi ]}
|
|
18
|
+
:contributors={[ ps:contact=* :name=shuka ]}
|
|
19
|
+
:version=1.2.3
|
|
20
|
+
:supersedes={[ doc:policy=* doc:policy=* ]}
|
|
21
|
+
]
|
|
22
|
+
''')
|
|
23
|
+
self.len(1, nodes)
|
|
24
|
+
self.eq('V-41', nodes[0].get('id'))
|
|
25
|
+
self.eq('rule 41', nodes[0].get('name'))
|
|
26
|
+
self.eq('If you can AAAAAAAA...', nodes[0].get('text'))
|
|
27
|
+
self.eq(1729209600000, nodes[0].get('created'))
|
|
28
|
+
self.eq(1729209600000, nodes[0].get('updated'))
|
|
29
|
+
self.eq(1099513724931, nodes[0].get('version'))
|
|
30
|
+
|
|
31
|
+
self.nn(nodes[0].get('file'))
|
|
32
|
+
self.nn(nodes[0].get('author'))
|
|
33
|
+
|
|
34
|
+
self.len(2, nodes[0].get('supersedes'))
|
|
35
|
+
self.len(1, nodes[0].get('contributors'))
|
|
36
|
+
|
|
37
|
+
self.len(1, await core.nodes('doc:policy:id=V-41 :file -> file:bytes'))
|
|
38
|
+
self.len(2, await core.nodes('doc:policy:id=V-41 :supersedes -> doc:policy'))
|
|
39
|
+
self.len(1, await core.nodes('doc:policy:id=V-41 :author -> ps:contact +:name=visi'))
|
|
40
|
+
self.len(1, await core.nodes('doc:policy:id=V-41 :contributors -> ps:contact +:name=shuka'))
|
|
41
|
+
|
|
42
|
+
nodes = await core.nodes('''
|
|
43
|
+
[ doc:standard=*
|
|
44
|
+
:id=V-99
|
|
45
|
+
:policy={ doc:policy:id=V-41 }
|
|
46
|
+
]
|
|
47
|
+
''')
|
|
48
|
+
self.len(1, nodes)
|
|
49
|
+
self.eq('V-99', nodes[0].get('id'))
|
|
50
|
+
self.nn(nodes[0].get('policy'))
|
|
51
|
+
self.len(1, await core.nodes('doc:standard -> doc:policy'))
|
synapse/tests/test_model_orgs.py
CHANGED
|
@@ -701,6 +701,47 @@ class OuModelTest(s_t_utils.SynTest):
|
|
|
701
701
|
self.len(1, await core.nodes('ou:asset :owner -> ps:contact +:name=foo '))
|
|
702
702
|
self.len(1, await core.nodes('ou:asset :operator -> ps:contact +:name=bar '))
|
|
703
703
|
|
|
704
|
+
visi = await core.auth.addUser('visi')
|
|
705
|
+
|
|
706
|
+
nodes = await core.nodes('''
|
|
707
|
+
[ ou:enacted=*
|
|
708
|
+
:id=V-99
|
|
709
|
+
:project={[ proj:project=* ]}
|
|
710
|
+
:status=10
|
|
711
|
+
:priority=highest
|
|
712
|
+
:created=20241018
|
|
713
|
+
:updated=20241018
|
|
714
|
+
:due=20241018
|
|
715
|
+
:completed=20241018
|
|
716
|
+
:creator=root
|
|
717
|
+
:assignee=visi
|
|
718
|
+
:scope=(ou:team, *)
|
|
719
|
+
:ext:creator={[ ps:contact=* :name=root ]}
|
|
720
|
+
:ext:assignee={[ ps:contact=* :name=visi ]}
|
|
721
|
+
]
|
|
722
|
+
''')
|
|
723
|
+
self.len(1, nodes)
|
|
724
|
+
self.eq('V-99', nodes[0].get('id'))
|
|
725
|
+
self.eq(10, nodes[0].get('status'))
|
|
726
|
+
self.eq(50, nodes[0].get('priority'))
|
|
727
|
+
|
|
728
|
+
self.eq(1729209600000, nodes[0].get('due'))
|
|
729
|
+
self.eq(1729209600000, nodes[0].get('created'))
|
|
730
|
+
self.eq(1729209600000, nodes[0].get('updated'))
|
|
731
|
+
self.eq(1729209600000, nodes[0].get('completed'))
|
|
732
|
+
|
|
733
|
+
self.eq(visi.iden, nodes[0].get('assignee'))
|
|
734
|
+
self.eq(core.auth.rootuser.iden, nodes[0].get('creator'))
|
|
735
|
+
|
|
736
|
+
self.nn(nodes[0].get('scope'))
|
|
737
|
+
self.nn(nodes[0].get('ext:creator'))
|
|
738
|
+
self.nn(nodes[0].get('ext:assignee'))
|
|
739
|
+
|
|
740
|
+
self.len(1, await core.nodes('ou:enacted -> proj:project'))
|
|
741
|
+
self.len(1, await core.nodes('ou:enacted :scope -> ou:team'))
|
|
742
|
+
self.len(1, await core.nodes('ou:enacted :ext:creator -> ps:contact +:name=root'))
|
|
743
|
+
self.len(1, await core.nodes('ou:enacted :ext:assignee -> ps:contact +:name=visi'))
|
|
744
|
+
|
|
704
745
|
async def test_ou_code_prefixes(self):
|
|
705
746
|
guid0 = s_common.guid()
|
|
706
747
|
guid1 = s_common.guid()
|
synapse/tests/test_model_syn.py
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import synapse.exc as s_exc
|
|
2
|
+
import synapse.common as s_common
|
|
2
3
|
import synapse.cortex as s_cortex
|
|
4
|
+
import synapse.datamodel as s_datamodel
|
|
3
5
|
|
|
4
6
|
import synapse.lib.stormsvc as s_stormsvc
|
|
5
7
|
|
|
@@ -46,6 +48,47 @@ class TestService(s_stormsvc.StormSvc):
|
|
|
46
48
|
|
|
47
49
|
class SynModelTest(s_t_utils.SynTest):
|
|
48
50
|
|
|
51
|
+
async def test_syn_userrole(self):
|
|
52
|
+
|
|
53
|
+
async with self.getTestCore() as core:
|
|
54
|
+
|
|
55
|
+
(ok, iden) = await core.callStorm('return($lib.trycast(syn:user, root))')
|
|
56
|
+
self.true(ok)
|
|
57
|
+
self.eq(iden, core.auth.rootuser.iden)
|
|
58
|
+
|
|
59
|
+
# coverage for iden taking precedence
|
|
60
|
+
(ok, iden) = await core.callStorm(f'return($lib.trycast(syn:user, {iden}))')
|
|
61
|
+
self.true(ok)
|
|
62
|
+
self.eq(iden, core.auth.rootuser.iden)
|
|
63
|
+
|
|
64
|
+
self.eq('root', await core.callStorm(f'return($lib.repr(syn:user, {iden}))'))
|
|
65
|
+
|
|
66
|
+
(ok, iden) = await core.callStorm('return($lib.trycast(syn:role, all))')
|
|
67
|
+
self.true(ok)
|
|
68
|
+
self.eq(iden, core.auth.allrole.iden)
|
|
69
|
+
|
|
70
|
+
# coverage for iden taking precedence
|
|
71
|
+
(ok, iden) = await core.callStorm(f'return($lib.trycast(syn:role, {iden}))')
|
|
72
|
+
self.true(ok)
|
|
73
|
+
self.eq(iden, core.auth.allrole.iden)
|
|
74
|
+
|
|
75
|
+
self.eq('all', await core.callStorm(f'return($lib.repr(syn:role, {iden}))'))
|
|
76
|
+
|
|
77
|
+
# coverage for DataModel without a cortex reference
|
|
78
|
+
iden = s_common.guid()
|
|
79
|
+
|
|
80
|
+
model = core.model
|
|
81
|
+
model.core = None
|
|
82
|
+
|
|
83
|
+
synuser = model.type('syn:user')
|
|
84
|
+
synrole = model.type('syn:user')
|
|
85
|
+
|
|
86
|
+
self.eq(iden, synuser.repr(iden))
|
|
87
|
+
self.eq(iden, synrole.repr(iden))
|
|
88
|
+
|
|
89
|
+
self.eq(iden, synuser.norm(iden)[0])
|
|
90
|
+
self.eq(iden, synrole.norm(iden)[0])
|
|
91
|
+
|
|
49
92
|
async def test_syn_tag(self):
|
|
50
93
|
|
|
51
94
|
async with self.getTestCore() as core:
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import synapse.common as s_common
|
|
2
|
+
|
|
3
|
+
import synapse.lib.base as s_base
|
|
4
|
+
import synapse.lib.cell as s_cell
|
|
5
|
+
|
|
6
|
+
import synapse.tools.promote as s_tools_promote
|
|
7
|
+
|
|
8
|
+
import synapse.tests.utils as s_t_utils
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class PromoteToolTest(s_t_utils.SynTest):
|
|
12
|
+
|
|
13
|
+
async def test_tool_promote_simple(self):
|
|
14
|
+
async with self.getTestAha() as aha:
|
|
15
|
+
async with await s_base.Base.anit() as base:
|
|
16
|
+
with self.getTestDir() as dirn:
|
|
17
|
+
dirn00 = s_common.genpath(dirn, '00.cell')
|
|
18
|
+
dirn01 = s_common.genpath(dirn, '01.cell')
|
|
19
|
+
|
|
20
|
+
cell00 = await base.enter_context(self.addSvcToAha(aha, '00.cell', s_cell.Cell, dirn=dirn00))
|
|
21
|
+
cell01 = await base.enter_context(self.addSvcToAha(aha, '01.cell', s_cell.Cell, dirn=dirn01,
|
|
22
|
+
provinfo={'mirror': 'cell'}))
|
|
23
|
+
self.true(cell00.isactive)
|
|
24
|
+
self.false(cell01.isactive)
|
|
25
|
+
await cell01.sync()
|
|
26
|
+
|
|
27
|
+
outp = self.getTestOutp()
|
|
28
|
+
argv = ['--svcurl', cell00.getLocalUrl()]
|
|
29
|
+
ret = await s_tools_promote.main(argv, outp=outp)
|
|
30
|
+
self.eq(1, ret)
|
|
31
|
+
outp.expect('Failed to promote service')
|
|
32
|
+
outp.expect('promote() called on non-mirror')
|
|
33
|
+
|
|
34
|
+
outp.clear()
|
|
35
|
+
argv = ['--svcurl', cell01.getLocalUrl()]
|
|
36
|
+
ret = await s_tools_promote.main(argv, outp=outp)
|
|
37
|
+
self.eq(0, ret)
|
|
38
|
+
self.false(cell00.isactive)
|
|
39
|
+
self.true(cell01.isactive)
|
|
40
|
+
await cell00.sync()
|
|
41
|
+
|
|
42
|
+
async def test_tool_promote_schism(self):
|
|
43
|
+
# Create a mirror of mirrors and try promoting the end mirror.
|
|
44
|
+
async with self.getTestAha() as aha:
|
|
45
|
+
async with await s_base.Base.anit() as base:
|
|
46
|
+
with self.getTestDir() as dirn:
|
|
47
|
+
dirn00 = s_common.genpath(dirn, '00.cell')
|
|
48
|
+
dirn01 = s_common.genpath(dirn, '01.cell')
|
|
49
|
+
dirn02 = s_common.genpath(dirn, '02.cell')
|
|
50
|
+
|
|
51
|
+
cell00 = await base.enter_context(self.addSvcToAha(aha, '00.cell', s_cell.Cell, dirn=dirn00))
|
|
52
|
+
cell01 = await base.enter_context(self.addSvcToAha(aha, '01.cell', s_cell.Cell, dirn=dirn01,
|
|
53
|
+
provinfo={'mirror': '00.cell'}))
|
|
54
|
+
cell02 = await base.enter_context(self.addSvcToAha(aha, '02.cell', s_cell.Cell, dirn=dirn02,
|
|
55
|
+
provinfo={'mirror': '01.cell'}))
|
|
56
|
+
self.true(cell00.isactive)
|
|
57
|
+
self.false(cell01.isactive)
|
|
58
|
+
self.false(cell02.isactive)
|
|
59
|
+
await cell02.sync()
|
|
60
|
+
|
|
61
|
+
outp = self.getTestOutp()
|
|
62
|
+
argv = ['--svcurl', cell02.getLocalUrl()]
|
|
63
|
+
ret = await s_tools_promote.main(argv, outp=outp)
|
|
64
|
+
self.eq(1, ret)
|
|
65
|
+
outp.expect('Failed to promote service')
|
|
66
|
+
# Note: The following message may change when SYN-7659 is addressed
|
|
67
|
+
outp.expect('ahaname=01.cell is not the current leader and cannot handoff leadership to aha://02.cell.synapse')
|
synapse/tools/promote.py
CHANGED
|
@@ -2,9 +2,12 @@ import sys
|
|
|
2
2
|
import asyncio
|
|
3
3
|
import argparse
|
|
4
4
|
|
|
5
|
+
import synapse.exc as s_exc
|
|
6
|
+
|
|
5
7
|
import synapse.telepath as s_telepath
|
|
6
8
|
|
|
7
9
|
import synapse.lib.output as s_output
|
|
10
|
+
import synapse.lib.urlhelp as s_urlhelp
|
|
8
11
|
|
|
9
12
|
descr = '''
|
|
10
13
|
Promote a mirror to the leader.
|
|
@@ -29,7 +32,17 @@ async def main(argv, outp=s_output.stdout):
|
|
|
29
32
|
graceful = not opts.failure
|
|
30
33
|
|
|
31
34
|
outp.printf(f'Promoting to leader: {opts.svcurl}')
|
|
32
|
-
|
|
35
|
+
try:
|
|
36
|
+
await cell.promote(graceful=graceful)
|
|
37
|
+
except s_exc.BadState as e:
|
|
38
|
+
mesg = f'Failed to promote service to being a leader; {e.get("mesg")}'
|
|
39
|
+
outp.printf(mesg)
|
|
40
|
+
return 1
|
|
41
|
+
except s_exc.SynErr as e:
|
|
42
|
+
outp.printf(f'Failed to promote service {s_urlhelp.sanitizeUrl(opts.svcurl)}: {e}')
|
|
43
|
+
return 1
|
|
44
|
+
|
|
45
|
+
return 0
|
|
33
46
|
|
|
34
47
|
if __name__ == '__main__': # pragma: no cover
|
|
35
48
|
sys.exit(asyncio.run(main(sys.argv[1:])))
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: synapse
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.185.0
|
|
4
4
|
Summary: Synapse Intelligence Analysis Framework
|
|
5
5
|
Author-email: The Vertex Project LLC <root@vertex.link>
|
|
6
6
|
License: Apache License 2.0
|
|
@@ -59,15 +59,10 @@ Requires-Dist: bump2version<1.1.0,>=1.0.1; extra == "dev"
|
|
|
59
59
|
Requires-Dist: pytest-xdist<4.0.0,>=3.0.2; extra == "dev"
|
|
60
60
|
Requires-Dist: coverage<8.0.0,>=7.0.0; extra == "dev"
|
|
61
61
|
Provides-Extra: docs
|
|
62
|
-
Requires-Dist:
|
|
63
|
-
Requires-Dist:
|
|
64
|
-
Requires-Dist:
|
|
65
|
-
Requires-Dist:
|
|
66
|
-
Requires-Dist: nbstripout<1.0.0,>=0.3.3; extra == "docs"
|
|
67
|
-
Requires-Dist: sphinx<7.0.0,>=6.2.0; extra == "docs"
|
|
68
|
-
Requires-Dist: sphinx-rtd-theme<2.0.0,>=1.0.0; extra == "docs"
|
|
69
|
-
Requires-Dist: sphinx-notfound-page==0.8.3; extra == "docs"
|
|
70
|
-
Requires-Dist: jinja2<3.1.0; extra == "docs"
|
|
62
|
+
Requires-Dist: sphinx<9.0.0,>=8.0.0; extra == "docs"
|
|
63
|
+
Requires-Dist: sphinx-rtd-theme<4.0.0,>=3.0.0; extra == "docs"
|
|
64
|
+
Requires-Dist: sphinx-notfound-page<2.0.0,>=1.0.4; extra == "docs"
|
|
65
|
+
Requires-Dist: jinja2<4.0.0,>=3.1.4; extra == "docs"
|
|
71
66
|
|
|
72
67
|
Synapse
|
|
73
68
|
=======
|