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
synapse/lib/cmd.py CHANGED
@@ -1,6 +1,11 @@
1
+ import sys
2
+ import asyncio
1
3
  import argparse
2
4
 
3
5
  import synapse.exc as s_exc
6
+ import synapse.common as s_common
7
+
8
+ import synapse.lib.coro as s_coro
4
9
  import synapse.lib.output as s_output
5
10
 
6
11
  class Parser(argparse.ArgumentParser):
@@ -25,6 +30,7 @@ class Parser(argparse.ArgumentParser):
25
30
 
26
31
  if message is not None:
27
32
  self.outp.printf(message)
33
+
28
34
  raise s_exc.ParserExit(mesg=message, status=status)
29
35
 
30
36
  def _print_message(self, text, fd=None):
@@ -32,3 +38,21 @@ class Parser(argparse.ArgumentParser):
32
38
  Note: this overrides an existing method in ArgumentParser
33
39
  '''
34
40
  self.outp.printf(text)
41
+
42
+ async def wrapmain(func): # pragma: no cover
43
+
44
+ try:
45
+ return await func(sys.argv[1:])
46
+
47
+ except s_exc.ParserExit:
48
+ return 1
49
+
50
+ except Exception as e:
51
+ print(f'ERROR: {s_exc.reprexc(e)}')
52
+ return 1
53
+
54
+ finally:
55
+ await s_coro.await_bg_tasks(timeout=10)
56
+
57
+ def exitmain(func): # pragma: no cover
58
+ sys.exit(asyncio.run(wrapmain(func)))
synapse/lib/coro.py CHANGED
@@ -175,10 +175,16 @@ def create_task(coro):
175
175
 
176
176
  return task
177
177
 
178
- async def await_bg_tasks():
178
+ async def await_bg_tasks(timeout=None):
179
+
179
180
  if not bgtasks:
180
181
  return []
181
- return await asyncio.gather(*tuple(bgtasks), return_exceptions=True)
182
+
183
+ coro = asyncio.gather(*tuple(bgtasks), return_exceptions=True)
184
+ try:
185
+ return await s_common.wait_for(coro, timeout)
186
+ except (asyncio.CancelledError, asyncio.TimeoutError):
187
+ return []
182
188
 
183
189
  class GenrHelp:
184
190
 
synapse/lib/drive.py CHANGED
@@ -69,6 +69,9 @@ class Drive(s_base.Base):
69
69
 
70
70
  def getItemInfo(self, iden, typename=None):
71
71
  info = self._getItemInfo(s_common.uhex(iden))
72
+ if not info:
73
+ return
74
+
72
75
  if typename is not None:
73
76
  self._reqInfoType(info, typename)
74
77
  return info
@@ -210,7 +213,7 @@ class Drive(s_base.Base):
210
213
 
211
214
  def _setItemPerm(self, bidn, perm):
212
215
  info = self._reqItemInfo(bidn)
213
- info['perm'] = perm
216
+ info['permissions'] = perm
214
217
  s_schemas.reqValidDriveInfo(info)
215
218
  self.slab.put(LKEY_INFO + bidn, s_msgpack.en(info), db=self.dbname)
216
219
  return info
@@ -286,7 +289,7 @@ class Drive(s_base.Base):
286
289
  info['kids'] = 0
287
290
  info['parent'] = pariden
288
291
 
289
- info.setdefault('perm', {'users': {}, 'roles': {}})
292
+ info.setdefault('permissions', {'users': {}, 'roles': {}})
290
293
  info.setdefault('version', (0, 0, 0))
291
294
 
292
295
  s_schemas.reqValidDriveInfo(info)
@@ -447,6 +450,8 @@ class Drive(s_base.Base):
447
450
 
448
451
  if vers is None:
449
452
  info = self._getItemInfo(bidn)
453
+ if info is None:
454
+ return None
450
455
  vers = info.get('version')
451
456
 
452
457
  versindx = getVersIndx(vers)
synapse/lib/link.py CHANGED
@@ -61,7 +61,15 @@ async def unixconnect(path):
61
61
  '''
62
62
  Connect to a PF_UNIX server listening on the given path.
