sovereign 0.18.1__py3-none-any.whl → 0.19.1__py3-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 sovereign might be problematic. Click here for more details.

sovereign/__init__.py CHANGED
@@ -1,7 +1,8 @@
1
1
  import os
2
2
  from contextvars import ContextVar
3
3
  from typing import Type, Any, Mapping
4
- from pkg_resources import get_distribution, resource_filename
4
+ from importlib.metadata import version
5
+ from pkg_resources import resource_filename
5
6
 
6
7
  from fastapi.responses import JSONResponse
7
8
  from starlette.templating import Jinja2Templates
@@ -52,9 +53,12 @@ def get_request_id() -> str:
52
53
  return _request_id_ctx_var.get()
53
54
 
54
55
 
55
- __version__ = get_distribution("sovereign").version
56
+ DIST_NAME = "sovereign"
57
+
58
+ __version__ = version(DIST_NAME)
56
59
  config_path = os.getenv("SOVEREIGN_CONFIG", "file:///etc/sovereign.yaml")
57
- html_templates = Jinja2Templates(resource_filename("sovereign", "templates"))
60
+
61
+ html_templates = Jinja2Templates(resource_filename(DIST_NAME, "templates"))
58
62
 
59
63
  try:
60
64
  config = SovereignConfigv2(**parse_raw_configuration(config_path))
sovereign/context.py CHANGED
@@ -26,10 +26,10 @@ class TemplateContext:
26
26
  self.configured_context = configured_context
27
27
  self.crypto = encryption_suite
28
28
  self.disabled_suite = disabled_suite
29
- # initial load
30
- self.context = self.load_context_variables()
31
29
  self.logger = logger
32
30
  self.stats = stats
31
+ # initial load
32
+ self.context = self.load_context_variables()
33
33
 
34
34
  async def start_refresh_context(self) -> NoReturn:
35
35
  if self.refresh_cron is not None:
@@ -40,21 +40,26 @@ class TemplateContext:
40
40
  raise RuntimeError("Failed to start refresh_context, this should never happen")
41
41
 
42
42
  async def refresh_context(self) -> None:
43
- try:
44
- self.context = self.load_context_variables()
45
- self.stats.increment("context.refresh.success")
46
- # pylint: disable=broad-except
47
- except Exception as e:
48
- self.logger(event=e)
49
- self.stats.increment("context.refresh.error")
43
+ self.context = self.load_context_variables()
50
44
 
51
45
  def load_context_variables(self) -> Dict[str, Any]:
52
46
  ret = dict()
53
47
  for k, v in self.configured_context.items():
54
- if isinstance(v, Loadable):
55
- ret[k] = v.load()
56
- elif isinstance(v, str):
57
- ret[k] = Loadable.from_legacy_fmt(v).load()
48
+ try:
49
+ if isinstance(v, Loadable):
50
+ ret[k] = v.load()
51
+ elif isinstance(v, str):
52
+ ret[k] = Loadable.from_legacy_fmt(v).load()
53
+ self.stats.increment(
54
+ "context.refresh.success",
55
+ tags=[f"context:{k}"],
56
+ )
57
+ except Exception as e: # pylint: disable=broad-exception-caught
58
+ self.logger(event=e)
59
+ self.stats.increment(
60
+ "context.refresh.error",
61
+ tags=[f"context:{k}"],
62
+ )
58
63
  if "crypto" not in ret:
59
64
  ret["crypto"] = self.crypto
60
65
  return ret
sovereign/server.py CHANGED
@@ -1,14 +1,18 @@
1
1
  import gunicorn.app.base
2
2
  from fastapi import FastAPI
3
- from typing import Optional, Dict, Any
3
+ from typing import Optional, Dict, Any, Callable
4
4
  from sovereign import asgi_config
5
5
  from sovereign.app import app
6
+ from sovereign.utils.entry_point_loader import EntryPointLoader
6
7
 
7
8
 
8
9
  class StandaloneApplication(gunicorn.app.base.BaseApplication): # type: ignore
