sovereign 0.29.4__py3-none-any.whl → 0.30.0__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/schemas.py CHANGED
@@ -1,48 +1,35 @@
1
- import multiprocessing
2
1
  import warnings
2
+ import multiprocessing
3
3
  from collections import defaultdict
4
4
  from dataclasses import dataclass
5
5
  from enum import Enum
6
6
  from os import getenv
7
7
  from types import ModuleType
8
- from typing import Any, Dict, List, Optional, Self, Tuple, Type, Union
8
+ from typing import Any, Dict, List, Mapping, Optional, Self, Tuple, Union
9
9
 
10
+ import yaml
10
11
  from croniter import CroniterBadCronError, croniter
11
- from fastapi.responses import JSONResponse
12
12
  from jinja2 import Template, meta
13
13
  from pydantic import (
14
14
  BaseModel,
15
15
  ConfigDict,
16
16
  Field,
17
17
  SecretStr,
18
+ ValidationError,
18
19
  model_validator,
19
20
  field_validator,
20
21
  )
21
22
  from pydantic_settings import BaseSettings, SettingsConfigDict
22
23
 
24
+ from sovereign.response_class import json_response_class
23
25
  from sovereign.dynamic_config import Loadable
24
26
  from sovereign.dynamic_config.deser import jinja_env
25
27
  from sovereign.utils.crypto.suites import EncryptionType
28
+ from sovereign.utils import dictupdate
26
29
  from sovereign.utils.version_info import compute_hash
27
30
 
28
31
  missing_arguments = {"missing", "positional", "arguments:"}
29
32
 
30
- JsonResponseClass: Type[JSONResponse] = JSONResponse
31
- # pylint: disable=unused-import
32
- try:
33
- import orjson
34
- from fastapi.responses import ORJSONResponse
35
-
36
- JsonResponseClass = ORJSONResponse
37
- except ImportError:
38
- try:
39
- import ujson
40
- from fastapi.responses import UJSONResponse
41
-
42
- JsonResponseClass = UJSONResponse
43
- except ImportError:
44
- pass
45
-
46
33
 
47
34
  class CacheStrategy(str, Enum):
48
35
  context = "context"
@@ -206,7 +193,7 @@ class ProcessedTemplate:
206
193
  self.resources = resources
207
194
  self.version_info = version_info
208
195
  self._rendered: Optional[bytes] = None
209
- if metadata == None:
196
+ if metadata is None:
210
197
  metadata = []
211
198
  self.metadata = metadata
212
199
 
@@ -217,7 +204,7 @@ class ProcessedTemplate:
217
204
  @property
218
205
  def rendered(self) -> bytes:
219
206
  if self._rendered is None:
