sovereign 0.29.4__tar.gz → 0.30.0__tar.gz

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.

Files changed (68) hide show
  1. {sovereign-0.29.4 → sovereign-0.30.0}/PKG-INFO +43 -45
  2. {sovereign-0.29.4 → sovereign-0.30.0}/README.md +40 -43
  3. {sovereign-0.29.4 → sovereign-0.30.0}/pyproject.toml +19 -31
  4. {sovereign-0.29.4 → sovereign-0.30.0}/src/sovereign/__init__.py +34 -40
  5. {sovereign-0.29.4 → sovereign-0.30.0}/src/sovereign/app.py +11 -10
  6. {sovereign-0.29.4 → sovereign-0.30.0}/src/sovereign/context.py +37 -24
  7. {sovereign-0.29.4 → sovereign-0.30.0}/src/sovereign/discovery.py +8 -9
  8. {sovereign-0.29.4 → sovereign-0.30.0}/src/sovereign/dynamic_config/deser.py +1 -2
  9. {sovereign-0.29.4 → sovereign-0.30.0}/src/sovereign/dynamic_config/loaders.py +1 -2
  10. {sovereign-0.29.4 → sovereign-0.30.0}/src/sovereign/logging/access_logger.py +14 -1
  11. {sovereign-0.29.4 → sovereign-0.30.0}/src/sovereign/logging/application_logger.py +0 -1
  12. {sovereign-0.29.4 → sovereign-0.30.0}/src/sovereign/logging/base_logger.py +3 -27
  13. {sovereign-0.29.4 → sovereign-0.30.0}/src/sovereign/logging/bootstrapper.py +1 -1
  14. {sovereign-0.29.4 → sovereign-0.30.0}/src/sovereign/middlewares.py +3 -2
  15. {sovereign-0.29.4 → sovereign-0.30.0}/src/sovereign/modifiers/lib.py +1 -0
  16. {sovereign-0.29.4 → sovereign-0.30.0}/src/sovereign/schemas.py +86 -37
  17. {sovereign-0.29.4 → sovereign-0.30.0}/src/sovereign/sources/inline.py +1 -0
  18. {sovereign-0.29.4 → sovereign-0.30.0}/src/sovereign/sources/lib.py +1 -0
  19. {sovereign-0.29.4 → sovereign-0.30.0}/src/sovereign/sources/poller.py +8 -8
  20. sovereign-0.30.0/src/sovereign/static/panel.js +56 -0
  21. sovereign-0.30.0/src/sovereign/static/search_filter.js +20 -0
  22. {sovereign-0.29.4 → sovereign-0.30.0}/src/sovereign/templates/resources.html +39 -36
  23. sovereign-0.30.0/src/sovereign/tracing.py +85 -0
  24. sovereign-0.30.0/src/sovereign/utils/crypto/suites/base_cipher.py +21 -0
  25. {sovereign-0.29.4 → sovereign-0.30.0}/src/sovereign/utils/dictupdate.py +2 -1
  26. {sovereign-0.29.4 → sovereign-0.30.0}/src/sovereign/views/admin.py +1 -0
  27. {sovereign-0.29.4 → sovereign-0.30.0}/src/sovereign/views/crypto.py +2 -1
  28. {sovereign-0.29.4 → sovereign-0.30.0}/src/sovereign/views/healthchecks.py +2 -1
  29. {sovereign-0.29.4 → sovereign-0.30.0}/src/sovereign/views/interface.py +21 -5
  30. sovereign-0.29.4/src/sovereign/configuration.py +0 -66
  31. sovereign-0.29.4/src/sovereign/templates/ul_filter.html +0 -22
  32. sovereign-0.29.4/src/sovereign/tracing.py +0 -85
  33. sovereign-0.29.4/src/sovereign/utils/crypto/suites/base_cipher.py +0 -26
  34. {sovereign-0.29.4 → sovereign-0.30.0}/LICENSE.txt +0 -0
  35. {sovereign-0.29.4 → sovereign-0.30.0}/src/sovereign/constants.py +0 -0
  36. {sovereign-0.29.4 → sovereign-0.30.0}/src/sovereign/dynamic_config/__init__.py +0 -0
  37. {sovereign-0.29.4 → sovereign-0.30.0}/src/sovereign/error_info.py +0 -0
  38. {sovereign-0.29.4 → sovereign-0.30.0}/src/sovereign/logging/types.py +0 -0
  39. {sovereign-0.29.4 → sovereign-0.30.0}/src/sovereign/modifiers/__init__.py +0 -0
  40. {sovereign-0.29.4 → sovereign-0.30.0}/src/sovereign/response_class.py +0 -0
  41. {sovereign-0.29.4 → sovereign-0.30.0}/src/sovereign/server.py +0 -0
  42. {sovereign-0.29.4 → sovereign-0.30.0}/src/sovereign/sources/__init__.py +0 -0
  43. {sovereign-0.29.4 → sovereign-0.30.0}/src/sovereign/sources/file.py +0 -0
  44. {sovereign-0.29.4 → sovereign-0.30.0}/src/sovereign/static/sass/style.scss +0 -0
  45. {sovereign-0.29.4 → sovereign-0.30.0}/src/sovereign/static/style.css +0 -0
  46. {sovereign-0.29.4 → sovereign-0.30.0}/src/sovereign/statistics.py +0 -0
  47. {sovereign-0.29.4 → sovereign-0.30.0}/src/sovereign/templates/base.html +0 -0
  48. {sovereign-0.29.4 → sovereign-0.30.0}/src/sovereign/templates/err.html +0 -0
  49. {sovereign-0.29.4 → sovereign-0.30.0}/src/sovereign/testing/loaders.py +0 -0
  50. {sovereign-0.29.4 → sovereign-0.30.0}/src/sovereign/testing/modifiers.py +0 -0
  51. {sovereign-0.29.4 → sovereign-0.30.0}/src/sovereign/utils/__init__.py +0 -0
  52. {sovereign-0.29.4 → sovereign-0.30.0}/src/sovereign/utils/auth.py +0 -0
  53. {sovereign-0.29.4 → sovereign-0.30.0}/src/sovereign/utils/crypto/__init__.py +0 -0
  54. {sovereign-0.29.4 → sovereign-0.30.0}/src/sovereign/utils/crypto/crypto.py +0 -0
  55. {sovereign-0.29.4 → sovereign-0.30.0}/src/sovereign/utils/crypto/suites/__init__.py +0 -0
  56. {sovereign-0.29.4 → sovereign-0.30.0}/src/sovereign/utils/crypto/suites/aes_gcm_cipher.py +0 -0
  57. {sovereign-0.29.4 → sovereign-0.30.0}/src/sovereign/utils/crypto/suites/disabled_cipher.py +0 -0
  58. {sovereign-0.29.4 → sovereign-0.30.0}/src/sovereign/utils/crypto/suites/fernet_cipher.py +0 -0
  59. {sovereign-0.29.4 → sovereign-0.30.0}/src/sovereign/utils/eds.py +0 -0
  60. {sovereign-0.29.4 → sovereign-0.30.0}/src/sovereign/utils/entry_point_loader.py +0 -0
  61. {sovereign-0.29.4 → sovereign-0.30.0}/src/sovereign/utils/mock.py +0 -0
  62. {sovereign-0.29.4 → sovereign-0.30.0}/src/sovereign/utils/resources.py +0 -0
  63. {sovereign-0.29.4 → sovereign-0.30.0}/src/sovereign/utils/templates.py +0 -0
  64. {sovereign-0.29.4 → sovereign-0.30.0}/src/sovereign/utils/timer.py +0 -0
  65. {sovereign-0.29.4 → sovereign-0.30.0}/src/sovereign/utils/version_info.py +0 -0
  66. {sovereign-0.29.4 → sovereign-0.30.0}/src/sovereign/utils/weighted_clusters.py +0 -0
  67. {sovereign-0.29.4 → sovereign-0.30.0}/src/sovereign/views/__init__.py +0 -0
  68. {sovereign-0.29.4 → sovereign-0.30.0}/src/sovereign/views/discovery.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sovereign