63
63
  '''
64
- reader, writer = await asyncio.open_unix_connection(path=path)
64
+ try:
65
+ reader, writer = await asyncio.open_unix_connection(path=path)
66
+ except ConnectionRefusedError as e:
67
+ mesg = f'Cell path is not listening: {path}'
68
+ raise s_exc.LinkErr(mesg=mesg) from e
69
+ except FileNotFoundError as e:
70
+ mesg = f'Cell path does not exist: {path}'
71
+ raise s_exc.NoSuchPath(mesg=mesg) from e
72
+
65
73
  info = {'path': path, 'unix': True}
66
74
  return await Link.anit(reader, writer, info=info)
67
75
 
@@ -321,9 +329,9 @@ class Link(s_base.Base):
321
329
  raise
322
330
 
323
331
  except Exception as e:
324
- mesg = f'rx error {e} link={self.getAddrInfo()}'
332
+ mesg = f'rx closed unexpectedly {e} link={self.getAddrInfo()}'
325
333
  if isinstance(e, (BrokenPipeError, ConnectionResetError)):
326
- logger.warning(mesg)
334
+ logger.debug(mesg)
327
335
  else:
328
336
  logger.exception(mesg)
329
337
  await self.fini()
synapse/lib/schemas.py CHANGED
@@ -469,7 +469,7 @@ driveInfoSchema = {
469
469
  'parent': {'type': 'string', 'pattern': s_config.re_iden},
470
470
  'type': {'type': 'string', 'pattern': re_drivename},
471
471
  'name': {'type': 'string', 'pattern': re_drivename},
472
- 'perm': s_msgpack.deepcopy(easyPermSchema),
472
+ 'permissions': s_msgpack.deepcopy(easyPermSchema),
473
473
  'kids': {'type': 'number', 'minimum': 0},
474
474
  'created': {'type': 'number'},
475
475
  'creator': {'type': 'string', 'pattern': s_config.re_iden},
synapse/lib/snap.py CHANGED
@@ -1454,7 +1454,9 @@ class Snap(s_base.Base):
1454
1454
  if isinstance(valu, dict):
1455
1455
  form = self.core.model.reqForm(name)
1456
1456
  if isinstance(form.type, s_types.Guid):
1457
- return await self._addGuidNodeByDict(form, valu, props=props)
1457
+ norms, props = await self._normGuidNodeDict(form, valu, props=props)
1458
+ valu = await self._addGuidNodeByDict(form, norms, props)
1459
+ return await self.getNodeByNdef((name, valu))
1458
1460
 
1459
1461
  async with self.getEditor() as editor:
1460
1462
  protonode = await editor.addNode(name, valu, props=props, norminfo=norminfo)
@@ -1464,100 +1466,109 @@ class Snap(s_base.Base):
1464
1466
  # the newly constructed node is cached
1465
1467
  return await self.getNodeByBuid(protonode.buid)
1466
1468
 
1467
- async def _addGuidNodeByDict(self, form, vals, props=None):
1469
+ async def _addGuidNodeByDict(self, form, norms, props):
1468
1470
 
1469
- if props is None:
1470
- props = {}
1471
-
1472
- trycast = vals.pop('$try', False)
1473
- addprops = vals.pop('$props', None)
1474
-
1475
- if not vals:
1476
- mesg = f'No values provided for form {form.full}'
1477
- raise s_exc.BadTypeValu(mesg=mesg)
1478
-
1479
- for name, valu in list(props.items()):
1480
- try:
1481
- props[name] = form.reqProp(name).type.norm(valu)
1482
- except s_exc.BadTypeValu as e:
1483
- mesg = e.get('mesg')
1484
- e.update({
1485
- 'prop': name,
1486
- 'form': form.name,
1487
- 'mesg': f'Bad value for prop {form.name}:{name}: {mesg}',
1488
- })
1489
- raise e
1490
-
1491
- if addprops is not None:
1492
- for name, valu in addprops.items():
1493
- try:
1494
- props[name] = form.reqProp(name).type.norm(valu)
1495
- except s_exc.BadTypeValu as e:
1496
- mesg = e.get("mesg")
1497
- if not trycast:
1498
- e.update({
1499
- 'prop': name,
1500
- 'form': form.name,
1501
- 'mesg': f'Bad value for prop {form.name}:{name}: {mesg}'
1502
- })
1503
- raise e
1504
- await self.warn(f'Skipping bad value for prop {form.name}:{name}: {mesg}')
1471
+ for name, info in norms.items():
1472
+ if info[0].isform:
1473
+ valu = await self._addGuidNodeByDict(*info)
1474
+ norms[name] = (form.prop(name), valu, {})
1505
1475
 
1506
- norms, proplist = self._normGuidNodeDict(form, vals)
1476
+ for name, info in props.items():
1477
+ if info[0].isform:
1478
+ valu = await self._addGuidNodeByDict(*info)
1479
+ props[name] = (form.prop(name), valu, {})
1507
1480
 
1508
- iden = s_common.guid(proplist)
1509
- node = await self._getGuidNodeByNorms(form, iden, norms)
1481
+ node = await self._getGuidNodeByNorms(form, norms)
1510
1482
 
1511
1483
  async with self.getEditor() as editor:
1512
1484
 
1513
1485
  if node is not None:
1514
1486
  proto = editor.loadNode(node)
1515
1487
  else:
1516
- proto = await editor.addNode(form.name, iden)
1488
+ proplist = [(name, info[1]) for name, info in norms.items()]
1489
+ proplist.sort()
1490
+
1491
+ proto = await editor.addNode(form.name, proplist)
1517
1492
  for name, (prop, valu, info) in norms.items():
1518
1493
  await proto.set(name, valu, norminfo=info)
1519
1494
 
1520
1495
  # ensure the non-deconf props are set
1521
- for name, (valu, info) in props.items():
1496
+ for name, (prop, valu, info) in props.items():
1522
1497
  await proto.set(name, valu, norminfo=info)
1523
1498
 
1524
- return await self.getNodeByBuid(proto.buid)
1499
+ return proto.valu
1500
+
1501
+ async def _normGuidNodeDict(self, form, vals, props=None):
1502
+
1503
+ if props is None:
1504
+ props = {}
1505
+
1506
+ trycast = vals.pop('$try', False)
1507
+ addprops = vals.pop('$props', None)
1508
+
1509
+ if not vals:
1510
+ mesg = f'No values provided for form {form.full}'
1511
+ raise s_exc.BadTypeValu(mesg=mesg)
1512
+
1513
+ props |= await self._normGuidNodeProps(form, props)
1525
1514
 
1526
- def _normGuidNodeDict(self, form, props):
1515
+ if addprops:
1516
+ props |= await self._normGuidNodeProps(form, addprops, trycast=trycast)
1517
+
1518
+ norms = await self._normGuidNodeProps(form, vals)
1519
+
1520
+ return norms, props
1521
+
1522
+ async def _normGuidNodeProps(self, form, props, trycast=False):
1527
1523
 
1528
1524
  norms = {}
1529
- proplist = []
1530
1525
 
1531
- for name, valu in props.items():
1526
+ for name, valu in list(props.items()):
1527
+ prop = form.reqProp(name)
1528
+
1529
+ if isinstance(valu, dict) and isinstance(prop.type, s_types.Guid):
1530
+ pform = self.core.model.reqForm(prop.type.name)
1531
+ gnorm, gprop = await self._normGuidNodeDict(pform, valu)
1532
+ norms[name] = (pform, gnorm, gprop)
1533
+ continue
1532
1534
 
1533
1535
  try:
1534
- prop = form.reqProp(name)
1535
- norm, norminfo = prop.type.norm(valu)
1536
+ norms[name] = (prop, *prop.type.norm(valu))
1536
1537
 
1537
- norms[name] = (prop, norm, norminfo)
1538
- proplist.append((name, norm))
1539
1538
  except s_exc.BadTypeValu as e:
1540
- mesg = e.get('mesg')
1541
- e.update({
1542
- 'prop': name,
1543
- 'form': form.name,
1544
- 'mesg': f'Bad value for prop {form.name}:{name}: {mesg}',
1545
- })
1546
- raise e
1547
-
1548
- proplist.sort()
1539
+ if not trycast:
1540
+ if 'prop' not in e.errinfo:
1541
+ mesg = e.get('mesg')
1542
+ e.update({
1543
+ 'prop': name,
1544
+ 'form': form.name,
1545
+ 'mesg': f'Bad value for prop {form.name}:{name}: {mesg}',
1546
+ })
1547
+ raise e
1549
1548
 
1550
- return norms, proplist
1549
+ return norms
1551
1550
 
1552
1551
  async def _getGuidNodeByDict(self, form, props):
1553
- norms, proplist = self._normGuidNodeDict(form, props)
1554
- return await self._getGuidNodeByNorms(form, s_common.guid(proplist), norms)
1552
+ norms, _ = await self._normGuidNodeDict(form, props)
1553
+ return await self._getGuidNodeByNorms(form, norms)
1554
+
1555
+ async def _getGuidNodeByNorms(self, form, norms):
1555
1556
 
1556
- async def _getGuidNodeByNorms(self, form, iden, norms):
1557
+ proplist = []
1558
+ for name, info in norms.items():
1559
+ if info[0].isform:
1560
+ if (node := await self._getGuidNodeByNorms(*info[:2])) is None:
1561
+ return
1562
+ valu = node.ndef[1]
1563
+ norms[name] = (form.prop(name), valu, {})
1564
+ proplist.append((name, valu))
1565
+ else:
1566
+ proplist.append((name, info[1]))
1557
1567
 
1558
1568
  # check first for an exact match via our same deconf strategy
1569
+ proplist.sort()
1559
1570
 
1560
- node = await self.getNodeByNdef((form.full, iden))
1571
+ node = await self.getNodeByNdef((form.full, s_common.guid(proplist)))
1561
1572
  if node is not None:
1562
1573
 
1563
1574
  # ensure we still match the property deconf criteria
synapse/lib/storm.py CHANGED
@@ -1454,7 +1454,8 @@ class StormDmon(s_base.Base):
1454
1454
  viewiden = opts.get('view')
1455
1455
 
1456
1456
  info = {'iden': self.iden, 'name': self.ddef.get('name', 'storm dmon'), 'view': viewiden}
1457
- await self.core.boss.promote('storm:dmon', user=self.user, info=info)
1457
+
1458
+ await self.core.boss.promote('storm:dmon', user=self.user, info=info, background=True)
1458
1459
 
1459
1460
  def dmonPrint(evnt):
1460
1461
  self._runLogAdd(evnt)
@@ -4,6 +4,7 @@ import aioimaplib
4
4
 
5
5
  import synapse.exc as s_exc
6
6
  import synapse.common as s_common
7
+ import synapse.lib.coro as s_coro
7
8
  import synapse.lib.stormtypes as s_stormtypes
8
9
 
9
10
  async def run_imap_coro(coro):
@@ -88,8 +89,8 @@ class ImapLib(s_stormtypes.Lib):
88
89
  imap_cli = aioimaplib.IMAP4(host=host, port=port, timeout=timeout)
89
90
 
90
91
  async def fini():
91
- # call protocol.logout() so fini() doesn't hang
92
- await s_common.wait_for(imap_cli.protocol.logout(), 5)
92
+ # call protocol.logout() via a background task
93
+ s_coro.create_task(s_common.wait_for(imap_cli.protocol.logout(), 5))
93
94
 
94
95
  self.runt.snap.onfini(fini)
95
96
 
@@ -37,6 +37,7 @@ class LibSpooled(s_stormtypes.Lib):
37
37
  async def _methSet(self, *vals):
38
38
  core = self.runt.snap.core
39
39
  spool = await s_spooled.Set.anit(dirn=core.dirn, cell=core, size=1000)
40
+ self.runt.snap.onfini(spool)
40
41
 
41
42
  valu = list(vals)
42
43
  for item in valu:
synapse/lib/task.py CHANGED
@@ -22,6 +22,7 @@ class Task(s_base.Base):
22
22
  info = {}
23
23
 
24
24
  self.boss = boss
25
+ self.background = False
25
26
 
26
27
  task._syn_task = self
27
28
 
synapse/lib/version.py CHANGED
@@ -223,6 +223,6 @@ def reqVersion(valu, reqver,
223
223
  ##############################################################################
224
224
  # The following are touched during the release process by bumpversion.
225
225
  # Do not modify these directly.
226
- version = (2, 213, 0)
226
+ version = (2, 214, 0)
227
227
  verstring = '.'.join([str(x) for x in version])
228
- commit = 'e3d843a470b137e9d2094b69a7878101afb4f8b1'
228
+ commit = '41e2ed0599236256e9452b8afeb152660e68e2c2'
synapse/models/inet.py CHANGED
@@ -1780,6 +1780,8 @@ class InetModule(s_module.CoreModule):
1780
1780
  ('remover', ('inet:service:account', {}), {
1781
1781
  'doc': 'The service account which removed or decommissioned the {service:base}.'}),
1782
1782
 
1783
+ ('app', ('inet:service:app', {}), {
1784
+ 'doc': 'The app which contains the {service:base}.'}),
1783
1785
  ),
1784
1786
  }),
1785
1787
 
@@ -3748,6 +3750,9 @@ class InetModule(s_module.CoreModule):
3748
3750
 
3749
3751
  ('tenant', ('inet:service:tenant', {}), {
3750
3752
  'doc': 'The tenant which contains the instance.'}),
3753
+
3754
+ ('app', ('inet:service:app', {}), {
3755
+ 'doc': 'The app which contains the instance.'}),
3751
3756
  )),
3752
3757
 
3753
3758
  ('inet:service:app', {}, (
@@ -0,0 +1,15 @@
1
+ :tocdepth: 2
2
+
3
+ :orphan:
4
+
5
+ .. highlight:: none
6
+ .. storm-cortex:: default
7
+
8
+ Bar
9
+ ---
10
+
11
+ A wild node appears!
12
+
13
+ .. storm-cli:: [inet:asn=1]
14
+
15
+ Words!
@@ -0,0 +1,4 @@
1
+ Hello world
2
+ -----------
3
+
4
+ Words
@@ -0,0 +1,5 @@
1
+ $lib.debug = $cmdopts.debug
2
+
3
+ $lib.print('Testcmd!')
4
+
5
+ if $lib.debug { $lib.print('Debug enabled!') }
@@ -0,0 +1,69 @@
1
+ name: testpkg
2
+ version: 1.2.3
3
+ synapse_version: ">=2.64.0,<3.0.0"
4
+
5
+ genopts:
6
+ dotstorm: true
7
+
8
+ author:
9
+ url: https://vertex.link
10
+ name: The Vertex Project, LLC.
11
+
12
+ desc: The test package does things
13
+
14
+ docs:
15
+ - title: Foo
16
+ path: docs/_build/foo.md
17
+ - title: Bar
18
+ path: docs/_build/bar.md
19
+ - title: Package Documentation
20
+ path: docs/_build/stormpackage.md
21
+
22
+ modules:
23
+ - name: testmod
24
+ - name: apimod
25
+ apidefs:
26
+ - name: search
27
+ desc: |
28
+ Execute a search
29
+
30
+ This API will foo the bar.
31
+
32
+ Examples:
33
+ Foo the ``bar``::
34
+
35
+ yield $lib.import(apimod).search(bar)
36
+
37
+ Baz the bam::
38
+
39
+ yield $lib.import(apimod).search(bam)
40
+
41
+ type:
42
+ type: function
43
+ args:
44
+ - { name: text, type: str, desc: "The text." }
45
+ - { name: mintime, type: [str, int], desc: "The mintime.", default: "-30days" }
46
+ - { name: foo, type: str, desc: "The foo." }
47
+ - { name: bar, type: str, desc: "The bar." }
48
+ - { name: baz, type: str, desc: "The baz." }
49
+ returns:
50
+ name: yields
51
+ type: node
52
+ desc: Yields it:dev:str nodes.
53
+ - name: status
54
+ desc: Get the status of the foo.
55
+ type:
56
+ type: function
57
+ returns:
58
+ type: dict
59
+ desc: A status dictionary.
60
+
61
+ commands:
62
+ - name: testcmd
63
+ descr: |
64
+ A testcmd!
65
+ cmdargs:
66
+ - - --debug
67
+ - default: false
68
+ action: store_true
69
+ help: Show verbose debug output.
@@ -5785,6 +5785,12 @@ class CortexBasicTest(s_t_utils.SynTest):
5785
5785
  ddef = await core01.callStorm('return($lib.dmon.get($iden))', opts=opts)
5786
5786
  self.none(ddef)
5787
5787
 
5788
+ await core00.callStorm('queue.del hehe')
5789
+ await core01.sync()
5790
+
5791
+ self.none(await core00.getAuthGate('queue:hehe'))
5792
+ self.none(await core01.getAuthGate('queue:hehe'))
5793
+
5788
5794
  # now lets start up in the opposite order...
5789
5795
  async with self.getTestCore(dirn=path01, conf=core01conf) as core01:
5790
5796
 
@@ -5889,7 +5895,7 @@ class CortexBasicTest(s_t_utils.SynTest):
5889
5895
 
5890
5896
  # consumer offline
5891
5897
  await asyncio.sleep(0)
5892
- await self.asyncraises(ConnectionRefusedError, core00.callStorm(strim, opts=opts))
5898
+ await self.asyncraises(s_exc.LinkErr, core00.callStorm(strim, opts=opts))
5893
5899
 
5894
5900
  # admin can still cull and break the mirror
5895
5901
  await core00.nodes('[ inet:ipv4=127.0.0.1/28 ]')
@@ -8478,6 +8484,14 @@ class CortexBasicTest(s_t_utils.SynTest):
8478
8484
  self.eq(msgs[1].get('hash'), qhash)
8479
8485
  self.eq(msgs[1].get('pool:from'), f'00.core.{ahanet}')
8480
8486
 
8487
+ with self.getLoggerStream('synapse') as stream:
8488
+ core01.boss.is_shutdown = True
8489
+ self.stormHasNoWarnErr(await core00.stormlist('inet:asn=0'))
8490
+ core01.boss.is_shutdown = False
8491
+
8492
+ stream.seek(0)
8493
+ self.isin('Proxy for pool mirror [01.core.synapse] is shutting down. Skipping.', stream.read())
8494
+
8481
8495
  with patch('synapse.cortex.CoreApi.getNexsIndx', _hang):
8482
8496
 
8483
8497
  with self.getLoggerStream('synapse') as stream:
@@ -8761,3 +8775,8 @@ class CortexBasicTest(s_t_utils.SynTest):
8761
8775
  self.eq(core._test_post_service_storage_index, offs)
8762
8776
  self.eq(core._test_pre_nexus_index, offs)
8763
8777
  self.ge(core._test_post_nexus_index, core._test_pre_nexus_index)
8778
+
8779
+ async def test_cortex_queue_mirror_authgates(self):
8780
+ async with self.getRegrCore('2.213.0-queue-authgates') as core:
8781
+ self.nn(await core.getAuthGate('queue:stillhere'))
8782
+ self.none(await core.getAuthGate('queue:authtest'))
@@ -98,7 +98,7 @@ class DaemonTest(s_t_utils.SynTest):
98
98
 
99
99
  # Invalid data casues a link to fail on rx
100
100
  async with await prox.getPoolLink() as link:
101
- with self.getAsyncLoggerStream('synapse.lib.link', 'rx error') as stream:
101
+ with self.getAsyncLoggerStream('synapse.lib.link', 'rx closed unexpectedly') as stream:
102
102
  byts = b'\x16\x03\x01\x02\x00\x01\x00\x01\xfc\x03\x03\xa6\xa3D\xd5\xdf%\xac\xa9\x92\xc3'
103
103
  await link.send(byts)
104
104
  self.true(await stream.wait(timeout=6))
synapse/tests/test_exc.py CHANGED
@@ -54,3 +54,9 @@ class ExcTest(s_t_utils.SynTest):
54
54
 
55
55
  with self.raises(s_exc.BadArg):
56
56
  s_exc.StormRaise(mesg='newp')
57
+
58
+ async def test_reprexc(self):
59
+ exc = s_exc.SynErr(mesg='woot')
60
+ self.eq('woot', s_exc.reprexc(exc))
61
+ self.eq('ValueError()', s_exc.reprexc(ValueError()))
62
+ self.eq("ValueError('woot')", s_exc.reprexc(ValueError('woot')))