10
+ _HOOKS = ["pre_fork", "post_fork"]
11
+
9
12
  def __init__(
10
13
  self, application: FastAPI, options: Optional[Dict[str, Any]] = None
11
14
  ) -> None:
15
+ self.loader = EntryPointLoader(*self._HOOKS)
12
16
  self.options = options or {}
13
17
  self.application = application
14
18
  super().__init__()
@@ -17,6 +21,20 @@ class StandaloneApplication(gunicorn.app.base.BaseApplication): # type: ignore
17
21
  for key, value in self.options.items():
18
22
  self.cfg.set(key.lower(), value)
19
23
 
24
+ for hook in self._HOOKS:
25
+ self._install_hooks(hook)
26
+
27
+ def _install_hooks(self, name: str) -> None:
28
+ hooks: list[Callable[[Any, Any], None]] = [
29
+ ep.load() for ep in self.loader.groups[name]
30
+ ]
31
+
32
+ def master_hook(server: Any, worker: Any) -> None:
33
+ for hook in hooks:
34
+ hook(server, worker)
35
+
36
+ self.cfg.set(name, master_hook)
37
+
20
38
  def load(self) -> FastAPI:
21
39
  return self.application
22
40
 
@@ -1,12 +1,13 @@
1
1
  import asyncio
2
2
  import traceback
3
3
  from copy import deepcopy
4
+ from importlib.metadata import EntryPoint
4
5
  from datetime import timedelta, datetime
5
- from pkg_resources import iter_entry_points, EntryPoint
6
6
  from typing import Iterable, Any, Dict, List, Union, Type, Optional
7
7
 
8
8
  from glom import glom, PathAccessError
9
9
 
10
+ from sovereign.utils.entry_point_loader import EntryPointLoader
10
11
  from sovereign.sources.lib import Source
11
12
  from sovereign.modifiers.lib import Modifier, GlobalModifier
12
13
  from sovereign.schemas import (
@@ -50,14 +51,10 @@ class SourcePoller:
50
51
  self.logger = logger
51
52
  self.stats = stats
52
53
 
53
- self.entry_points: Dict[str, List[EntryPoint]] = dict()
54
- for entry_point in ("sources", "modifiers", "global_modifiers"):
55
- self.entry_points[entry_point] = list(
56
- iter_entry_points(f"sovereign.{entry_point}")
57
- )
54
+ self.entry_points = EntryPointLoader("sources", "modifiers", "global_modifiers")
58
55
 
59
56
  self.source_classes: Dict[str, Type[Source]] = {
60
- e.name: e.load() for e in self.entry_points["sources"]
57
+ e.name: e.load() for e in self.entry_points.groups["sources"]
61
58
  }
62
59
  self.sources = [self.setup_source(s) for s in sources]
63
60
  if not self.sources:
@@ -89,14 +86,14 @@ class SourcePoller:
89
86
  if len(self.modifiers) == len(modifiers):
90
87
  return
91
88
  self.modifiers = self.load_modifier_entrypoints(
92
- self.entry_points["modifiers"], modifiers
89
+ self.entry_points.groups["modifiers"], modifiers
93
90
  )
94
91
 
95
92
  def lazy_load_global_modifiers(self, global_modifiers: List[str]) -> None:
96
93
  if len(self.global_modifiers) == len(global_modifiers):
97
94
  return
98
95
  self.global_modifiers = self.load_global_modifier_entrypoints(
99
- self.entry_points["global_modifiers"], global_modifiers
96
+ self.entry_points.groups["global_modifiers"], global_modifiers
100
97
  )
101
98
 
102
99
  def load_modifier_entrypoints(
@@ -0,0 +1,18 @@
1
+ from typing import Dict
2
+ from functools import cached_property
3
+ from importlib.metadata import entry_points, EntryPoints
4
+
5
+
6
+ class EntryPointLoader:
7
+ ENTRY_POINTS = entry_points()
8
+
9
+ def __init__(self, *args: str) -> None:
10
+ self._groups = args
11
+
12
+ @classmethod
13
+ def _select(cls, group: str) -> EntryPoints:
14
+ return cls.ENTRY_POINTS.select(group=f"sovereign.{group}")
15
+
16
+ @cached_property
17
+ def groups(self) -> Dict[str, EntryPoints]:
18
+ return {group: self._select(group) for group in self._groups}
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sovereign
3
- Version: 0.18.1
3
+ Version: 0.19.1
4
4
  Summary: Envoy Proxy control-plane written in Python
5
5
  Home-page: https://pypi.org/project/sovereign/
6
6
  License: Apache-2.0
@@ -1,7 +1,7 @@
1
- sovereign/__init__.py,sha256=S6Wdp9HKMrOJwiGzjdYrT6LSZT7mz5m2Dcr_syOScLQ,3110
1
+ sovereign/__init__.py,sha256=OqRozdp92NTV_6pbYNtyXsTAHxkpHTpxslhNgcrXuNY,3136
2
2
  sovereign/app.py,sha256=z5dT5wdVNeAQap5ORRmnLpJstb1euWoj4vXZPrMttNs,4017
3
3
  sovereign/config_loader.py,sha256=siuXN6T62Lx3JzMchnEBZ7ZDuSCFH73oWuUk-oTOVQQ,6382
4
- sovereign/context.py,sha256=zOiI5ml3OeMytT-N-fqXVafzoJByoJ15ys97wPQjbH8,4212
4
+ sovereign/context.py,sha256=VswYtHZNcRMMT-Dlx9CBTxLo398uRXUPl6N--VcqybE,4411
5
5
  sovereign/discovery.py,sha256=EIghvk_HMYp14WzEG1aQhnsoGcLXMWSrCncPobJST4c,5885
6
6
  sovereign/error_info.py,sha256=r2KXBYq9Fo7AI2pmIpATWFm0pykr2MqfrKH0WWW5Sfk,1488
7
7
  sovereign/logs.py,sha256=DZK6F3LMxhch96qFasdXA6NPlQHJcKbjD83_S8W6Rds,4340
@@ -10,12 +10,12 @@ sovereign/modifiers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSu
10
10
  sovereign/modifiers/lib.py,sha256=DbXsxrrjnFE4Y7rbwpeiM5tS5w5NBwSdYH58AtDTP0I,2884
11
11
  sovereign/modifiers/test.py,sha256=7_c2hWXn_sYJ6997N1_uSWtClOikcOzu1yRCY56-l-4,361
12
12
  sovereign/schemas.py,sha256=jCW9WSjZ7SP8ycloYtC-6KG0Vj0VRBOesSTKa0kymrQ,27367
13
- sovereign/server.py,sha256=K9Zfw2d-I20s0F8-DeFHTg0B65IRluDalqSyJHQo67Y,825
13
+ sovereign/server.py,sha256=z8Uz1UYIZix0S40Srk774WIMDN2jl2SozO8irib0wc4,1402
14
14
  sovereign/sources/__init__.py,sha256=g9hEpFk8j5i1ApHQpbc9giTyJW41Ppgsqv5P9zGxOJk,78
15
15
  sovereign/sources/file.py,sha256=A4UWoRU39v2Ex5Mtdl_uw53iMkslYylF4CiiwW7LOpk,689
16
16
  sovereign/sources/inline.py,sha256=bNqVZyelcUofYBWHFOUIhOUU9az32CdBEfaYRzNzFFE,1002
17
17
  sovereign/sources/lib.py,sha256=LIbnlKkL0bQT10y4GT2E8yypjYxqfJYbB9FkGB5C2oc,1030
18
- sovereign/sources/poller.py,sha256=u1XMjkw6oCXWL8Uh3TPuHYKwIIj-86VF-iVzlHPkIKU,11044
18
+ sovereign/sources/poller.py,sha256=byxlEfhB1m2Uhzpi3wlknNLKRRQ47o56VuYLZrrFq1Q,10940
19
19
  sovereign/static/sass/style.scss,sha256=tPHPEm3sZeBFGDyyn3pHcA-nbaKT-h-UsSTsf6dHNDU,1158
20
20
  sovereign/static/style.css,sha256=vG8HPsbCbPIZfHgy7gSeof97Pnp0okkyaXyJzIEEW-8,447517
21
21
  sovereign/statistics.py,sha256=Xfj4oWMfCkbYc2ibF7rDUpbw6Zw6dI4N5BpCLDQc4j4,2336
@@ -28,6 +28,7 @@ sovereign/utils/auth.py,sha256=9rruWP-Ok8ec9l_MzWY3oUZKI8s7jt0Dmx3kHWnTRgQ,1772
28
28
  sovereign/utils/crypto.py,sha256=jNM3YRgdkxmTEeEDftkXnn33rr2qmT1-_3n3DUUdzRE,3438
29
29
  sovereign/utils/dictupdate.py,sha256=JkDjg16u7sW6A_4Q2oX1PY_MtJU7m1VivZWn9VLZ9V8,2559
30
30
  sovereign/utils/eds.py,sha256=3NwvQpFMxeWJ8pT1XhzqikrgT26HjObms4Ieh3hivOM,3894
31
+ sovereign/utils/entry_point_loader.py,sha256=BEVodk-um70RvT1nSOu_IB-hr1K4ppthXod0VZEiZJ8,526
31
32
  sovereign/utils/mock.py,sha256=UCWiZ7PsRxvDL9OmSXUuzuGPri2s69IABXLALZHWGII,1269
32
33
  sovereign/utils/templates.py,sha256=FE_H_oE7VrS3X_VN1z_g10b9-rpmi1_gL-cMxi5XtXU,1057
33
34
  sovereign/utils/timer.py,sha256=_dUtEasj0BKbWYuQ_T3HFIyjurXXj-La-dNSMAwKMSo,795
@@ -39,8 +40,8 @@ sovereign/views/crypto.py,sha256=nxp6bkPU9GZw_zOk0fsJdz_XRQPXxPI6cXQDL9-cigU,204
39
40
  sovereign/views/discovery.py,sha256=dPX0auMsQCCura7eIq-jEGQoS92Avs9QPAsPGDjWL5I,5902
40
41
  sovereign/views/healthchecks.py,sha256=_WkMunlrFpqGTLgtNtRr7gCsDCv5kiuYxCyTi-dMEKM,1357
41
42
  sovereign/views/interface.py,sha256=2wXb5Kf5CbY_X37dr1v-3Uoep04abvv8x7BaUTNqsPg,7093
42
- sovereign-0.18.1.dist-info/entry_points.txt,sha256=kOn848ucVbNvtsGABDuwzOHmNiOb0Ey8dV85Z3dLv3Y,222
43
- sovereign-0.18.1.dist-info/LICENSE.txt,sha256=2X125zvAb9AYLjCgdMDQZuufhm0kwcg31A8pGKj_-VY,560
44
- sovereign-0.18.1.dist-info/WHEEL,sha256=vxFmldFsRN_Hx10GDvsdv1wroKq8r5Lzvjp6GZ4OO8c,88
45
- sovereign-0.18.1.dist-info/METADATA,sha256=-acGNjvQvlkw8E_JTwPPQaWpOlz0CqE66ltLOArvvDA,6417
46
- sovereign-0.18.1.dist-info/RECORD,,
43
+ sovereign-0.19.1.dist-info/entry_points.txt,sha256=kOn848ucVbNvtsGABDuwzOHmNiOb0Ey8dV85Z3dLv3Y,222
44
+ sovereign-0.19.1.dist-info/LICENSE.txt,sha256=2X125zvAb9AYLjCgdMDQZuufhm0kwcg31A8pGKj_-VY,560
45
+ sovereign-0.19.1.dist-info/WHEEL,sha256=vxFmldFsRN_Hx10GDvsdv1wroKq8r5Lzvjp6GZ4OO8c,88
46
+ sovereign-0.19.1.dist-info/METADATA,sha256=gUIo4dFBvurdReBiftpAOL1Je9CbcitbtcigturyikU,6417
47
+ sovereign-0.19.1.dist-info/RECORD,,