3
- Version: 0.29.4
3
+ Version: 0.30.0
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
@@ -51,60 +51,70 @@ Requires-Dist: pydantic-settings (<2.6.0)
51
51
  Requires-Dist: redis (<=5.0.0)
52
52
  Requires-Dist: requests (>=2.31.0,<3.0.0)
53
53
  Requires-Dist: sentry-sdk (>=2.14.0,<3.0.0) ; extra == "sentry"
54
+ Requires-Dist: starlette-context (>=0.3.6,<0.4.0)
54
55
  Requires-Dist: structlog (>=23.1.0,<24.0.0)
55
56
  Requires-Dist: ujson (>=5.8.0,<6.0.0) ; extra == "ujson"
56
57
  Requires-Dist: uvicorn (>=0.23.2,<0.24.0)
57
58
  Requires-Dist: uvloop (>=0.19.0,<0.20.0)
58
- Project-URL: Documentation, https://vsyrakis.bitbucket.io/sovereign/docs/
59
+ Project-URL: Documentation, https://developer.atlassian.com/platform/sovereign/
59
60
  Project-URL: Repository, https://bitbucket.org/atlassian/sovereign/src/master/
60
61
  Description-Content-Type: text/markdown
61
62
 
62
63
  sovereign
63
64
  =========
