synapse 2.213.0__py311-none-any.whl → 2.214.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 (68) hide show
  1. synapse/cortex.py +37 -6
  2. synapse/daemon.py +6 -6
  3. synapse/exc.py +13 -1
  4. synapse/lib/aha.py +5 -0
  5. synapse/lib/ast.py +2 -6
  6. synapse/lib/boss.py +47 -2
  7. synapse/lib/cell.py +193 -3
  8. synapse/lib/certdir.py +44 -1
  9. synapse/lib/cmd.py +24 -0
  10. synapse/lib/coro.py +8 -2
  11. synapse/lib/drive.py +7 -2
  12. synapse/lib/link.py +11 -3
  13. synapse/lib/schemas.py +1 -1
  14. synapse/lib/snap.py +76 -65
  15. synapse/lib/storm.py +2 -1
  16. synapse/lib/stormlib/imap.py +3 -2
  17. synapse/lib/stormlib/spooled.py +1 -0
  18. synapse/lib/task.py +1 -0
  19. synapse/lib/version.py +2 -2
  20. synapse/models/inet.py +5 -0
  21. synapse/tests/files/testpkg_build_docs/docs/bar.rst +15 -0
  22. synapse/tests/files/testpkg_build_docs/docs/foo.rst +4 -0
  23. synapse/tests/files/testpkg_build_docs/storm/commands/testcmd.storm +0 -0
  24. synapse/tests/files/testpkg_build_docs/storm/modules/apimod.storm +0 -0
  25. synapse/tests/files/testpkg_build_docs/storm/modules/testmod.storm +0 -0
  26. synapse/tests/files/testpkg_build_docs/storm/testcmd.storm +5 -0
  27. synapse/tests/files/testpkg_build_docs/testpkg.yaml +69 -0
  28. synapse/tests/test_cortex.py +20 -1
  29. synapse/tests/test_daemon.py +1 -1
  30. synapse/tests/test_exc.py +6 -0
  31. synapse/tests/test_lib_ast.py +69 -14
  32. synapse/tests/test_lib_boss.py +8 -0
  33. synapse/tests/test_lib_cell.py +104 -5
  34. synapse/tests/test_lib_certdir.py +8 -0
  35. synapse/tests/test_lib_coro.py +5 -0
  36. synapse/tests/test_lib_httpapi.py +10 -2
  37. synapse/tests/test_lib_link.py +1 -1
  38. synapse/tests/test_lib_storm.py +121 -1
  39. synapse/tests/test_lib_stormlib_spooled.py +20 -0
  40. synapse/tests/test_lib_types.py +1 -1
  41. synapse/tests/test_model_inet.py +7 -0
  42. synapse/tests/test_telepath.py +32 -5
  43. synapse/tests/test_tools_axon.py +304 -0
  44. synapse/tests/test_tools_cortex_layer.py +419 -0
  45. synapse/tests/test_tools_demote.py +114 -0
  46. synapse/tests/test_tools_pkgs_gendocs.py +100 -0
  47. synapse/tests/test_tools_shutdown.py +95 -0
  48. synapse/tests/test_utils.py +22 -1
  49. synapse/tests/utils.py +44 -29
  50. synapse/tools/aha/easycert.py +2 -0
  51. synapse/tools/aha/enroll.py +3 -0
  52. synapse/tools/axon/__init__.py +0 -0
  53. synapse/tools/axon/dump.py +155 -0
  54. synapse/tools/axon/load.py +89 -0
  55. synapse/tools/cortex/__init__.py +0 -0
  56. synapse/tools/cortex/layer/__init__.py +0 -0
  57. synapse/tools/cortex/layer/dump.py +184 -0
  58. synapse/tools/cortex/layer/load.py +129 -0
  59. synapse/tools/demote.py +52 -0
  60. synapse/tools/healthcheck.py +1 -1
  61. synapse/tools/pkgs/gendocs.py +176 -0
  62. synapse/tools/pkgs/pandoc_filter.py +79 -0
  63. synapse/tools/shutdown.py +52 -0
  64. {synapse-2.213.0.dist-info → synapse-2.214.0.dist-info}/METADATA +1 -1
  65. {synapse-2.213.0.dist-info → synapse-2.214.0.dist-info}/RECORD +68 -45
  66. {synapse-2.213.0.dist-info → synapse-2.214.0.dist-info}/WHEEL +0 -0
  67. {synapse-2.213.0.dist-info → synapse-2.214.0.dist-info}/licenses/LICENSE +0 -0
  68. {synapse-2.213.0.dist-info → synapse-2.214.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,419 @@
1
+ import os
2
+
3
+ import synapse.common as s_common
4
+
5
+ import synapse.lib.msgpack as s_msgpack
6
+ import synapse.lib.version as s_version
7
+
8
+ import synapse.tests.utils as s_test
9
+
10
+ import synapse.tools.cortex.layer.dump as s_t_dump
11
+ import synapse.tools.cortex.layer.load as s_t_load
12
+
13
+ class LayerTest(s_test.SynTest):
14
+
15
+ async def test_tools_layer_dump(self):
16
+
17
+ async with self.getTestCore() as core:
18
+
19
+ url = core.getLocalUrl()
20
+
21
+ layr00 = await core.addLayer()
22
+ layr00iden = layr00.get('iden')
23
+ view00 = await core.addView({'layers': [layr00iden]})
24
+
25
+ soffs = await core.getNexsIndx()
26
+
27
+ opts = {'view': view00.get('iden'), 'vars': {'n': 256}}
28
+ nodes = await core.nodes('for $i in $lib.range($n) { [test:int=$i] }', opts=opts)
29
+ self.len(256, nodes)
30
+
31
+ eoffs = soffs + 256
32
+
33
+ chunksize = 10
34
+
35
+ with self.getTestDir() as dirn:
36
+ argv = (
37
+ '--url', url,
38
+ '--chunksize', str(chunksize),
39
+ '--offset', str(soffs),
40
+ layr00iden,
41
+ dirn,
42
+ )
43
+
44
+ outp = self.getTestOutp()
45
+ self.eq(0, await s_t_dump.main(argv, outp=outp))
46
+ outp.expect(f'Successfully exported layer {layr00iden}.')
47
+
48
+ for ii in range(soffs, eoffs - chunksize, chunksize):
49
+ path = s_common.genpath(dirn, f'{core.iden}.{layr00iden}.{ii}-{ii + chunksize - 1}.nodeedits')
50
+ self.true(os.path.exists(path))
51
+
52
+ # Open and inspect first file
53
+ filename = f'{core.iden}.{layr00iden}.{soffs}-{soffs + 9}.nodeedits'
54
+ msgs = list(s_msgpack.iterfile(s_common.genpath(dirn, filename)))
55
+ self.len(12, msgs)
56
+
57
+ self.eq(msgs[0][0], 'init')
58
+ self.eq(msgs[0][1].get('hdrvers'), 1)
59
+ self.eq(msgs[0][1].get('celliden'), core.iden)
60
+ self.eq(msgs[0][1].get('layriden'), layr00iden)
61
+ self.eq(msgs[0][1].get('offset'), soffs)
62
+ self.eq(msgs[0][1].get('chunksize'), chunksize)
63
+ self.nn(msgs[0][1].get('tick'))
64
+ self.isinstance(msgs[0][1].get('tick'), int)
65
+ self.eq(msgs[0][1].get('cellvers'), core.cellinfo.get('cell:version'))
66
+
67
+ for msg in msgs[1:-1]:
68
+ self.len(2, msg)
69
+ self.eq(msg[0], 'edit')
70
+ self.len(3, msg[1])
71
+
72
+ self.eq(msgs[11][0], 'fini')
73
+ self.eq(msgs[11][1].get('offset'), soffs + 9)
74
+ self.nn(msgs[11][1].get('tock'))
75
+ self.isinstance(msgs[11][1].get('tock'), int)
76
+
77
+ # Test state tracking
78
+ with self.getTestDir() as dirn:
79
+ # Check state file is written
80
+ argv = (
81
+ '--url', url,
82
+ '--chunksize', str(chunksize),
83
+ '--offset', str(soffs),
84
+ layr00iden,
85
+ dirn,
86
+ )
87
+
88
+ outp = self.getTestOutp()
89
+ self.eq(0, await s_t_dump.main(argv, outp=outp))
90
+ outp.expect(f'Successfully exported layer {layr00iden}.')
91
+
92
+ state = s_common.yamlload(dirn, f'{core.iden}.{layr00iden}.yaml')
93
+ self.eq(state, {'offset:next': eoffs})
94
+
95
+ # Check state file is read
96
+ opts = {'view': view00.get('iden'), 'vars': {'n': 256}}
97
+ nodes = await core.nodes('for $i in $lib.range($n) { [test:str=$i] }', opts=opts)
98
+ self.len(256, nodes)
99
+
100
+ state = {'offset:next': eoffs + 1}
101
+ statefile = s_common.genpath(dirn, 'state.yaml')
102
+ s_common.yamlsave(state, statefile)
103
+
104
+ argv = (
105
+ '--url', url,
106
+ '--statefile', statefile,
107
+ layr00iden,
108
+ s_common.genpath(dirn, 'next'),
109
+ )
110
+
111
+ outp = self.getTestOutp()
112
+ self.eq(0, await s_t_dump.main(argv, outp=outp))
113
+ outp.expect(f'Successfully exported layer {layr00iden}.')
114
+
115
+ state = s_common.yamlload(dirn, statefile)
116
+ self.eq(state, {'offset:next': eoffs + 256})
117
+
118
+ async def test_tools_layer_dump_errors(self):
119
+
120
+ # Non-cortex cell
121
+ async with self.getTestCell() as cell:
122
+ with self.getTestDir() as dirn:
123
+ with s_common.genfile(dirn, 'newp') as fd:
124
+ filename = fd.name
125
+ fd.write(s_msgpack.en(('init', {'offset': 0, 'cellvers': s_version.version})))
126
+
127
+ url = cell.getLocalUrl()
128
+ argv = ('--url', url, s_common.guid(), dirn)
129
+ outp = self.getTestOutp()
130
+ self.eq(1, await s_t_dump.main(argv, outp=outp))
131
+ outp.expect(f'ERROR: Layer dump tool only works on cortexes, not cell.')
132
+
133
+ async with self.getTestCore() as core:
134
+
135
+ url = core.getLocalUrl()
136
+
137
+ layr00 = await core.addLayer()
138
+ layr00iden = layr00.get('iden')
139
+ view00 = await core.addView({'layers': [layr00iden]})
140
+
141
+ soffs = await core.getNexsIndx()
142
+
143
+ opts = {'view': view00.get('iden'), 'vars': {'n': 256}}
144
+ nodes = await core.nodes('for $i in $lib.range($n) { [test:int=$i] }', opts=opts)
145
+ self.len(256, nodes)
146
+
147
+ eoffs = soffs + 256
148
+
149
+ chunksize = 10
150
+
151
+ with self.getTestDir() as dirn:
152
+ # Handle no edits from offset
153
+ argv = (
154
+ '--url', url,
155
+ '--chunksize', str(chunksize),
156
+ '--offset', '9000',
157
+ layr00iden,
158
+ dirn,
159
+ )
160
+
161
+ outp = self.getTestOutp()
162
+ self.eq(1, await s_t_dump.main(argv, outp=outp))
163
+ outp.expect(f'ERROR: No edits to export starting from offset (9000).')
164
+
165
+ # Handle outdir being an existing file
166
+ filename = s_common.genpath(dirn, 'newp')
167
+ s_common.genfile(filename).close()
168
+
169
+ argv = (
170
+ '--url', url,
171
+ '--chunksize', str(chunksize),
172
+ layr00iden,
173
+ filename,
174
+ )
175
+
176
+ outp = self.getTestOutp()
177
+ self.eq(1, await s_t_dump.main(argv, outp=outp))
178
+ outp.expect(f'ERROR: Specified output directory {filename} exists but is not a directory.')
179
+
180
+ # Invalid layer iden
181
+ newpiden = s_common.guid()
182
+ argv = (
183
+ '--url', url,
184
+ '--chunksize', str(chunksize),
185
+ newpiden,
186
+ dirn,
187
+ )
188
+
189
+ outp = self.getTestOutp()
190
+ self.eq(1, await s_t_dump.main(argv, outp=outp))
191
+ outp.expect(f'ERROR: No such layer {newpiden}.')
192
+
193
+ async def test_tools_layer_load(self):
194
+ async with self.getTestCore() as core:
195
+
196
+ url = core.getLocalUrl()
197
+
198
+ layr00 = await core.addLayer()
199
+ layr00iden = layr00.get('iden')
200
+ view00 = await core.addView({'layers': [layr00iden]})
201
+
202
+ layr01 = await core.addLayer()
203
+ layr01iden = layr01.get('iden')
204
+ view01 = await core.addView({'layers': [layr01iden]})
205
+
206
+ soffs = await core.getNexsIndx()
207
+
208
+ opts = {'view': view00.get('iden'), 'vars': {'n': 256}}
209
+ nodes = await core.nodes('for $i in $lib.range($n) { [test:int=$i] }', opts=opts)
210
+ self.len(256, nodes)
211
+
212
+ eoffs = soffs + 256
213
+
214
+ with self.getTestDir() as dirn:
215
+ # Export layr00
216
+ argv = (
217
+ '--url', url,
218
+ layr00iden,
219
+ dirn,
220
+ )
221
+
222
+ outp = self.getTestOutp()
223
+ self.eq(0, await s_t_dump.main(argv, outp=outp))
224
+ outp.expect(f'Successfully exported layer {layr00iden}.')
225
+
226
+ # Verify layr01 is empty
227
+ opts = {'view': view01.get('iden')}
228
+ nodes = await core.nodes('inet:ipv4', opts=opts)
229
+ self.len(0, nodes)
230
+
231
+ files = [os.path.join(dirn, k) for k in os.listdir(dirn) if k.endswith('.nodeedits')]
232
+ self.len(1, files)
233
+
234
+ # Import to layr01
235
+ argv = (
236
+ '--url', url,
237
+ '--dryrun',
238
+ layr01iden,
239
+ files[0],
240
+ )
241
+
242
+ outp = self.getTestOutp()
243
+ self.eq(0, await s_t_load.main(argv, outp=outp))
244
+ outp.expect('Processing the following nodeedits:')
245
+ outp.expect(f'{soffs:<16d} | {files[0]}')
246
+ outp.expect(f'Loading {files[0]}, offset={soffs}, tick=')
247
+ outp.expect(f'Successfully read {files[0]} as a dryrun test.')
248
+
249
+ # Verify layr01 is empty
250
+ opts = {'view': view01.get('iden')}
251
+ nodes = await core.nodes('inet:ipv4', opts=opts)
252
+ self.len(0, nodes)
253
+
254
+ # Import to layr01
255
+ argv = (
256
+ '--url', url,
257
+ layr01iden,
258
+ files[0],
259
+ )
260
+
261
+ outp = self.getTestOutp()
262
+ self.eq(0, await s_t_load.main(argv, outp=outp))
263
+ outp.expect('Processing the following nodeedits:')
264
+ outp.expect(f'{soffs:<16d} | {files[0]}')
265
+ outp.expect(f'Loading {files[0]}, offset={soffs}, tick=')
266
+ outp.expect(f'Successfully loaded {files[0]} with {eoffs - soffs} edits ({soffs} - {eoffs - 1}).')
267
+
268
+ # Verify layr01 has data now
269
+ opts = {'view': view01.get('iden')}
270
+ nodes = await core.nodes('test:int', opts=opts)
271
+ self.len(256, nodes)
272
+
273
+ async def test_tools_layer_load_errors(self):
274
+
275
+ iden = s_common.guid()
276
+
277
+ # Non-cortex cell
278
+ with self.getTestDir() as dirn:
279
+ with s_common.genfile(dirn, 'newp') as fd:
280
+ filename = fd.name
281
+ fd.write(s_msgpack.en(('init', {'offset': 0, 'cellvers': s_version.version})))
282
+
283
+ async with self.getTestCell() as cell:
284
+ url = cell.getLocalUrl()
285
+ argv = ('--url', url, iden, filename)
286
+ outp = self.getTestOutp()
287
+ self.eq(1, await s_t_load.main(argv, outp=outp))
288
+ outp.expect(f'ERROR: Layer load tool only works on cortexes, not cell.')
289
+
290
+ # Non-existent file
291
+ argv = (iden, 'newp')
292
+ outp = self.getTestOutp()
293
+ self.eq(1, await s_t_load.main(argv, outp=outp))
294
+ outp.expect('Invalid input file specified: newp.')
295
+
296
+ # Input file is a directory
297
+ with self.getTestDir() as dirn:
298
+ argv = (iden, dirn)
299
+ outp = self.getTestOutp()
300
+ self.eq(1, await s_t_load.main(argv, outp=outp))
301
+ outp.expect(f'Invalid input file specified: {dirn}.')
302
+
303
+ # Input file doesn't have an init message first
304
+ with self.getTestDir() as dirn:
305
+ with s_common.genfile(dirn, 'noinit.nodeedits') as fd:
306
+ filename = fd.name
307
+ fd.write(s_msgpack.en(('newp', {})))
308
+
309
+ argv = (iden, filename)
310
+ outp = self.getTestOutp()
311
+ self.eq(1, await s_t_load.main(argv, outp=outp))
312
+ outp.expect(f'Invalid header in {filename}.')
313
+
314
+ # Invalid/too high cell version
315
+ with self.getTestDir() as dirn:
316
+ version = (99, 99, 0)
317
+ verstr = '.'.join(map(str, version))
318
+
319
+ with s_common.genfile(dirn, 'cellvers00.nodeedits') as fd:
320
+ file00 = fd.name
321
+ fd.write(s_msgpack.en(('init', {'offset': 0, 'cellvers': s_version.version})))
322
+
323
+ with s_common.genfile(dirn, 'cellvers01.nodeedits') as fd:
324
+ file01 = fd.name
325
+ fd.write(s_msgpack.en(('init', {'offset': 0, 'cellvers': version})))
326
+
327
+ async with self.getTestCore() as core:
328
+ url = core.getLocalUrl()
329
+ argv = ('--url', url, iden, file00, file01)
330
+ outp = self.getTestOutp()
331
+ self.eq(1, await s_t_load.main(argv, outp=outp))
332
+ outp.expect(f'Synapse version mismatch ({s_version.verstring} < {verstr}).')
333
+
334
+ # Invalid message type
335
+ with self.getTestDir() as dirn:
336
+ with s_common.genfile(dirn, 'badtype.nodeedits') as fd:
337
+ filename = fd.name
338
+ fd.write(s_msgpack.en((
339
+ 'init',
340
+ {
341
+ 'hdrvers': 1,
342
+ 'celliden': s_common.guid(),
343
+ 'layriden': s_common.guid(),
344
+ 'offset': 0,
345
+ 'chunksize': 10000,
346
+ 'tick': s_common.now(),
347
+ 'cellvers': s_version.version,
348
+ }
349
+ )))
350
+
351
+ fd.write(s_msgpack.en(('newp', {})))
352
+
353
+ async with self.getTestCore() as core:
354
+ url = core.getLocalUrl()
355
+ layriden = core.getView().layers[0].iden
356
+ argv = ('--url', url, layriden, filename)
357
+ outp = self.getTestOutp()
358
+ self.eq(1, await s_t_load.main(argv, outp=outp))
359
+ outp.expect('Unexpected message type: newp.')
360
+
361
+ # Missing fini
362
+ with self.getTestDir() as dirn:
363
+ with s_common.genfile(dirn, 'badtype.nodeedits') as fd:
364
+ filename = fd.name
365
+ fd.write(s_msgpack.en((
366
+ 'init',
367
+ {
368
+ 'hdrvers': 1,
369
+ 'celliden': s_common.guid(),
370
+ 'layriden': s_common.guid(),
371
+ 'offset': 0,
372
+ 'chunksize': 10000,
373
+ 'tick': s_common.now(),
374
+ 'cellvers': s_version.version,
375
+ }
376
+ )))
377
+
378
+ async with self.getTestCore() as core:
379
+ url = core.getLocalUrl()
380
+ layriden = core.getView().layers[0].iden
381
+ argv = ('--url', url, layriden, filename)
382
+ outp = self.getTestOutp()
383
+ self.eq(1, await s_t_load.main(argv, outp=outp))
384
+ outp.expect(f'Incomplete/corrupt export: {filename}.')
385
+
386
+ # Fini offset mismatch
387
+ with self.getTestDir() as dirn:
388
+ soffs = 0
389
+ eoffs = 1000
390
+ with s_common.genfile(dirn, 'badtype.nodeedits') as fd:
391
+ filename = fd.name
392
+ fd.write(s_msgpack.en((
393
+ 'init',
394
+ {
395
+ 'hdrvers': 1,
396
+ 'celliden': s_common.guid(),
397
+ 'layriden': s_common.guid(),
398
+ 'offset': soffs,
399
+ 'chunksize': 10000,
400
+ 'tick': s_common.now(),
401
+ 'cellvers': s_version.version,
402
+ }
403
+ )))
404
+
405
+ fd.write(s_msgpack.en((
406
+ 'fini',
407
+ {
408
+ 'offset': eoffs,
409
+ 'tock': s_common.now(),
410
+ }
411
+ )))
412
+
413
+ async with self.getTestCore() as core:
414
+ url = core.getLocalUrl()
415
+ layriden = core.getView().layers[0].iden
416
+ argv = ('--url', url, layriden, filename)
417
+ outp = self.getTestOutp()
418
+ self.eq(1, await s_t_load.main(argv, outp=outp))
419
+ outp.expect(f'Incomplete/corrupt export: {filename}. Expected offset {eoffs}, got {soffs}.')
@@ -0,0 +1,114 @@
1
+ import unittest.mock as mock
2
+
3
+ import synapse.exc as s_exc
4
+ import synapse.common as s_common
5
+
6
+ import synapse.lib.cell as s_cell
7
+
8
+ import synapse.tools.demote as s_tools_demote
9
+
10
+ import synapse.tests.utils as s_test
11
+
12
+ async def boom(*args, **kwargs):
13
+ raise s_exc.SynErr(mesg='BOOM')
14
+
15
+ class DemoteToolTest(s_test.SynTest):
16
+
17
+ async def test_tool_demote_base(self):
18
+
19
+ async with self.getTestAha() as aha:
20
+
21
+ with self.getTestDir() as dirn:
22
+
23
+ dirn00 = s_common.genpath(dirn, '00.cell')
24
+ dirn01 = s_common.genpath(dirn, '01.cell')
25
+
26
+ cell00 = await aha.enter_context(self.addSvcToAha(aha, '00.cell', s_cell.Cell, dirn=dirn00))
27
+ cell01 = await aha.enter_context(self.addSvcToAha(aha, '01.cell', s_cell.Cell, dirn=dirn01,
28
+ provinfo={'mirror': 'cell'}))
29
+ self.true(cell00.isactive)
30
+ self.false(cell01.isactive)
31
+
32
+ await cell01.sync()
33
+
34
+ outp = self.getTestOutp()
35
+ argv = ['--url', cell00.getLocalUrl()]
36
+
37
+ self.eq(0, await s_tools_demote.main(argv, outp=outp))
38
+ outp.expect('Demoting leader: cell://')
39
+
40
+ self.false(cell00.isactive)
41
+ self.true(cell01.isactive)
42
+
43
+ await cell00.sync()
44
+
45
+ outp.clear()
46
+ self.eq(1, await s_tools_demote.main(argv, outp=outp))
47
+ outp.expect('Failed to demote service cell:')
48
+
49
+ # get some test coverage for the various levels of exception handlers...
50
+
51
+ with mock.patch.object(cell00, 'getNexsIndx', boom):
52
+ with self.getLoggerStream('synapse') as stream:
53
+ argv = ['--url', cell01.getLocalUrl(), '--timeout', '12']
54
+ self.eq(1, await s_tools_demote.main(argv, outp=outp))
55
+ stream.expect('...error retrieving nexus index for')
56
+
57
+ with mock.patch.object(cell00, 'promote', boom):
58
+ with self.getLoggerStream('synapse') as stream:
59
+ argv = ['--url', cell01.getLocalUrl(), '--timeout', '12']
60
+ self.eq(1, await s_tools_demote.main(argv, outp=outp))
61
+ stream.expect('...error promoting')
62
+
63
+ with mock.patch.object(cell01, '_getDemotePeers', boom):
64
+ with self.getLoggerStream('synapse') as stream:
65
+ argv = ['--url', cell01.getLocalUrl(), '--timeout', '12']
66
+ outp.clear()
67
+ self.eq(1, await s_tools_demote.main(argv, outp=outp))
68
+ outp.expect('Error while demoting service')
69
+ stream.expect('error during task: demote')
70
+
71
+ self.false(cell00.isactive)
72
+ self.true(cell01.isactive)
73
+
74
+ outp.clear()
75
+ self.eq(1, await s_tools_demote.main(['--url', 'newp://hehe'], outp=outp))
76
+ outp.expect('Error while demoting service newp://hehe')
77
+
78
+ self.true(await aha.schedCoro(cell01.shutdown(timeout=12)))
79
+ self.true(cell00.isactive)
80
+ self.false(cell01.isactive)
81
+
82
+ self.true(await cell01.waitfini(timeout=12))
83
+
84
+ # test demote with insufficient peers
85
+ with self.getLoggerStream('synapse') as stream:
86
+ argv = ['--url', cell00.getLocalUrl(), '--timeout', '12']
87
+ self.eq(1, await s_tools_demote.main(argv, outp=outp))
88
+ stream.expect('...no suitable services discovered.')
89
+
90
+ async def test_tool_demote_no_features(self):
91
+
92
+ async with self.getTestAha() as aha:
93
+ aha.features.pop('getAhaSvcsByIden')
94
+
95
+ with self.getTestDir() as dirn:
96
+
97
+ dirn00 = s_common.genpath(dirn, '00.cell')
98
+ dirn01 = s_common.genpath(dirn, '01.cell')
99
+
100
+ cell00 = await aha.enter_context(self.addSvcToAha(aha, '00.cell', s_cell.Cell, dirn=dirn00))
101
+ cell01 = await aha.enter_context(self.addSvcToAha(aha, '01.cell', s_cell.Cell, dirn=dirn01,
102
+ provinfo={'mirror': 'cell'}))
103
+ self.true(cell00.isactive)
104
+ self.false(cell01.isactive)
105
+
106
+ await cell01.sync()
107
+
108
+ outp = self.getTestOutp()
109
+ argv = ['--url', cell00.getLocalUrl()]
110
+ with self.getAsyncLoggerStream('synapse.daemon') as stream:
111
+ self.eq(1, await s_tools_demote.main(argv, outp=outp))
112
+ stream.expect('AHA server does not support feature: getAhaSvcsByIden >= 1')
113
+ outp.expect('Error while demoting service')
114
+ outp.expect('AHA server does not support feature: getAhaSvcsByIden')
@@ -0,0 +1,100 @@
1
+ import io
2
+ import os
3
+ import sys
4
+ import json
5
+
6
+ import synapse.exc as s_exc
7
+ import synapse.common as s_common
8
+
9
+ import synapse.tests.utils as s_t_utils
10
+
11
+ import synapse.tools.pkgs.gendocs as s_t_gendocs
12
+ import synapse.tools.pkgs.pandoc_filter as s_t_pandoc_filter
13
+
14
+ class TestPkgBuildDocs(s_t_utils.SynTest):
15
+
16
+ def setUp(self):
17
+ if not s_t_gendocs.hasPandoc():
18
+ self.skip('pandoc is not available')
19
+ super().setUp()
20
+
21
+ async def test_pkg_builddocs(self):
22
+
23
+ with self.getTestDir(mirror='testpkg_build_docs') as dirn:
24
+ testpkgfp = os.path.join(dirn, 'testpkg.yaml')
25
+ self.true(os.path.isfile(testpkgfp))
26
+ argv = [testpkgfp, ]
27
+ r = await s_t_gendocs.main(argv)
28
+ self.eq(r, 0)
29
+
30
+ pkgdef = s_common.yamlload(testpkgfp)
31
+ efiles = set()
32
+ for dnfo in pkgdef.get('docs'):
33
+ bname = os.path.basename(dnfo.get('path'))
34
+ efiles.add(bname)
35
+ efiles.add(bname.rsplit('.', 1)[0] + '.rst')
36
+ builddir = os.path.join(dirn, 'docs', '_build')
37
+ self.eq(efiles, set(os.listdir(builddir)))
38
+
39
+ text = s_common.getbytes(os.path.join(builddir, 'bar.md')).decode()
40
+ self.isin('storm> [inet:asn=1]', text)
41
+ self.isin('inet:asn=1\n', text)
42
+ self.notin(':orphan:', text)
43
+ self.notin(':tocdepth:', text)
44
+
45
+ text = s_common.getbytes(os.path.join(builddir, 'stormpackage.md')).decode()
46
+ self.isin(': baz (str): The baz.', text)
47
+ self.isin(': Baz the bam:\n\n yield $lib.import(apimod).search(bam)', text)
48
+
49
+ with self.getTestDir(mirror='testpkg_build_docs') as dirn:
50
+ testpkgfp = os.path.join(dirn, 'testpkg.yaml')
51
+ self.true(os.path.isfile(testpkgfp))
52
+ argv = [testpkgfp, '--rst-only']
53
+ r = await s_t_gendocs.main(argv)
54
+ self.eq(r, 0)
55
+
56
+ pkgdef = s_common.yamlload(testpkgfp)
57
+ efiles = set()
58
+ for dnfo in pkgdef.get('docs'):
59
+ bname = os.path.basename(dnfo.get('path'))
60
+ efiles.add(bname)
61
+ efiles.add(bname.rsplit('.', 1)[0] + '.rst')
62
+ builddir = os.path.join(dirn, 'docs', '_build')
63
+ self.eq(efiles, set(os.listdir(builddir)))
64
+
65
+ text = s_common.getbytes(os.path.join(builddir, 'bar.md')).decode()
66
+ self.eq('', text)
67
+ text = s_common.getbytes(os.path.join(builddir, 'stormpackage.md')).decode()
68
+ self.eq('', text)
69
+
70
+ with self.getTestDir(mirror='testpkg_build_docs') as dirn:
71
+
72
+ # Missing input files
73
+ testpkgfp = os.path.join(dirn, 'newp.yaml')
74
+ self.false(os.path.isfile(testpkgfp))
75
+ argv = [testpkgfp, ]
76
+ with self.raises(s_exc.BadArg) as cm:
77
+ await s_t_gendocs.main(argv)
78
+ self.isin('Package does not exist or does not contain yaml', cm.exception.get('mesg'))
79
+
80
+ # pandoc api version check coverage
81
+ old_stdin = sys.stdin
82
+ try:
83
+ sys.stdin = io.StringIO(json.dumps({'pandoc-api-version': [2, 0, 0]}))
84
+ with self.raises(Exception) as cm:
85
+ s_t_pandoc_filter.main()
86
+ self.isin('does not match required version', str(cm.exception))
87
+ finally:
88
+ sys.stdin = old_stdin
89
+
90
+ # pandoc failure
91
+ outp = self.getTestOutp()
92
+ oldv = s_t_gendocs.PANDOC_FILTER
93
+ try:
94
+ s_t_gendocs.PANDOC_FILTER = os.path.join(dirn, 'newp.py')
95
+ with self.raises(s_exc.SynErr) as cm:
96
+ await s_t_gendocs.main([os.path.join(dirn, 'testpkg.yaml'),], outp=outp)
97
+ self.isin('Error converting', cm.exception.get('mesg'))
98
+ outp.expect('ERR: Error running filter')
99
+ finally:
100
+ s_t_gendocs.PANDOC_FILTER = oldv