220
- result = JsonResponseClass(content="").render(
207
+ result = json_response_class(content="").render(
221
208
  content={
222
209
  "version_info": self.version,
223
210
  "resources": self.resources,
@@ -381,7 +368,7 @@ class SovereignAsgiConfig(BaseSettings):
381
368
  log_level: str = "warning"
382
369
  worker_class: str = "uvicorn.workers.UvicornWorker"
383
370
  worker_timeout: int = Field(30, alias="SOVEREIGN_WORKER_TIMEOUT")
384
- worker_tmp_dir: str = "/dev/shm"
371
+ worker_tmp_dir: Optional[str] = Field(None, alias="SOVEREIGN_WORKER_TMP_DIR")
385
372
  graceful_timeout: Optional[int] = Field(None)
386
373
  max_requests: int = Field(0, alias="SOVEREIGN_MAX_REQUESTS")
387
374
  max_requests_jitter: int = Field(0, alias="SOVEREIGN_MAX_REQUESTS_JITTER")
@@ -399,7 +386,7 @@ class SovereignAsgiConfig(BaseSettings):
399
386
  return self
400
387
 
401
388
  def as_gunicorn_conf(self) -> Dict[str, Any]:
402
- return {
389
+ ret = {
403
390
  "bind": ":".join(map(str, [self.host, self.port])),
404
391
  "keepalive": self.keepalive,
405
392
  "reuse_port": self.reuse_port,
@@ -409,11 +396,13 @@ class SovereignAsgiConfig(BaseSettings):
409
396
  "threads": self.threads,
410
397
  "workers": self.workers,
411
398
  "worker_class": self.worker_class,
412
- "worker_tmp_dir": self.worker_tmp_dir,
413
399
  "graceful_timeout": self.graceful_timeout,
414
400
  "max_requests": self.max_requests,
415
401
  "max_requests_jitter": self.max_requests_jitter,
416
402
  }
403
+ if self.worker_tmp_dir is not None:
404
+ ret["worker_tmp_dir"] = self.worker_tmp_dir
405
+ return ret
417
406
 
418
407
 
419
408
  class SovereignConfig(BaseSettings):
@@ -437,7 +426,7 @@ class SovereignConfig(BaseSettings):
437
426
  "service_clusters", alias="SOVEREIGN_SOURCE_MATCH_KEY"
438
427
  )
439
428
  sources_refresh_rate: int = Field(30, alias="SOVEREIGN_SOURCES_REFRESH_RATE")
440
- cache_strategy: str = Field("context", alias="SOVEREIGN_CACHE_STRATEGY")
429
+ cache_strategy: Optional[Any] = Field(None, alias="SOVEREIGN_CACHE_STRATEGY")
441
430
  refresh_context: bool = Field(False, alias="SOVEREIGN_REFRESH_CONTEXT")
442
431
  context_refresh_rate: Optional[int] = Field(
443
432
  None, alias="SOVEREIGN_CONTEXT_REFRESH_RATE"
@@ -461,6 +450,17 @@ class SovereignConfig(BaseSettings):
461
450
  populate_by_name=True,
462
451
  )
463
452
 
453
+ def __init__(self, *args, **kwargs):
454
+ warnings.warn(
455
+ (
456
+ "This version of Sovereign config is deprecated and will be removed in a future release. "
457
+ "To migrate, use `sovereign config migrate file:///etc/sovereign.yaml,file://./config/example.yaml`"
458
+ ),
459
+ DeprecationWarning,
460
+ stacklevel=2,
461
+ )
462
+ super().__init__(*args, **kwargs)
463
+
464
464
  @property
465
465
  def passwords(self) -> List[str]:
466
466
  return self.auth_passwords.split(",") or []
@@ -629,9 +629,7 @@ class ContextConfiguration(BaseSettings):
629
629
 
630
630
  class SourcesConfiguration(BaseSettings):
631
631
  refresh_rate: int = Field(30, alias="SOVEREIGN_SOURCES_REFRESH_RATE")
632
- cache_strategy: CacheStrategy = Field(
633
- CacheStrategy.context, alias="SOVEREIGN_CACHE_STRATEGY"
634
- )
632
+ cache_strategy: Optional[Any] = None
635
633
  model_config = SettingsConfigDict(
636
634
  env_file=".env",
637
635
  extra="ignore",
@@ -753,21 +751,30 @@ class LegacyConfig(BaseSettings):
753
751
 
754
752
 
755
753
  class SovereignConfigv2(BaseSettings):
756
- sources: List[ConfiguredSource]
757
754
  templates: Dict[str, List[TemplateSpecification]]
758
- source_config: SourcesConfiguration = SourcesConfiguration()
759
- modifiers: List[str] = []
760
- global_modifiers: List[str] = []
761
755
  template_context: ContextConfiguration = ContextConfiguration()
762
- matching: NodeMatching = NodeMatching()
763
756
  authentication: AuthConfiguration = AuthConfiguration()
764
757
  logging: LoggingConfiguration = LoggingConfiguration()
765
758
  statsd: StatsdConfig = StatsdConfig()
766
759
  sentry_dsn: SecretStr = Field(SecretStr(""), alias="SOVEREIGN_SENTRY_DSN")
767
- debug: bool = Field(False, alias="SOVEREIGN_DEBUG")
768
- legacy_fields: LegacyConfig = LegacyConfig()
769
760
  discovery_cache: DiscoveryCacheConfig = DiscoveryCacheConfig()
770
- tracing: TracingConfig = TracingConfig()
761
+ tracing: Optional[TracingConfig] = Field(default_factory=TracingConfig)
762
+ debug: bool = Field(False, alias="SOVEREIGN_DEBUG")
763
+
764
+ # Deprecated in 0.30
765
+ sources: Optional[List[ConfiguredSource]] = Field(None, deprecated=True)
766
+ source_config: SourcesConfiguration = Field(
767
+ default_factory=SourcesConfiguration, deprecated=True
768
+ )
769
+ matching: Optional[NodeMatching] = Field(
770
+ default_factory=NodeMatching, deprecated=True
771
+ )
772
+ modifiers: List[str] = Field(default_factory=list, deprecated=True)
773
+ global_modifiers: List[str] = Field(default_factory=list, deprecated=True)
774
+ legacy_fields: LegacyConfig = Field(default_factory=LegacyConfig, deprecated=True)
775
+
776
+ expected_service_clusters: List[str] = Field(default_factory=list, deprecated=True)
777
+
771
778
  model_config = SettingsConfigDict(
772
779
  env_file=".env",
773
780
  extra="ignore",
@@ -823,7 +830,7 @@ class SovereignConfigv2(BaseSettings):
823
830
  templates=new_templates,
824
831
  source_config=SourcesConfiguration(
825
832
  refresh_rate=other.sources_refresh_rate,
826
- cache_strategy=CacheStrategy(other.cache_strategy),
833
+ cache_strategy=None,
827
834
  ),
828
835
  modifiers=other.modifiers,
829
836
  global_modifiers=other.global_modifiers,
@@ -867,3 +874,45 @@ class SovereignConfigv2(BaseSettings):
867
874
  ),
868
875
  discovery_cache=other.discovery_cache,
869
876
  )
877
+
878
+
879
+ def migrate_configs():
880
+ import argparse
881
+
882
+ parser = argparse.ArgumentParser(description="Tool to manage configurations.")
883
+ subparsers = parser.add_subparsers(dest="command", help="Main commands")
884
+ config_parser = subparsers.add_parser("config", help="Configuration commands")
885
+ config_subparsers = config_parser.add_subparsers(
886
+ dest="subcommand", help="Config subcommands"
887
+ )
888
+ migrate_parser = config_subparsers.add_parser(
889
+ "migrate", help="Migrate configuration files"
890
+ )
891
+ migrate_parser.add_argument("files", help="Files to migrate")
892
+ args = parser.parse_args()
893
+
894
+ if args.command == "config" and args.subcommand == "migrate":
895
+
896
+ def secret_str_representer(dumper, data):
897
+ return dumper.represent_scalar(
898
+ "tag:yaml.org,2002:str", data.get_secret_value()
899
+ )
900
+
901
+ yaml.SafeDumper.add_representer(SecretStr, secret_str_representer)
902
+ try:
903
+ SovereignConfigv2(**parse_raw_configuration(args.files))
904
+ except ValidationError:
905
+ print("Already v2")
906
+ old_config = SovereignConfig(**parse_raw_configuration(args.files))
907
+ config = SovereignConfigv2.from_legacy_config(old_config)
908
+ print(yaml.safe_dump(config.model_dump()))
909
+ exit(0)
910
+
911
+
912
+ def parse_raw_configuration(path: str) -> Mapping[Any, Any]:
913
+ ret: Mapping[Any, Any] = dict()
914
+ for p in path.split(","):
915
+ spec = Loadable.from_legacy_fmt(p)
916
+ # For some reason mypy is broken here
917
+ ret = dictupdate.merge(obj_a=ret, obj_b=spec.load(), merge_lists=True) # type: ignore
918
+ return ret
@@ -19,6 +19,7 @@ Example configuration (YAML):
19
19
  region: us-east-1
20
20
  plan_id: 7d57270a-0348-58d3-829d-447a98fe98d5
21
21
  """
22
+
22
23
  from typing import Dict, Any, List
23
24
  from sovereign.sources.lib import Source
24
25
 
sovereign/sources/lib.py CHANGED
@@ -6,6 +6,7 @@ used via configuration.
6
6
 
7
7
  `todo entry point install guide`
8
8
  """
9
+
9
10
  import abc
10
11
  from typing import Any, Dict, List
11
12
 
@@ -40,8 +40,8 @@ class SourcePoller:
40
40
  self,
41
41
  sources: List[ConfiguredSource],
42
42
  matching_enabled: bool,
43
- node_match_key: str,
44
- source_match_key: str,
43
+ node_match_key: Optional[str],
44
+ source_match_key: Optional[str],
45
45
  source_refresh_rate: int,
46
46
  logger: BoundLogger,
47
47
  stats: Any,
@@ -181,6 +181,8 @@ class SourcePoller:
181
181
  return new
182
182
 
183
183
  def extract_node_key(self, node: Union[Node, Dict[Any, Any]]) -> Any:
184
+ if self.node_match_key is None:
185
+ return
184
186
  if "." not in self.node_match_key:
185
187
  # key is not nested, don't need glom
186
188
  node_value = getattr(node, self.node_match_key)
@@ -189,13 +191,13 @@ class SourcePoller:
189
191
  node_value = glom(node, self.node_match_key)
190
192
  except PathAccessError:
191
193
  raise RuntimeError(
192
- f'Failed to find key "{self.node_match_key}" in discoveryRequest({node}).\n'
193
- f"See the docs for more info: "
194
- f"https://vsyrakis.bitbucket.io/sovereign/docs/html/guides/node_matching.html"
194
+ f'Failed to find key "{self.node_match_key}" in discoveryRequest({node})'
195
195
  )
196
196
  return node_value
197
197
 
198
198
  def extract_source_key(self, source: Dict[Any, Any]) -> Any:
199
+ if self.source_match_key is None:
200
+ return
199
201
  if "." not in self.source_match_key:
200
202
  # key is not nested, don't need glom
201
203
  source_value = source[self.source_match_key]
@@ -204,9 +206,7 @@ class SourcePoller:
204
206
  source_value = glom(source, self.source_match_key)
205
207
  except PathAccessError:
206
208
  raise RuntimeError(
207
- f'Failed to find key "{self.source_match_key}" in instance({source}).\n'
208
- f"See the docs for more info: "
209
- f"https://vsyrakis.bitbucket.io/sovereign/docs/html/guides/node_matching.html"
209
+ f'Failed to find key "{self.source_match_key}" in instance({source})'
210
210
  )
211
211
  return source_value
212
212
 
@@ -0,0 +1,56 @@
1
+ document.addEventListener('DOMContentLoaded', function() {
2
+ function clearSearch() {
3
+ const searchInput = document.getElementById('searchInput');
4
+ searchInput.placeholder = '';
5
+ }
6
+
7
+ // Function to hide all panels except active
8
+ function updateVisibility() {
9
+ const panelBlocks = document.querySelectorAll('.virtualhost');
10
+ panelBlocks.forEach(block => {
11
+ if (!block.classList.contains('is-active')) {
12
+ block.classList.add('filtered');
13
+ } else {
14
+ block.classList.remove('filtered');
15
+ }
16
+ });
17
+ }
18
+ updateVisibility();
19
+
20
+ window.filterTabs = function(element, filter) {
21
+ const tabs = document.querySelectorAll('.panel-tabs a');
22
+ tabs.forEach(tab => tab.classList.remove('is-active'));
23
+ element.classList.add('is-active');
24
+
25
+ const virtualHosts = document.querySelectorAll('.virtualhost');
26
+ if (filter === "all") {
27
+ virtualHosts.forEach(vh => vh.classList.remove('filtered'));
28
+ } else {
29
+ virtualHosts.forEach(vh => {
30
+ if (vh.getAttribute("data-category") == filter) {
31
+ vh.classList.remove('filtered');
32
+ } else {
33
+ vh.classList.add('filtered');
34
+ }
35
+ });
36
+ }
37
+ clearSearch();
38
+ };
39
+
40
+ const searchInput = document.getElementById('searchInput');
41
+ searchInput.addEventListener('input', function() {
42
+ const query = searchInput.value.toLowerCase();
43
+ const panelBlocks = document.querySelectorAll('.virtualhost');
44
+ panelBlocks.forEach(block => {
45
+ const text = block.textContent.toLowerCase();
46
+ if (text.includes(query)) {
47
+ block.classList.remove('filtered');
48
+ } else {
49
+ block.classList.add('filtered');
50
+ }
51
+ });
52
+ });
53
+
54
+ const allTab = document.querySelector('.panel-tabs a.is-active');
55
+ filterTabs(allTab, 'all');
56
+ });
@@ -0,0 +1,20 @@
1
+ function filter_results(id, list) {
2
+ // Declare variables
3
+ let input, filter, container, iterable, resource, i, txtValue;
4
+ input = document.getElementById(id);
5
+ filter = input.value.toUpperCase();
6
+
7
+ container = document.getElementById(list);
8
+ iterable = container.getElementsByTagName("a");
9
+
10
+ // Loop through all list items, and hide those who don't match the search query
11
+ for (i = 0; i < iterable.length; i++) {
12
+ resource = iterable[i];
13
+ txtValue = resource.textContent;
14
+ if (txtValue.toUpperCase().indexOf(filter) > -1) {
15
+ iterable[i].style.display = "";
16
+ } else {
17
+ iterable[i].style.display = "none";
18
+ }
19
+ }
20
+ }
@@ -1,10 +1,15 @@
1
1
  {%- extends 'base.html' %}
2
- {%- import 'ul_filter.html' as filter %}
3
2
  {% block title %}{{ resource_type|capitalize }}{% endblock %}
4
3
 
5
4
  {% block head %}
6
5
  <meta name="last_update" content="{{ last_update }}">
7
- {{ filter }}
6
+ <script src="/static/search_filter.js"></script>
7
+ <script src="/static/panel.js"></script>
8
+ <style>
9
+ .filtered {
10
+ display: none;
11
+ }
12
+ </style>
8
13
  {% endblock %}
9
14
 
10
15
 
@@ -74,7 +79,7 @@
74
79
  type="text"
75
80
  id="search_filter"
76
81
  onkeyup="filter_results('search_filter', 'resources')"
77
- placeholder="Filter resources by any string"
82
+ placeholder="Filter {{ resource_type }} by any string"
78
83
  >
79
84
  </label>
80
85
  <span class="icon is-left">
@@ -118,39 +123,37 @@
118
123
  </nav>
119
124
 
120
125
  {% if resource_type == 'routes' %}
121
- {% for resource in res %}
122
- <nav class="panel" id="virtual_hosts">
123
- <p class="panel-heading">
124
- Virtual Hosts (Route Configuration: {{ resource["name"] }})
125
- </p>
126
- <div class="panel-block">
127
- <p class="control has-icons-left">
128
- <label for="search_filter_virtual_hosts">
129
- <input
130
- class="input"
131
- type="text"
132
- id="search_filter_virtual_hosts"
133
- onkeyup="filter_results('search_filter_virtual_hosts', 'virtual_hosts')"
134
- placeholder="Filter resources by any string"
135
- >
136
- </label>
137
- <span class="icon is-left">
138
- <i class="fas fa-search" aria-hidden="true"></i>
139
- </span>
140
- </p>
141
- </div>
142
-
143
- {% for virtualhost in resource['virtual_hosts'] %}
144
- <a class="panel-block"
145
- href="/ui/resources/routes/{{ resource['name'] }}/{{ virtualhost['name'] }}">
146
- <span class="panel-icon">
147
- <i class="fas fa-arrow-right" aria-hidden="true"></i>
148
- </span>
149
- {{ virtualhost['name'] }}
150
- </a>
151
- {% endfor %}
152
- </nav>
153
- {% endfor %}
126
+ <nav class="panel">
127
+ <p class="panel-heading">Virtual Hosts</p>
128
+ <div class="panel-block">
129
+ <p class="control has-icons-left">
130
+ <input id="searchInput" class="input" type="text" placeholder="Filter virtual-hosts by any string" />
131
+ <span class="icon is-left">
132
+ <i class="fas fa-search" aria-hidden="true"></i>
133
+ </span>
134
+ </p>
135
+ </div>
136
+ <p class="panel-tabs">
137
+ <a class="is-active" onclick="filterTabs(this, 'all')">All</a>
138
+ {% for resource in res %}
139
+ <a onclick="filterTabs(this, '{{ resource["name"] }}')">
140
+ {{ resource['name'] }}
141
+ </a>
142
+ {% endfor %}
143
+ </p>
144
+ {% for resource in res %}
145
+ {% for virtualhost in resource['virtual_hosts'] %}
146
+ <a class="panel-block virtualhost"
147
+ data-category="{{ resource['name'] }}"
148
+ href="/ui/resources/routes/{{ resource['name'] }}/{{ virtualhost['name'] }}">
149
+ <span class="panel-icon">
150
+ <i class="fas fa-arrow-right" aria-hidden="true"></i>
151
+ </span>
152
+ {{ virtualhost['name'] }}
153
+ </a>
154
+ {% endfor %}
155
+ {% endfor %}
156
+ </nav>
154
157
  {% endif %}
155
158
  {% else %}
156
159
  <span class="panel-icon">
sovereign/tracing.py CHANGED
@@ -31,55 +31,55 @@ def timestamp():
31
31
 
32
32
 
33
33
  TRACING = config.tracing
34
- TRACING_DISABLED = not TRACING.enabled
35
-
36
-
37
- class Tracer:
38
- def gen_id(self):
39
- if TRACING.trace_id_128bit:
40
- trace_id = generate_128bit()
41
- else:
42
- trace_id = generate_64bit()
43
- _trace_id_ctx_var.set(trace_id)
44
- return trace_id
45
-
46
- def __init__(self, span_name):
47
- if TRACING_DISABLED:
48
- return
49
- span_id = get_span_id()
50
- self.parent_span_id = None
51
- if span_id != "":
52
- # We are already inside a trace context
53
- self.parent_span_id = span_id
54
- self.trace_id = get_trace_id()
55
- self.span_id = self.gen_id()
56
- self.span_name = span_name
57
-
58
- def __enter__(self):
59
- if TRACING_DISABLED:
60
- return nullcontext()
61
- self.trace = {
62
- "traceId": self.trace_id,
63
- "id": self.span_id,
64
- "name": self.span_name,
65
- "timestamp": time.time(),
66
- "tags": TRACING.tags,
67
- }
68
- if self.parent_span_id:
69
- self.trace["parent_span_id"] = self.parent_span_id
70
- return self
71
-
72
- def __exit__(self, exc_type, exc_value, traceback):
73
- if TRACING_DISABLED:
74
- return
75
- self.trace["duration"] = time.time() - self.trace["timestamp"]
76
- self.submit()
77
-
78
- def submit(self):
79
- print(f"{self.span_name}: {self.trace['duration']}")
80
- try:
81
- url = f"{TRACING.collector}{TRACING.endpoint}"
82
- requests.post(url, json=self.trace)
83
- # pylint: disable=broad-except
84
- except Exception as e:
85
- print(f"Failed to submit trace: {self.trace}, Error:{e}")
34
+ if TRACING is not None:
35
+ TRACING_DISABLED = not TRACING.enabled
36
+
37
+ class Tracer:
38
+ def gen_id(self):
39
+ if TRACING.trace_id_128bit:
40
+ trace_id = generate_128bit()
41
+ else:
42
+ trace_id = generate_64bit()
43
+ _trace_id_ctx_var.set(trace_id)
44
+ return trace_id
45
+
46
+ def __init__(self, span_name):
47
+ if TRACING_DISABLED:
48
+ return
49
+ span_id = get_span_id()
50
+ self.parent_span_id = None
51
+ if span_id != "":
52
+ # We are already inside a trace context
53
+ self.parent_span_id = span_id
54
+ self.trace_id = get_trace_id()
55
+ self.span_id = self.gen_id()
56
+ self.span_name = span_name
57
+
58
+ def __enter__(self):
59
+ if TRACING_DISABLED:
60
+ return nullcontext()
61
+ self.trace = {
62
+ "traceId": self.trace_id,
63
+ "id": self.span_id,
64
+ "name": self.span_name,
65
+ "timestamp": time.time(),
66
+ "tags": TRACING.tags,
67
+ }
68
+ if self.parent_span_id:
69
+ self.trace["parent_span_id"] = self.parent_span_id
70
+ return self
71
+
72
+ def __exit__(self, exc_type, exc_value, traceback):
73
+ if TRACING_DISABLED:
74
+ return
75
+ self.trace["duration"] = time.time() - self.trace["timestamp"]
76
+ self.submit()
77
+
78
+ def submit(self):
79
+ print(f"{self.span_name}: {self.trace['duration']}")
80
+ try:
81
+ url = f"{TRACING.collector}{TRACING.endpoint}"
82
+ requests.post(url, json=self.trace)
83
+ # pylint: disable=broad-except
84
+ except Exception as e:
85
+ print(f"Failed to submit trace: {self.trace}, Error:{e}")
@@ -4,23 +4,18 @@ from typing import Any
4
4
 
5
5
  class CipherSuite(ABC):
6
6
  @abstractmethod
7
- def __init__(self, *args: Any, **kwargs: Any) -> None:
8
- ...
7
+ def __init__(self, *args: Any, **kwargs: Any) -> None: ...
9
8
 
10
9
  @abstractmethod
11
- def encrypt(self, data: str) -> str:
12
- ...
10
+ def encrypt(self, data: str) -> str: ...
13
11
 
14
12
  @abstractmethod
15
- def decrypt(self, data: str) -> str:
16
- ...
13
+ def decrypt(self, data: str) -> str: ...
17
14
 
18
15
  @property
19
16
  @abstractmethod
20
- def key_available(self) -> bool:
21
- ...
17
+ def key_available(self) -> bool: ...
22
18
 
23
19
  @classmethod
24
20
  @abstractmethod
25
- def generate_key(cls) -> bytes:
26
- ...
21
+ def generate_key(cls) -> bytes: ...
@@ -1,6 +1,7 @@
1
1
  # type: ignore
2
2
  # pylint: disable=no-name-in-module,too-many-branches
3
- """ Stolen from the saltstack library """
3
+ """Stolen from the saltstack library"""
4
+
4
5
  from collections.abc import Mapping
5
6
  import copy
6
7
 
sovereign/views/admin.py CHANGED
@@ -92,6 +92,7 @@ def instances(
92
92
  title="Whether the sources should run Modifiers/Global Modifiers prior to being returned",
93
93
  ),
94
94
  ) -> JSONResponse:
95
+ assert poller is not None # how else would there be sources
95
96
  node = mock_discovery_request(service_cluster=service_cluster).node
96
97
  args = {
97
98
  "modify": yaml.safe_load(modified),
sovereign/views/crypto.py CHANGED
@@ -4,7 +4,8 @@ from fastapi import APIRouter, Body
4
4
  from fastapi.responses import JSONResponse
5
5
  from pydantic import BaseModel, Field
6
6
 
7
- from sovereign import json_response_class, logs, server_cipher_container
7
+ from sovereign import logs, server_cipher_container
8
+ from sovereign.response_class import json_response_class
8
9
  from sovereign.schemas import EncryptionConfig
9
10
  from sovereign.utils.crypto.crypto import CipherContainer
10
11
  from sovereign.utils.crypto.suites import EncryptionType
@@ -2,7 +2,8 @@ from typing import List
2
2
  from fastapi import Response
3
3
  from fastapi.routing import APIRouter
4
4
  from fastapi.responses import PlainTextResponse
5
- from sovereign import XDS_TEMPLATES, __version__, json_response_class
5
+ from sovereign import XDS_TEMPLATES, __version__
6
+ from sovereign.response_class import json_response_class
6
7
  from sovereign.utils.mock import mock_discovery_request
7
8
  from sovereign.views.discovery import perform_discovery
8
9