synapse 2.176.0__py311-none-any.whl → 2.178.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/axon.py +24 -9
- synapse/cortex.py +337 -172
- synapse/cryotank.py +46 -37
- synapse/datamodel.py +17 -4
- synapse/exc.py +19 -0
- synapse/lib/agenda.py +7 -13
- synapse/lib/aha.py +361 -88
- synapse/lib/auth.py +1520 -0
- synapse/lib/base.py +27 -9
- synapse/lib/cell.py +422 -163
- synapse/lib/config.py +15 -11
- synapse/lib/coro.py +13 -0
- synapse/lib/grammar.py +5 -0
- synapse/lib/hive.py +24 -3
- synapse/lib/hiveauth.py +6 -32
- synapse/lib/layer.py +7 -9
- synapse/lib/link.py +22 -18
- synapse/lib/lmdbslab.py +152 -3
- synapse/lib/modelrev.py +1 -1
- synapse/lib/nexus.py +24 -12
- synapse/lib/schemas.py +136 -0
- synapse/lib/storm.py +61 -29
- synapse/lib/stormlib/aha.py +1 -1
- synapse/lib/stormlib/auth.py +185 -10
- synapse/lib/stormlib/cortex.py +16 -5
- synapse/lib/stormlib/gen.py +80 -0
- synapse/lib/stormlib/imap.py +6 -2
- synapse/lib/stormlib/model.py +55 -0
- synapse/lib/stormlib/modelext.py +60 -0
- synapse/lib/stormlib/smtp.py +12 -2
- synapse/lib/stormlib/tabular.py +212 -0
- synapse/lib/stormtypes.py +14 -1
- synapse/lib/trigger.py +1 -1
- synapse/lib/version.py +2 -2
- synapse/lib/view.py +55 -28
- synapse/models/base.py +7 -0
- synapse/models/biz.py +4 -0
- synapse/models/files.py +8 -1
- synapse/models/inet.py +8 -0
- synapse/telepath.py +32 -17
- synapse/tests/files/aha/certs/cas/synapse.crt +28 -0
- synapse/tests/files/aha/certs/cas/synapse.key +51 -0
- synapse/tests/files/aha/certs/hosts/00.aha.loop.vertex.link.crt +30 -0
- synapse/tests/files/aha/certs/hosts/00.aha.loop.vertex.link.key +51 -0
- synapse/tests/files/aha/certs/users/root@synapse.crt +29 -0
- synapse/tests/files/aha/certs/users/root@synapse.key +51 -0
- synapse/tests/files/changelog/model_2.176.0_16ee721a6b7221344eaf946c3ab4602dda546b1a.yaml.gz +0 -0
- synapse/tests/files/changelog/model_2.176.0_2a25c58bbd344716cd7cbc3f4304d8925b0f4ef2.yaml.gz +0 -0
- synapse/tests/files/rstorm/testsvc.py +1 -1
- synapse/tests/test_axon.py +8 -5
- synapse/tests/test_cortex.py +149 -141
- synapse/tests/test_cryotank.py +4 -4
- synapse/tests/test_datamodel.py +7 -0
- synapse/tests/test_lib_agenda.py +10 -3
- synapse/tests/test_lib_aha.py +336 -490
- synapse/tests/{test_lib_hiveauth.py → test_lib_auth.py} +314 -11
- synapse/tests/test_lib_base.py +20 -0
- synapse/tests/test_lib_cell.py +210 -30
- synapse/tests/test_lib_config.py +4 -3
- synapse/tests/test_lib_httpapi.py +18 -14
- synapse/tests/test_lib_layer.py +33 -33
- synapse/tests/test_lib_link.py +42 -1
- synapse/tests/test_lib_lmdbslab.py +68 -0
- synapse/tests/test_lib_nexus.py +12 -4
- synapse/tests/test_lib_node.py +0 -7
- synapse/tests/test_lib_storm.py +45 -0
- synapse/tests/test_lib_stormlib_aha.py +35 -36
- synapse/tests/test_lib_stormlib_auth.py +21 -0
- synapse/tests/test_lib_stormlib_cell.py +4 -15
- synapse/tests/test_lib_stormlib_cortex.py +12 -12
- synapse/tests/test_lib_stormlib_gen.py +99 -0
- synapse/tests/test_lib_stormlib_imap.py +14 -3
- synapse/tests/test_lib_stormlib_model.py +108 -0
- synapse/tests/test_lib_stormlib_modelext.py +64 -0
- synapse/tests/test_lib_stormlib_smtp.py +51 -0
- synapse/tests/test_lib_stormlib_tabular.py +226 -0
- synapse/tests/test_lib_stormsvc.py +4 -1
- synapse/tests/test_lib_stormtypes.py +10 -0
- synapse/tests/test_model_base.py +3 -0
- synapse/tests/test_model_biz.py +3 -0
- synapse/tests/test_model_files.py +12 -2
- synapse/tests/test_model_inet.py +24 -0
- synapse/tests/test_tools_aha.py +78 -101
- synapse/tests/test_tools_changelog.py +196 -0
- synapse/tests/test_tools_healthcheck.py +4 -3
- synapse/tests/utils.py +87 -121
- synapse/tools/aha/clone.py +50 -0
- synapse/tools/aha/enroll.py +2 -1
- synapse/tools/backup.py +2 -2
- synapse/tools/changelog.py +776 -15
- {synapse-2.176.0.dist-info → synapse-2.178.0.dist-info}/METADATA +48 -48
- {synapse-2.176.0.dist-info → synapse-2.178.0.dist-info}/RECORD +95 -82
- {synapse-2.176.0.dist-info → synapse-2.178.0.dist-info}/WHEEL +1 -1
- {synapse-2.176.0.dist-info → synapse-2.178.0.dist-info}/LICENSE +0 -0
- {synapse-2.176.0.dist-info → synapse-2.178.0.dist-info}/top_level.txt +0 -0
synapse/lib/config.py
CHANGED
|
@@ -392,10 +392,16 @@ class Config(c_abc.MutableMapping):
|
|
|
392
392
|
else:
|
|
393
393
|
return
|
|
394
394
|
|
|
395
|
-
def reqConfValu(self, key):
|
|
395
|
+
def reqConfValu(self, key): # pragma: no cover
|
|
396
396
|
'''
|
|
397
|
-
|
|
398
|
-
|
|
397
|
+
Deprecated. Use ``req(key)`` API instead.
|
|
398
|
+
'''
|
|
399
|
+
s_common.deprecated('Config.reqConfValu(), use req() instead.')
|
|
400
|
+
return self.req(key)
|
|
401
|
+
|
|
402
|
+
def req(self, key):
|
|
403
|
+
'''
|
|
404
|
+
Get a configuration value. If that value is not present in the schema or is not set, then raise an exception.
|
|
399
405
|
|
|
400
406
|
Args:
|
|
401
407
|
key (str): The key to require.
|
|
@@ -403,17 +409,15 @@ class Config(c_abc.MutableMapping):
|
|
|
403
409
|
Returns:
|
|
404
410
|
The requested value.
|
|
405
411
|
'''
|
|
406
|
-
# Ensure that the key is in self.json_schema
|
|
407
412
|
if key not in self.json_schema.get('properties', {}):
|
|
408
|
-
raise s_exc.BadArg(mesg='
|
|
409
|
-
|
|
413
|
+
raise s_exc.BadArg(mesg=f'The {key} configuration option is not present in the configuration schema.',
|
|
414
|
+
name=key)
|
|
410
415
|
|
|
411
|
-
|
|
412
|
-
if
|
|
413
|
-
|
|
414
|
-
key=key)
|
|
416
|
+
valu = self.conf.get(key, s_common.novalu)
|
|
417
|
+
if valu is not s_common.novalu:
|
|
418
|
+
return valu
|
|
415
419
|
|
|
416
|
-
|
|
420
|
+
raise s_exc.NeedConfValu(mesg=f'The {key} configuration option is required.', name=key)
|
|
417
421
|
|
|
418
422
|
def reqKeyValid(self, key, value):
|
|
419
423
|
'''
|
synapse/lib/coro.py
CHANGED
|
@@ -148,6 +148,19 @@ async def ornot(func, *args, **kwargs):
|
|
|
148
148
|
return await retn
|
|
149
149
|
return retn
|
|
150
150
|
|
|
151
|
+
bgtasks = set()
|
|
152
|
+
def create_task(coro):
|
|
153
|
+
|
|
154
|
+
task = asyncio.get_running_loop().create_task(coro)
|
|
155
|
+
bgtasks.add(task)
|
|
156
|
+
|
|
157
|
+
def done(t):
|
|
158
|
+
bgtasks.remove(t)
|
|
159
|
+
|
|
160
|
+
task.add_done_callback(done)
|
|
161
|
+
|
|
162
|
+
return task
|
|
163
|
+
|
|
151
164
|
class GenrHelp:
|
|
152
165
|
|
|
153
166
|
def __init__(self, genr):
|
synapse/lib/grammar.py
CHANGED
|
@@ -15,6 +15,8 @@ formrestr = r'[a-z_][a-z0-9_]*(:[a-z0-9_]+)+'
|
|
|
15
15
|
formre = regex.compile(formrestr)
|
|
16
16
|
tagrestr = r'(\w+\.)*\w+'
|
|
17
17
|
tagre = regex.compile(tagrestr)
|
|
18
|
+
edgerestr = r'[\w\.:]{1,200}'
|
|
19
|
+
edgere = regex.compile(edgerestr)
|
|
18
20
|
basepropnopivpropstr = r'[a-z_][a-z0-9_]*(?:(\:|\.)[a-z_][a-z0-9_]*)*'
|
|
19
21
|
basepropnopivpropre = regex.compile(basepropnopivpropstr)
|
|
20
22
|
|
|
@@ -38,6 +40,9 @@ def isFormName(name):
|
|
|
38
40
|
def isBasePropNoPivprop(name):
|
|
39
41
|
return basepropnopivpropre.fullmatch(name) is not None
|
|
40
42
|
|
|
43
|
+
def isEdgeVerb(verb):
|
|
44
|
+
return edgere.fullmatch(verb) is not None
|
|
45
|
+
|
|
41
46
|
floatre = regex.compile(r'\s*-?\d+(\.\d+)?([eE][-+]\d+)?')
|
|
42
47
|
|
|
43
48
|
def parse_float(text, off):
|
synapse/lib/hive.py
CHANGED
|
@@ -91,7 +91,7 @@ class Hive(s_nexus.Pusher, s_telepath.Aware):
|
|
|
91
91
|
An optionally persistent atomically accessed tree which implements
|
|
92
92
|
primitives for use in making distributed/clustered services.
|
|
93
93
|
'''
|
|
94
|
-
async def __anit__(self, conf=None, nexsroot=None):
|
|
94
|
+
async def __anit__(self, conf=None, nexsroot=None, cell=None):
|
|
95
95
|
|
|
96
96
|
await s_nexus.Pusher.__anit__(self, 'hive', nexsroot=nexsroot)
|
|
97
97
|
|
|
@@ -100,6 +100,7 @@ class Hive(s_nexus.Pusher, s_telepath.Aware):
|
|
|
100
100
|
if conf is None:
|
|
101
101
|
conf = {}
|
|
102
102
|
|
|
103
|
+
self.cell = cell
|
|
103
104
|
self.conf = conf
|
|
104
105
|
self.nodes = {} # full=Node()
|
|
105
106
|
|
|
@@ -340,6 +341,18 @@ class Hive(s_nexus.Pusher, s_telepath.Aware):
|
|
|
340
341
|
|
|
341
342
|
@s_nexus.Pusher.onPush('hive:set')
|
|
342
343
|
async def _set(self, full, valu):
|
|
344
|
+
if self.cell is not None:
|
|
345
|
+
if full[0] == 'auth':
|
|
346
|
+
if len(full) == 5:
|
|
347
|
+
_, _, iden, dtyp, name = full
|
|
348
|
+
if dtyp == 'vars':
|
|
349
|
+
await self.cell.auth._hndlsetUserVarValu(iden, name, valu)
|
|
350
|
+
elif dtyp == 'profile':
|
|
351
|
+
await self.cell.auth._hndlsetUserProfileValu(iden, name, valu)
|
|
352
|
+
|
|
353
|
+
elif full[0] == 'cellvers':
|
|
354
|
+
self.cell.setCellVers(full[-1], valu, nexs=False)
|
|
355
|
+
|
|
343
356
|
node = await self._getHiveNode(full)
|
|
344
357
|
|
|
345
358
|
oldv = node.valu
|
|
@@ -377,6 +390,14 @@ class Hive(s_nexus.Pusher, s_telepath.Aware):
|
|
|
377
390
|
@s_nexus.Pusher.onPush('hive:pop')
|
|
378
391
|
async def _pop(self, full):
|
|
379
392
|
|
|
393
|
+
if self.cell is not None and full[0] == 'auth':
|
|
394
|
+
if len(full) == 5:
|
|
395
|
+
_, _, iden, dtyp, name = full
|
|
396
|
+
if dtyp == 'vars':
|
|
397
|
+
await self.cell.auth._hndlpopUserVarValu(iden, name)
|
|
398
|
+
elif dtyp == 'profile':
|
|
399
|
+
await self.cell.auth._hndlpopUserProfileValu(iden, name)
|
|
400
|
+
|
|
380
401
|
node = self.nodes.get(full)
|
|
381
402
|
if node is None:
|
|
382
403
|
return
|
|
@@ -434,10 +455,10 @@ class Hive(s_nexus.Pusher, s_telepath.Aware):
|
|
|
434
455
|
|
|
435
456
|
class SlabHive(Hive):
|
|
436
457
|
|
|
437
|
-
async def __anit__(self, slab, db=None, conf=None, nexsroot=None):
|
|
458
|
+
async def __anit__(self, slab, db=None, conf=None, nexsroot=None, cell=None):
|
|
438
459
|
self.db = db
|
|
439
460
|
self.slab = slab
|
|
440
|
-
await Hive.__anit__(self, conf=conf, nexsroot=nexsroot)
|
|
461
|
+
await Hive.__anit__(self, conf=conf, nexsroot=nexsroot, cell=cell)
|
|
441
462
|
self.slab.onfini(self.fini)
|
|
442
463
|
|
|
443
464
|
async def _storLoadHive(self):
|
synapse/lib/hiveauth.py
CHANGED
|
@@ -277,7 +277,6 @@ class Auth(s_nexus.Pusher):
|
|
|
277
277
|
|
|
278
278
|
return user
|
|
279
279
|
|
|
280
|
-
@s_nexus.Pusher.onPushAuto('user:name')
|
|
281
280
|
async def setUserName(self, iden, name):
|
|
282
281
|
if not isinstance(name, str):
|
|
283
282
|
raise s_exc.BadArg(mesg='setUserName() name must be a string')
|
|
@@ -302,7 +301,6 @@ class Auth(s_nexus.Pusher):
|
|
|
302
301
|
}
|
|
303
302
|
await self.feedBeholder('user:name', beheld)
|
|
304
303
|
|
|
305
|
-
@s_nexus.Pusher.onPushAuto('role:name')
|
|
306
304
|
async def setRoleName(self, iden, name):
|
|
307
305
|
if not isinstance(name, str):
|
|
308
306
|
raise s_exc.BadArg(mesg='setRoleName() name must be a string')
|
|
@@ -346,7 +344,6 @@ class Auth(s_nexus.Pusher):
|
|
|
346
344
|
|
|
347
345
|
await self.fire('cell:beholder', **behold)
|
|
348
346
|
|
|
349
|
-
@s_nexus.Pusher.onPushAuto('user:info')
|
|
350
347
|
async def setUserInfo(self, iden, name, valu, gateiden=None, logged=True, mesg=None):
|
|
351
348
|
|
|
352
349
|
user = await self.reqUser(iden)
|
|
@@ -373,7 +370,6 @@ class Auth(s_nexus.Pusher):
|
|
|
373
370
|
# since any user info *may* effect auth
|
|
374
371
|
user.clearAuthCache()
|
|
375
372
|
|
|
376
|
-
@s_nexus.Pusher.onPushAuto('role:info')
|
|
377
373
|
async def setRoleInfo(self, iden, name, valu, gateiden=None, logged=True, mesg=None):
|
|
378
374
|
role = await self.reqRole(iden)
|
|
379
375
|
|
|
@@ -528,7 +524,6 @@ class Auth(s_nexus.Pusher):
|
|
|
528
524
|
|
|
529
525
|
return user
|
|
530
526
|
|
|
531
|
-
@s_nexus.Pusher.onPush('user:add')
|
|
532
527
|
async def _addUser(self, iden, name):
|
|
533
528
|
|
|
534
529
|
user = self.usersbyname.get(name)
|
|
@@ -554,7 +549,6 @@ class Auth(s_nexus.Pusher):
|
|
|
554
549
|
|
|
555
550
|
return self.role(iden)
|
|
556
551
|
|
|
557
|
-
@s_nexus.Pusher.onPush('role:add')
|
|
558
552
|
async def _addRole(self, iden, name):
|
|
559
553
|
|
|
560
554
|
role = self.rolesbyname.get(name)
|
|
@@ -574,7 +568,6 @@ class Auth(s_nexus.Pusher):
|
|
|
574
568
|
await self.reqUser(iden)
|
|
575
569
|
return await self._push('user:del', iden)
|
|
576
570
|
|
|
577
|
-
@s_nexus.Pusher.onPush('user:del')
|
|
578
571
|
async def _delUser(self, iden):
|
|
579
572
|
|
|
580
573
|
if iden == self.rootuser.iden:
|
|
@@ -608,7 +601,6 @@ class Auth(s_nexus.Pusher):
|
|
|
608
601
|
await self.reqRole(iden)
|
|
609
602
|
return await self._push('role:del', iden)
|
|
610
603
|
|
|
611
|
-
@s_nexus.Pusher.onPush('role:del')
|
|
612
604
|
async def _delRole(self, iden):
|
|
613
605
|
|
|
614
606
|
if iden == self.allrole.iden:
|
|
@@ -838,10 +830,7 @@ class HiveRole(HiveRuler):
|
|
|
838
830
|
}
|
|
839
831
|
|
|
840
832
|
async def _setRulrInfo(self, name, valu, gateiden=None, nexs=True, mesg=None):
|
|
841
|
-
|
|
842
|
-
return await self.auth.setRoleInfo(self.iden, name, valu, gateiden=gateiden, mesg=mesg)
|
|
843
|
-
else:
|
|
844
|
-
return await self.auth._hndlsetRoleInfo(self.iden, name, valu, gateiden=gateiden, logged=nexs, mesg=mesg)
|
|
833
|
+
return await self.auth.setRoleInfo(self.iden, name, valu, gateiden=gateiden, logged=nexs, mesg=mesg)
|
|
845
834
|
|
|
846
835
|
async def setName(self, name):
|
|
847
836
|
return await self.auth.setRoleName(self.iden, name)
|
|
@@ -929,10 +918,7 @@ class HiveUser(HiveRuler):
|
|
|
929
918
|
}
|
|
930
919
|
|
|
931
920
|
async def _setRulrInfo(self, name, valu, gateiden=None, nexs=True, mesg=None):
|
|
932
|
-
|
|
933
|
-
return await self.auth.setUserInfo(self.iden, name, valu, gateiden=gateiden, mesg=mesg)
|
|
934
|
-
else:
|
|
935
|
-
return await self.auth._hndlsetUserInfo(self.iden, name, valu, gateiden=gateiden, logged=nexs, mesg=mesg)
|
|
921
|
+
return await self.auth.setUserInfo(self.iden, name, valu, gateiden=gateiden, logged=nexs, mesg=mesg)
|
|
936
922
|
|
|
937
923
|
async def setName(self, name):
|
|
938
924
|
return await self.auth.setUserName(self.iden, name)
|
|
@@ -1232,10 +1218,7 @@ class HiveUser(HiveRuler):
|
|
|
1232
1218
|
|
|
1233
1219
|
roles.remove(role.iden)
|
|
1234
1220
|
mesg = {'name': 'role:revoke', 'iden': self.iden, 'role': role.pack()}
|
|
1235
|
-
|
|
1236
|
-
await self.auth.setUserInfo(self.iden, 'roles', roles, mesg=mesg)
|
|
1237
|
-
else:
|
|
1238
|
-
await self.auth._hndlsetUserInfo(self.iden, 'roles', roles, logged=nexs, mesg=mesg)
|
|
1221
|
+
await self.auth.setUserInfo(self.iden, 'roles', roles, logged=nexs, mesg=mesg)
|
|
1239
1222
|
|
|
1240
1223
|
def isLocked(self):
|
|
1241
1224
|
return self.info.get('locked')
|
|
@@ -1271,18 +1254,12 @@ class HiveUser(HiveRuler):
|
|
|
1271
1254
|
async def setAdmin(self, admin, gateiden=None, logged=True):
|
|
1272
1255
|
if not isinstance(admin, bool):
|
|
1273
1256
|
raise s_exc.BadArg(mesg='setAdmin requires a boolean')
|
|
1274
|
-
|
|
1275
|
-
await self.auth.setUserInfo(self.iden, 'admin', admin, gateiden=gateiden)
|
|
1276
|
-
else:
|
|
1277
|
-
await self.auth._hndlsetUserInfo(self.iden, 'admin', admin, gateiden=gateiden, logged=logged)
|
|
1257
|
+
await self.auth.setUserInfo(self.iden, 'admin', admin, gateiden=gateiden, logged=logged)
|
|
1278
1258
|
|
|
1279
1259
|
async def setLocked(self, locked, logged=True):
|
|
1280
1260
|
if not isinstance(locked, bool):
|
|
1281
1261
|
raise s_exc.BadArg(mesg='setLocked requires a boolean')
|
|
1282
|
-
|
|
1283
|
-
await self.auth.setUserInfo(self.iden, 'locked', locked)
|
|
1284
|
-
else:
|
|
1285
|
-
await self.auth._hndlsetUserInfo(self.iden, 'locked', locked, logged=logged)
|
|
1262
|
+
await self.auth.setUserInfo(self.iden, 'locked', locked, logged=logged)
|
|
1286
1263
|
|
|
1287
1264
|
async def setArchived(self, archived):
|
|
1288
1265
|
if not isinstance(archived, bool):
|
|
@@ -1347,7 +1324,4 @@ class HiveUser(HiveRuler):
|
|
|
1347
1324
|
shadow = await s_passwd.getShadowV2(passwd=passwd)
|
|
1348
1325
|
else:
|
|
1349
1326
|
raise s_exc.BadArg(mesg='Password must be a string')
|
|
1350
|
-
|
|
1351
|
-
await self.auth.setUserInfo(self.iden, 'passwd', shadow)
|
|
1352
|
-
else:
|
|
1353
|
-
await self.auth._hndlsetUserInfo(self.iden, 'passwd', shadow, logged=nexs)
|
|
1327
|
+
await self.auth.setUserInfo(self.iden, 'passwd', shadow, logged=nexs)
|
synapse/lib/layer.py
CHANGED
|
@@ -1431,9 +1431,6 @@ class Layer(s_nexus.Pusher):
|
|
|
1431
1431
|
self.growsize = self.layrinfo.get('growsize')
|
|
1432
1432
|
self.logedits = self.layrinfo.get('logedits')
|
|
1433
1433
|
|
|
1434
|
-
self.mapasync = core.conf.get('layer:lmdb:map_async')
|
|
1435
|
-
self.maxreplaylog = core.conf.get('layer:lmdb:max_replay_log')
|
|
1436
|
-
|
|
1437
1434
|
# slim hooks to avoid async/fire
|
|
1438
1435
|
self.nodeAddHook = None
|
|
1439
1436
|
self.nodeDelHook = None
|
|
@@ -2034,7 +2031,7 @@ class Layer(s_nexus.Pusher):
|
|
|
2034
2031
|
'stortype': stortype})
|
|
2035
2032
|
|
|
2036
2033
|
async def pack(self):
|
|
2037
|
-
ret = self.layrinfo
|
|
2034
|
+
ret = deepcopy(self.layrinfo)
|
|
2038
2035
|
if ret.get('mirror'):
|
|
2039
2036
|
ret['mirror'] = s_urlhelp.sanitizeUrl(ret['mirror'])
|
|
2040
2037
|
ret['offset'] = await self.getEditIndx()
|
|
@@ -2728,8 +2725,6 @@ class Layer(s_nexus.Pusher):
|
|
|
2728
2725
|
slabopts = {
|
|
2729
2726
|
'readahead': True,
|
|
2730
2727
|
'lockmemory': self.lockmemory,
|
|
2731
|
-
'map_async': self.mapasync,
|
|
2732
|
-
'max_replay_log': self.maxreplaylog,
|
|
2733
2728
|
}
|
|
2734
2729
|
|
|
2735
2730
|
if self.growsize is not None:
|
|
@@ -2810,9 +2805,11 @@ class Layer(s_nexus.Pusher):
|
|
|
2810
2805
|
|
|
2811
2806
|
# TODO when we can set more props, we may need to parse values.
|
|
2812
2807
|
if valu is None:
|
|
2813
|
-
|
|
2808
|
+
self.layrinfo.pop(name, None)
|
|
2814
2809
|
else:
|
|
2815
|
-
|
|
2810
|
+
self.layrinfo[name] = valu
|
|
2811
|
+
|
|
2812
|
+
self.core.layerdefs.set(self.iden, self.layrinfo)
|
|
2816
2813
|
|
|
2817
2814
|
await self.core.feedBeholder('layer:set', {'iden': self.iden, 'name': name, 'valu': valu}, gates=[self.iden])
|
|
2818
2815
|
return valu
|
|
@@ -4453,7 +4450,8 @@ class Layer(s_nexus.Pusher):
|
|
|
4453
4450
|
|
|
4454
4451
|
@s_nexus.Pusher.onPush('layer:set:modelvers')
|
|
4455
4452
|
async def _setModelVers(self, vers):
|
|
4456
|
-
|
|
4453
|
+
self.layrinfo['model:version'] = vers
|
|
4454
|
+
self.core.layerdefs.set(self.iden, self.layrinfo)
|
|
4457
4455
|
|
|
4458
4456
|
async def getStorNodes(self):
|
|
4459
4457
|
'''
|
synapse/lib/link.py
CHANGED
|
@@ -21,7 +21,7 @@ async def connect(host, port, ssl=None, hostname=None, linkinfo=None):
|
|
|
21
21
|
'''
|
|
22
22
|
Async connect and return a Link().
|
|
23
23
|
'''
|
|
24
|
-
info = {'host': host, 'port': port, 'ssl': ssl, 'hostname': hostname}
|
|
24
|
+
info = {'host': host, 'port': port, 'ssl': ssl, 'hostname': hostname, 'tls': bool(ssl)}
|
|
25
25
|
if linkinfo is not None:
|
|
26
26
|
info.update(linkinfo)
|
|
27
27
|
|
|
@@ -137,6 +137,25 @@ class Link(s_base.Base):
|
|
|
137
137
|
|
|
138
138
|
self.info = info
|
|
139
139
|
|
|
140
|
+
self._addrinfo = {}
|
|
141
|
+
# _addrinfo is populated in this order so that as first hit tls links (prod deployments)
|
|
142
|
+
# then unix links (unit tests with local sockets, container healthchecks, local tools )
|
|
143
|
+
# then tcp links ( unit tests and legacy deployments )
|
|
144
|
+
if self.info.get('tls'):
|
|
145
|
+
self._addrinfo['family'] = 'tls'
|
|
146
|
+
self._addrinfo['addr'] = self.sock.getpeername()
|
|
147
|
+
elif self.info.get('unix'):
|
|
148
|
+
self._addrinfo['family'] = 'unix'
|
|
149
|
+
# Unix sockets don't use getpeername
|
|
150
|
+
self._addrinfo['addr'] = self.sock.getsockname()
|
|
151
|
+
else:
|
|
152
|
+
self._addrinfo['family'] = 'tcp'
|
|
153
|
+
self._addrinfo['addr'] = self.sock.getpeername()
|
|
154
|
+
if self.sock.family == socket.AF_INET:
|
|
155
|
+
self._addrinfo['ipver'] = 'ipv4'
|
|
156
|
+
elif self.sock.family == socket.AF_INET6:
|
|
157
|
+
self._addrinfo['ipver'] = 'ipv6'
|
|
158
|
+
|
|
140
159
|
self.unpk = s_msgpack.Unpk()
|
|
141
160
|
|
|
142
161
|
async def fini():
|
|
@@ -145,7 +164,7 @@ class Link(s_base.Base):
|
|
|
145
164
|
self.reader._transport.abort()
|
|
146
165
|
try:
|
|
147
166
|
await self.writer.wait_closed()
|
|
148
|
-
except
|
|
167
|
+
except Exception as e:
|
|
149
168
|
logger.debug('Link error waiting on close: %s', str(e))
|
|
150
169
|
|
|
151
170
|
self.onfini(fini)
|
|
@@ -212,22 +231,7 @@ class Link(s_base.Base):
|
|
|
212
231
|
'''
|
|
213
232
|
Get a summary of address information related to the link.
|
|
214
233
|
'''
|
|
215
|
-
|
|
216
|
-
'addr': self.sock.getpeername(),
|
|
217
|
-
}
|
|
218
|
-
# Set family information
|
|
219
|
-
if self.info.get('unix'):
|
|
220
|
-
ret['family'] = 'unix'
|
|
221
|
-
# Unix sockets don't use getpeername
|
|
222
|
-
ret['addr'] = self.sock.getsockname()
|
|
223
|
-
elif self.info.get('tls'):
|
|
224
|
-
ret['family'] = 'tls'
|
|
225
|
-
# Set ipver if needed
|
|
226
|
-
if self.sock.family == socket.AF_INET:
|
|
227
|
-
ret['ipver'] = 'ipv4'
|
|
228
|
-
if self.sock.family == socket.AF_INET6:
|
|
229
|
-
ret['ipver'] = 'ipv6'
|
|
230
|
-
return ret
|
|
234
|
+
return dict(self._addrinfo)
|
|
231
235
|
|
|
232
236
|
async def send(self, byts):
|
|
233
237
|
self.writer.write(byts)
|
synapse/lib/lmdbslab.py
CHANGED
|
@@ -166,6 +166,148 @@ class SlabDict:
|
|
|
166
166
|
self.set(name, curv)
|
|
167
167
|
return curv
|
|
168
168
|
|
|
169
|
+
class SafeKeyVal:
|
|
170
|
+
'''
|
|
171
|
+
Key/value storage that does not store items in memory and ensures keys are < 512 characters in length.
|
|
172
|
+
|
|
173
|
+
Note:
|
|
174
|
+
The key size limitation includes the length of any prefixes added by
|
|
175
|
+
using getSubKeyVal().
|
|
176
|
+
'''
|
|
177
|
+
def __init__(self, slab, name, prefix=''):
|
|
178
|
+
|
|
179
|
+
self.prefix = prefix
|
|
180
|
+
self._prefix = prefix.encode('utf8')
|
|
181
|
+
self.preflen = len(self._prefix)
|
|
182
|
+
|
|
183
|
+
if self.preflen > 510:
|
|
184
|
+
mesg = 'SafeKeyVal prefix lengths must be < 511 bytes.'
|
|
185
|
+
raise s_exc.BadArg(mesg, prefix=self._prefix[:1024])
|
|
186
|
+
|
|
187
|
+
self.name = name
|
|
188
|
+
self.slab = slab
|
|
189
|
+
self.valudb = slab.initdb(name)
|
|
190
|
+
|
|
191
|
+
def getSubKeyVal(self, prefix):
|
|
192
|
+
|
|
193
|
+
if not prefix or not isinstance(prefix, str):
|
|
194
|
+
mesg = 'SafeKeyVal.getSubKeyVal() requires a string prefix of at least one character.'
|
|
195
|
+
raise s_exc.BadArg(mesg, prefix=prefix)
|
|
196
|
+
|
|
197
|
+
if self.prefix:
|
|
198
|
+
prefix = self.prefix + prefix
|
|
199
|
+
|
|
200
|
+
return SafeKeyVal(self.slab, self.name, prefix=prefix)
|
|
201
|
+
|
|
202
|
+
def reqValidName(self, name):
|
|
203
|
+
|
|
204
|
+
_name = name.encode('utf-8')
|
|
205
|
+
|
|
206
|
+
if self._prefix:
|
|
207
|
+
_name = self._prefix + _name
|
|
208
|
+
|
|
209
|
+
if len(_name) > 511:
|
|
210
|
+
maxlen = 511 - self.preflen
|
|
211
|
+
mesg = f'SafeKeyVal keys with prefix {self.prefix} must be less < {maxlen} bytes in length.'
|
|
212
|
+
raise s_exc.BadArg(mesg, prefix=self.prefix, name=name[:1024])
|
|
213
|
+
return _name
|
|
214
|
+
|
|
215
|
+
def get(self, name, defv=None):
|
|
216
|
+
'''
|
|
217
|
+
Get the value for a key.
|
|
218
|
+
|
|
219
|
+
Note:
|
|
220
|
+
This may only be used for keys < 512 characters in length.
|
|
221
|
+
'''
|
|
222
|
+
name = self.reqValidName(name)
|
|
223
|
+
|
|
224
|
+
if (byts := self.slab.get(name, db=self.valudb)) is None:
|
|
225
|
+
return defv
|
|
226
|
+
return s_msgpack.un(byts)
|
|
227
|
+
|
|
228
|
+
def set(self, name, valu):
|
|
229
|
+
|
|
230
|
+
name = self.reqValidName(name)
|
|
231
|
+
|
|
232
|
+
self.slab.put(name, s_msgpack.en(valu), db=self.valudb)
|
|
233
|
+
return valu
|
|
234
|
+
|
|
235
|
+
def pop(self, name, defv=None):
|
|
236
|
+
|
|
237
|
+
name = self.reqValidName(name)
|
|
238
|
+
|
|
239
|
+
if (byts := self.slab.pop(name, db=self.valudb)) is not None:
|
|
240
|
+
return s_msgpack.un(byts)
|
|
241
|
+
return defv
|
|
242
|
+
|
|
243
|
+
def delete(self, name):
|
|
244
|
+
'''
|
|
245
|
+
Delete a key.
|
|
246
|
+
'''
|
|
247
|
+
name = self.reqValidName(name)
|
|
248
|
+
return self.slab.delete(name, db=self.valudb)
|
|
249
|
+
|
|
250
|
+
async def truncate(self, pref=''):
|
|
251
|
+
'''
|
|
252
|
+
Delete all keys.
|
|
253
|
+
'''
|
|
254
|
+
pref = self.reqValidName(pref)
|
|
255
|
+
|
|
256
|
+
if not pref:
|
|
257
|
+
genr = self.slab.scanKeys(db=self.valudb)
|
|
258
|
+
else:
|
|
259
|
+
genr = self.slab.scanKeysByPref(pref, db=self.valudb)
|
|
260
|
+
|
|
261
|
+
for lkey in genr:
|
|
262
|
+
self.slab.delete(lkey, db=self.valudb)
|
|
263
|
+
await asyncio.sleep(0)
|
|
264
|
+
|
|
265
|
+
def items(self, pref=''):
|
|
266
|
+
|
|
267
|
+
pref = self.reqValidName(pref)
|
|
268
|
+
|
|
269
|
+
if not pref:
|
|
270
|
+
genr = self.slab.scanByFull(db=self.valudb)
|
|
271
|
+
else:
|
|
272
|
+
genr = self.slab.scanByPref(pref, db=self.valudb)
|
|
273
|
+
|
|
274
|
+
if self.prefix:
|
|
275
|
+
for lkey, byts in genr:
|
|
276
|
+
yield lkey[self.preflen:].decode('utf8'), s_msgpack.un(byts)
|
|
277
|
+
return
|
|
278
|
+
|
|
279
|
+
for lkey, byts in genr:
|
|
280
|
+
yield lkey.decode('utf8'), s_msgpack.un(byts)
|
|
281
|
+
|
|
282
|
+
def keys(self, pref=''):
|
|
283
|
+
|
|
284
|
+
pref = self.reqValidName(pref)
|
|
285
|
+
|
|
286
|
+
if not pref:
|
|
287
|
+
genr = self.slab.scanKeys(db=self.valudb)
|
|
288
|
+
else:
|
|
289
|
+
genr = self.slab.scanKeysByPref(pref, db=self.valudb)
|
|
290
|
+
|
|
291
|
+
if self.prefix:
|
|
292
|
+
for lkey in genr:
|
|
293
|
+
yield lkey[self.preflen:].decode('utf8')
|
|
294
|
+
return
|
|
295
|
+
|
|
296
|
+
for lkey in genr:
|
|
297
|
+
yield lkey.decode('utf8')
|
|
298
|
+
|
|
299
|
+
def values(self, pref=''):
|
|
300
|
+
|
|
301
|
+
pref = self.reqValidName(pref)
|
|
302
|
+
|
|
303
|
+
if not pref:
|
|
304
|
+
genr = self.slab.scanByFull(db=self.valudb)
|
|
305
|
+
else:
|
|
306
|
+
genr = self.slab.scanByPref(pref, db=self.valudb)
|
|
307
|
+
|
|
308
|
+
for lkey, byts in genr:
|
|
309
|
+
yield s_msgpack.un(byts)
|
|
310
|
+
|
|
169
311
|
class SlabAbrv:
|
|
170
312
|
'''
|
|
171
313
|
A utility for translating arbitrary bytes into fixed with id bytes
|
|
@@ -696,7 +838,7 @@ class Slab(s_base.Base):
|
|
|
696
838
|
'recovering': slab.recovering,
|
|
697
839
|
'maxsize': slab.maxsize,
|
|
698
840
|
'growsize': slab.growsize,
|
|
699
|
-
'mapasync':
|
|
841
|
+
'mapasync': True,
|
|
700
842
|
|
|
701
843
|
})
|
|
702
844
|
return retn
|
|
@@ -709,6 +851,8 @@ class Slab(s_base.Base):
|
|
|
709
851
|
kwargs.setdefault('lockmemory', False)
|
|
710
852
|
kwargs.setdefault('map_async', True)
|
|
711
853
|
|
|
854
|
+
assert kwargs.get('map_async')
|
|
855
|
+
|
|
712
856
|
opts = kwargs
|
|
713
857
|
|
|
714
858
|
self.path = path
|
|
@@ -753,8 +897,6 @@ class Slab(s_base.Base):
|
|
|
753
897
|
logger.info(f'SYN_LOCKMEM_DISABLE envar set, skipping lockmem for {self.path}')
|
|
754
898
|
self.lockmemory = False
|
|
755
899
|
|
|
756
|
-
self.mapasync = opts.setdefault('map_async', True)
|
|
757
|
-
|
|
758
900
|
self.mapsize = _mapsizeround(mapsize)
|
|
759
901
|
if self.maxsize is not None:
|
|
760
902
|
self.mapsize = min(self.mapsize, self.maxsize)
|
|
@@ -845,6 +987,13 @@ class Slab(s_base.Base):
|
|
|
845
987
|
self.onfini(mq)
|
|
846
988
|
return mq
|
|
847
989
|
|
|
990
|
+
def getSafeKeyVal(self, name, prefix='', create=True):
|
|
991
|
+
if not create and not self.dbexists(name):
|
|
992
|
+
mesg = f'Database {name=} does not exist.'
|
|
993
|
+
raise s_exc.BadArg(mesg=mesg)
|
|
994
|
+
|
|
995
|
+
return SafeKeyVal(self, name, prefix=prefix)
|
|
996
|
+
|
|
848
997
|
def statinfo(self):
|
|
849
998
|
return {
|
|
850
999
|
'locking_memory': self.locking_memory, # whether the memory lock loop was started and hasn't ended
|
synapse/lib/modelrev.py
CHANGED