64
65
 
66
+
65
67
  Mission statement
66
68
  -----------------
67
69
  This project implements a JSON control-plane based on the [envoy](https://envoyproxy.io) [data-plane-api](https://github.com/envoyproxy/data-plane-api)
68
70
 
69
- The purpose of `sovereign` is to supply downstream envoy proxies with
70
- configuration in near-realtime by responding to discovery requests.
71
+ The purpose of `sovereign` is to supply downstream envoy proxies with dynamic configuration.
72
+
71
73
 
72
74
  Mechanism of Operation
73
75
  ----------------------
74
- tl;dr version:
75
- ```
76
- * Polls HTTP/File/Other for data
77
- * (optional) Applies transforms to the data
78
- * Uses the data to generate Envoy configuration from templates
79
- ```
76
+ Sovereign allows you to define templates that represent each resource type
77
+ provided by Envoy. For example, clusters, routes, listeners, secrets,
78
+ extension_configs, etc.
79
+
80
+ In order to enrich the templates with data, Sovereign has ways of polling data
81
+ out-of-band which it then includes as variables that can be accessed within the
82
+ templates.
83
+
84
+ This allows Sovereign to provide configuration to Envoy that changes over time
85
+ depending on the data sources, without needing to redeploy the control-plane.
80
86
 
81
- In a nutshell, Sovereign
82
- gathers contextual data (*"sources"* and *"template context"*),
83
- optionally applies transforms to that data (using *"modifiers"*) and finally
84
- uses the data to generate envoy configuration from either python code, or jinja2 templates.
87
+ Sovereign provides some built-in ways of polling data (such as over HTTP, or
88
+ on-disk) but also exposes extension points, allowing you to write your own
89
+ plugins in Python.
85
90
 
86
- This is performed in a semi-stateless way, where the only state is data cached in memory.
87
91
 
88
- Template context is intended to be statically configured, whereas *Sources*
89
- are meant to be dynamic - for example, fetching from an API, an S3 bucket,
90
- or a file that receives updates.
92
+ Support
93
+ ------------
94
+ [Submit new issues here](https://bitbucket.org/atlassian/sovereign/issues/new)
95
+
96
+ If you're unable to submit an issue on Bitbucket, send an email to [vsyrakis@atlassian.com](mailto:vsyrakis@atlassian.com)
97
+
91
98
 
92
- *Modifiers* can mutate the data retrieved from sources, just in case the data
93
- is in a less than favorable structure.
99
+ Release
100
+ ------------
101
+ See [RELEASE.md]
94
102
 
95
- Both modifiers and sources are pluggable, i.e. it's easy to write your own and
96
- plug them into Sovereign for your use-case.
97
103
 
98
- Currently, Sovereign supports only providing configuration to Envoy as JSON.
99
- That is to say, gRPC is not supported yet. Contributions in this area are highly
100
- appreciated!
104
+ Roadmap
105
+ ------------
106
+ * Performance improvements
107
+ * Data persistence
108
+ * Push API (versus polling)
109
+ * Client for Sovereign
110
+ * gRPC
101
111
 
102
- The JSON configuration can be viewed in real-time with Sovereign's read-only web interface.
103
112
 
104
113
  Requirements
105
114
  ------------
106
115
  * Python 3.8+
107
116
 
117
+
108
118
  Installation
109
119
  ------------
110
120
  ```
@@ -113,62 +123,52 @@ pip install sovereign
113
123
 
114
124
  Documentation
115
125
  -------------
116
- [Read the docs here!](https://vsyrakis.bitbucket.io/sovereign/docs/)
126
+ [Read the docs here!](https://developer.atlassian.com/platform/sovereign/)
117
127
 
118
- :new: Read-only user interface
119
- ------------------------
120
- Added in `v0.5.3`!
121
128
 
122
- This interface allows you to browse the resources currently returned by Sovereign.
123
-
124
- ![Sovereign User Interface Screenshot](https://bitbucket.org/atlassian/sovereign/src/master/assets/sovereign_ui.png)
125
129
 
126
130
  Local development
127
131
  =================
128
132
 
133
+
129
134
  Requirements
130
135
  ------------
136
+ * Poetry
131
137
  * Docker
132
138
  * Docker-compose
133
139
 
140
+
134
141
  Installing dependencies for dev
135
142
  -------------------------------
136
- I recommend creating a virtualenv before doing any dev work
137
-
143
+ Dependencies and creation of virtualenv is handled by poetry
138
144
  ```
139
- python3 -m venv venv
140
- source venv/bin/activate
141
- pip install -r requirements-dev.txt
145
+ poetry install
146
+ poetry shell
142
147
  ```
143
148
 
144
149
  Running locally
145
150
  ---------------
146
151
  Running the test env
147
-
148
152
  ```
149
153
  make run
150
154
  ```
151
155
 
152
156
  Running the test env daemonized
153
-
154
157
  ```
155
158
  make run-daemon
156
159
  ```
157
160
 
158
161
  Pylint
159
-
160
162
  ```
161
163
  make lint
162
164
  ```
163
165
 
164
166
  Unit tests
165
-
166
167
  ```
167
168
  make unit
168
169
  ```
169
170
 
170
171
  Acceptance tests
171
-
172
172
  ```
173
173
  make run-daemon acceptance
174
174
  ```
@@ -176,7 +176,6 @@ make run-daemon acceptance
176
176
 
177
177
  Contributors
178
178
  ============
179
-
180
179
  Pull requests, issues and comments welcome. For pull requests:
181
180
 
182
181
  * Add tests for new features and bug fixes
@@ -205,7 +204,6 @@ those contributing as an individual.
205
204
 
206
205
  License
207
206
  ========
208
-
209
207
  Copyright (c) 2018 Atlassian and others.
210
208
  Apache 2.0 licensed, see [LICENSE.txt](LICENSE.txt) file.
211
209
 
@@ -1,49 +1,58 @@
1
1
  sovereign
2
2
  =========
3
3
 
4
+
4
5
  Mission statement
5
6
  -----------------
6
7
  This project implements a JSON control-plane based on the [envoy](https://envoyproxy.io) [data-plane-api](https://github.com/envoyproxy/data-plane-api)
7
8
 
8
- The purpose of `sovereign` is to supply downstream envoy proxies with
9
- configuration in near-realtime by responding to discovery requests.
9
+ The purpose of `sovereign` is to supply downstream envoy proxies with dynamic configuration.
10
+
10
11
 
11
12
  Mechanism of Operation
12
13
  ----------------------
13
- tl;dr version:
14
- ```
15
- * Polls HTTP/File/Other for data
16
- * (optional) Applies transforms to the data
17
- * Uses the data to generate Envoy configuration from templates
18
- ```
14
+ Sovereign allows you to define templates that represent each resource type
15
+ provided by Envoy. For example, clusters, routes, listeners, secrets,
16
+ extension_configs, etc.
17
+
18
+ In order to enrich the templates with data, Sovereign has ways of polling data
19
+ out-of-band which it then includes as variables that can be accessed within the
20
+ templates.
21
+
22
+ This allows Sovereign to provide configuration to Envoy that changes over time
23
+ depending on the data sources, without needing to redeploy the control-plane.
19
24
 
20
- In a nutshell, Sovereign
21
- gathers contextual data (*"sources"* and *"template context"*),
22
- optionally applies transforms to that data (using *"modifiers"*) and finally
23
- uses the data to generate envoy configuration from either python code, or jinja2 templates.
25
+ Sovereign provides some built-in ways of polling data (such as over HTTP, or
26
+ on-disk) but also exposes extension points, allowing you to write your own
27
+ plugins in Python.
24
28
 
25
- This is performed in a semi-stateless way, where the only state is data cached in memory.
26
29
 
27
- Template context is intended to be statically configured, whereas *Sources*
28
- are meant to be dynamic - for example, fetching from an API, an S3 bucket,
29
- or a file that receives updates.
30
+ Support
31
+ ------------
32
+ [Submit new issues here](https://bitbucket.org/atlassian/sovereign/issues/new)
33
+
34
+ If you're unable to submit an issue on Bitbucket, send an email to [vsyrakis@atlassian.com](mailto:vsyrakis@atlassian.com)
35
+
30
36
 
31
- *Modifiers* can mutate the data retrieved from sources, just in case the data
32
- is in a less than favorable structure.
37
+ Release
38
+ ------------
39
+ See [RELEASE.md]
33
40
 
34
- Both modifiers and sources are pluggable, i.e. it's easy to write your own and
35
- plug them into Sovereign for your use-case.
36
41
 
37
- Currently, Sovereign supports only providing configuration to Envoy as JSON.
38
- That is to say, gRPC is not supported yet. Contributions in this area are highly
39
- appreciated!
42
+ Roadmap
43
+ ------------
44
+ * Performance improvements
45
+ * Data persistence
46
+ * Push API (versus polling)
47
+ * Client for Sovereign
48
+ * gRPC
40
49
 
41
- The JSON configuration can be viewed in real-time with Sovereign's read-only web interface.
42
50
 
43
51
  Requirements
44
52
  ------------
45
53
  * Python 3.8+
46
54
 
55
+
47
56
  Installation
48
57
  ------------
49
58
  ```
@@ -52,62 +61,52 @@ pip install sovereign
52
61
 
53
62
  Documentation
54
63
  -------------
55
- [Read the docs here!](https://vsyrakis.bitbucket.io/sovereign/docs/)
64
+ [Read the docs here!](https://developer.atlassian.com/platform/sovereign/)
56
65
 
57
- :new: Read-only user interface
58
- ------------------------
59
- Added in `v0.5.3`!
60
66
 
61
- This interface allows you to browse the resources currently returned by Sovereign.
62
-
63
- ![Sovereign User Interface Screenshot](https://bitbucket.org/atlassian/sovereign/src/master/assets/sovereign_ui.png)
64
67
 
65
68
  Local development
66
69
  =================
67
70
 
71
+
68
72
  Requirements
69
73
  ------------
74
+ * Poetry
70
75
  * Docker
71
76
  * Docker-compose
72
77
 
78
+
73
79
  Installing dependencies for dev
74
80
  -------------------------------
75
- I recommend creating a virtualenv before doing any dev work
76
-
81
+ Dependencies and creation of virtualenv is handled by poetry
77
82
  ```
78
- python3 -m venv venv
79
- source venv/bin/activate
80
- pip install -r requirements-dev.txt
83
+ poetry install
84
+ poetry shell
81
85
  ```
82
86
 
83
87
  Running locally
84
88
  ---------------
85
89
  Running the test env
86
-
87
90
  ```
88
91
  make run
89
92
  ```
90
93
 
91
94
  Running the test env daemonized
92
-
93
95
  ```
94
96
  make run-daemon
95
97
  ```
96
98
 
97
99
  Pylint
98
-
99
100
  ```
100
101
  make lint
101
102
  ```
102
103
 
103
104
  Unit tests
104
-
105
105
  ```
106
106
  make unit
107
107
  ```
108
108
 
109
109
  Acceptance tests
110
-
111
110
  ```
112
111
  make run-daemon acceptance
113
112
  ```
@@ -115,7 +114,6 @@ make run-daemon acceptance
115
114
 
116
115
  Contributors
117
116
  ============
118
-
119
117
  Pull requests, issues and comments welcome. For pull requests:
120
118
 
121
119
  * Add tests for new features and bug fixes
@@ -144,7 +142,6 @@ those contributing as an individual.
144
142
 
145
143
  License
146
144
  ========
147
-
148
145
  Copyright (c) 2018 Atlassian and others.
149
146
  Apache 2.0 licensed, see [LICENSE.txt](LICENSE.txt) file.
150
147
 
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "sovereign"
3
- version = "0.29.4"
3
+ version = "0.30.0"
4
4
  description = "Envoy Proxy control-plane written in Python"
5
5
  license = "Apache-2.0"
6
6
  packages = [
@@ -8,7 +8,7 @@ packages = [
8
8
  ]
9
9
  readme = "README.md"
10
10
  #include = ["CHANGELOG.md", "CODE_OF_CONDUCT.md"]
11
- documentation = "https://vsyrakis.bitbucket.io/sovereign/docs/"
11
+ documentation = "https://developer.atlassian.com/platform/sovereign/"
12
12
  repository = "https://bitbucket.org/atlassian/sovereign/src/master/"
13
13
  homepage = "https://pypi.org/project/sovereign/"
14
14
  authors = ["Vasili Syrakis <vsyrakis@atlassian.com>"]
@@ -58,6 +58,8 @@ sovereign = 'sovereign.server:main'
58
58
  "jinja2" = "sovereign.dynamic_config.deser:JinjaDeserializer"
59
59
  "string" = "sovereign.dynamic_config.deser:StringDeserializer"
60
60
  "raw" = "sovereign.dynamic_config.deser:PassthroughDeserializer"
61
+ "none" = "sovereign.dynamic_config.deser:PassthroughDeserializer"
62
+ "passthrough" = "sovereign.dynamic_config.deser:PassthroughDeserializer"
61
63
  "ujson" = "sovereign.dynamic_config.deser:UjsonDeserializer"
62
64
  "orjson" = "sovereign.dynamic_config.deser:OrjsonDeserializer"
63
65
 
@@ -88,6 +90,7 @@ httptools = {version = "^0.6.0", optional = true}
88
90
  cachetools = "^5.3.2"
89
91
  pydantic = "^2.7.2"
90
92
  pydantic-settings = "<2.6.0"
93
+ starlette-context = "^0.3.6"
91
94
 
92
95
  [tool.poetry.extras]
93
96
  sentry = ["sentry-sdk"]
@@ -99,40 +102,28 @@ caching = ["cashews"]
99
102
  httptools = ["httptools"]
100
103
 
101
104
  [tool.poetry.group.dev.dependencies]
102
- pytest = "^7.0.0"
103
- "ruamel.yaml" = "^0.17.32"
104
- pytest-asyncio = "^0.20.0"
105
- pytest-mock = "^3.10.0"
106
- pytest-spec = "^3.2.0"
107
- pytest-timeout = "^2.1.0"
108
- coverage = "^7.3.1"
109
- invoke = "^2.2.0"
110
- pylint = "^2.17.6"
111
- tavern = "^2.9.2"
112
- twine = "^4.0.2"
113
- poethepoet = "^0.23.0"
114
- mypy = "^1.8.0"
115
- black = "^23.9.1"
116
- freezegun = "^1.2.2"
105
+ # http integration test
106
+ tavern = "^2.11.0"
107
+ # mocking
117
108
  moto = "^4.2.4"
118
- httpx = "^0.25.0"
109
+ freezegun = "^1.2.2"
110
+ pytest-mock = "^3.14.0"
111
+ pytest-asyncio = "^0.23"
112
+ # type and lint checks
113
+ mypy = "^1.8.0"
114
+ ruff = "^0.8.4"
115
+ # used in release checking script
116
+ toml = "^0.10.2"
117
+ # needed for starlette testclient
118
+ httpx = "^0.28.1"
119
+ # mypy types
119
120
  types-croniter = "^1.4.0.1"
120
121
  types-requests = "^2.31.0.8"
121
122
  types-setuptools = "^68.2.0.0"
122
123
  types-ujson = "^5.8.0.1"
123
124
  types-PyYAML = "^6.0.12.12"
124
- pylama = "^8.4.1"
125
- prospector = "^1.10.2"
126
- toml = "^0.10.2"
127
125
  types-cachetools = "^5.3.0.7"
128
126
 
129
- [tool.poe.tasks]
130
- types = { cmd = "mypy src/sovereign --ignore-missing-imports", help = "Check types with mypy" }
131
- format = { cmd = "black . --exclude test", help = "Apply black formatting to source code" }
132
- clean = { cmd = "rm -rf site test-reports logs .coverage .mypy_cache .pytest_cache dist sovereign.egg-info **/__pycache__", help = "Clean out generated files from the workspace" }
133
- check-style = { cmd = "black . --check --diff --exclude test", help = "Check if code style is correct" }
134
- lint = { cmd = "pylint src/sovereign", help = "Run linter checks" }
135
-
136
127
  [tool.black]
137
128
  target-version = ['py311']
138
129
 
@@ -142,9 +133,6 @@ plugins = [
142
133
  ]
143
134
  ignore_missing_imports = true
144
135
 
145
- [tool.coverage.run]
146
- omit = ["test/*"]
147
-
148
136
  [build-system]
149
137
  requires = ["poetry-core>=1.0.0"]
150
138
  build-backend = "poetry.core.masonry.api"
@@ -1,46 +1,26 @@
1
1
  import os
2
+ import sys
2
3
  from contextvars import ContextVar
3
4
  from importlib.metadata import version
4
- from typing import Any, Mapping, Type
5
+ from typing import Optional
5
6
 
6
- from fastapi.responses import JSONResponse
7
7
  from pydantic import ValidationError
8
8
  from starlette.templating import Jinja2Templates
9
9
 
10
- from sovereign import dynamic_config
11
10
  from sovereign.context import TemplateContext
12
11
  from sovereign.logging.bootstrapper import LoggerBootstrapper
13
- from sovereign.schemas import SovereignAsgiConfig, SovereignConfig, SovereignConfigv2
12
+ from sovereign.schemas import (
13
+ SovereignAsgiConfig,
14
+ SovereignConfig,
15
+ SovereignConfigv2,
16
+ migrate_configs,
17
+ parse_raw_configuration,
18
+ )
14
19
  from sovereign.sources import SourcePoller
15
20
  from sovereign.statistics import configure_statsd
16
21
  from sovereign.utils.crypto.crypto import CipherContainer
17
- from sovereign.utils.dictupdate import merge # type: ignore
18
22
  from sovereign.utils.resources import get_package_file
19
23
 
20
- json_response_class: Type[JSONResponse] = JSONResponse
21
- try:
22
- import orjson
23
- from fastapi.responses import ORJSONResponse
24
-
25
- json_response_class = ORJSONResponse
26
- except ImportError:
27
- try:
28
- import ujson
29
- from fastapi.responses import UJSONResponse
30
-
31
- json_response_class = UJSONResponse
32
- except ImportError:
33
- pass
34
-
35
-
36
- def parse_raw_configuration(path: str) -> Mapping[Any, Any]:
37
- ret: Mapping[Any, Any] = dict()
38
- for p in path.split(","):
39
- spec = dynamic_config.Loadable.from_legacy_fmt(p)
40
- ret = merge(obj_a=ret, obj_b=spec.load(), merge_lists=True)
41
- return ret
42
-
43
-
44
24
  _request_id_ctx_var: ContextVar[str] = ContextVar("request_id", default="")
45
25
 
46
26
 
@@ -57,6 +37,9 @@ html_templates = Jinja2Templates(
57
37
  directory=str(get_package_file(DIST_NAME, "templates"))
58
38
  )
59
39
 
40
+ if sys.argv[0].endswith("sovereign"):
41
+ migrate_configs()
42
+
60
43
  try:
61
44
  config = SovereignConfigv2(**parse_raw_configuration(config_path))
62
45
  except ValidationError:
@@ -69,15 +52,25 @@ logs = LoggerBootstrapper(config)
69
52
  application_logger = logs.application_logger.logger
70
53
 
71
54
  stats = configure_statsd(config=config.statsd)
72
- poller = SourcePoller(
73
- sources=config.sources,
74
- matching_enabled=config.matching.enabled,
75
- node_match_key=config.matching.node_key,
76
- source_match_key=config.matching.source_key,
77
- source_refresh_rate=config.source_config.refresh_rate,
78
- logger=application_logger,
79
- stats=stats,
80
- )
55
+ poller = None
56
+ if config.sources is not None:
57
+ if config.matching is not None:
58
+ matching_enabled = config.matching.enabled
59
+ node_key: Optional[str] = config.matching.node_key
60
+ source_key: Optional[str] = config.matching.source_key
61
+ else:
62
+ matching_enabled = False
63
+ node_key = None
64
+ source_key = None
65
+ poller = SourcePoller(
66
+ sources=config.sources,
67
+ matching_enabled=matching_enabled,
68
+ node_match_key=node_key,
69
+ source_match_key=source_key,
70
+ source_refresh_rate=config.source_config.refresh_rate,
71
+ logger=application_logger,
72
+ stats=stats,
73
+ )
81
74
 
82
75
  encryption_configs = config.authentication.encryption_configs
83
76
  server_cipher_container = CipherContainer.from_encryption_configs(
@@ -95,5 +88,6 @@ template_context = TemplateContext(
95
88
  logger=application_logger,
96
89
  stats=stats,
97
90
  )
98
- poller.lazy_load_modifiers(config.modifiers)
99
- poller.lazy_load_global_modifiers(config.global_modifiers)
91
+ if poller is not None:
92
+ poller.lazy_load_modifiers(config.modifiers)
93
+ poller.lazy_load_global_modifiers(config.global_modifiers)
@@ -4,24 +4,22 @@ from collections import namedtuple
4
4
 
5
5
  import uvicorn
6
6
  from fastapi import FastAPI, Request
7
- from fastapi.responses import RedirectResponse, FileResponse, Response, JSONResponse
7
+ from fastapi.responses import FileResponse, JSONResponse, RedirectResponse, Response
8
+ from starlette_context.middleware import RawContextMiddleware
8
9
 
9
10
  from sovereign import (
10
11
  __version__,
11
- config,
12
12
  asgi_config,
13
- json_response_class,
13
+ config,
14
+ logs,
14
15
  poller,
15
16
  template_context,
16
- logs,
17
17
  )
18
+ from sovereign.response_class import json_response_class
18
19
  from sovereign.error_info import ErrorInfo
20
+ from sovereign.middlewares import LoggingMiddleware, RequestContextLogMiddleware
19
21
  from sovereign.utils.resources import get_package_file
20
- from sovereign.views import crypto, discovery, healthchecks, admin, interface
21
- from sovereign.middlewares import (
22
- RequestContextLogMiddleware,
23
- LoggingMiddleware,
24
- )
22
+ from sovereign.views import admin, crypto, discovery, healthchecks, interface
25
23
 
26
24
  Router = namedtuple("Router", "module tags prefix")
27
25
 
@@ -89,6 +87,8 @@ def init_app() -> FastAPI:
89
87
  application.add_middleware(SentryAsgiMiddleware)
90
88
  logs.application_logger.logger.info("Sentry middleware enabled")
91
89
 
90
+ application.add_middleware(RawContextMiddleware)
91
+
92
92
  @application.exception_handler(500)
93
93
  async def exception_handler(_: Request, exc: Exception) -> JSONResponse:
94
94
  """
@@ -109,7 +109,8 @@ def init_app() -> FastAPI:
109
109
 
110
110
  @application.on_event("startup")
111
111
  async def keep_sources_uptodate() -> None:
112
- asyncio.create_task(poller.poll_forever())
112
+ if poller is not None:
113
+ asyncio.create_task(poller.poll_forever())
113
114
 
114
115
  @application.on_event("startup")
115
116
  async def refresh_template_context() -> None: