sovereign 0.29.3__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.
- {sovereign-0.29.3 → sovereign-0.30.0}/PKG-INFO +46 -47
- {sovereign-0.29.3 → sovereign-0.30.0}/README.md +40 -43
- {sovereign-0.29.3 → sovereign-0.30.0}/pyproject.toml +21 -33
- {sovereign-0.29.3 → sovereign-0.30.0}/src/sovereign/__init__.py +34 -40
- {sovereign-0.29.3 → sovereign-0.30.0}/src/sovereign/app.py +11 -10
- {sovereign-0.29.3 → sovereign-0.30.0}/src/sovereign/context.py +37 -24
- {sovereign-0.29.3 → sovereign-0.30.0}/src/sovereign/discovery.py +8 -9
- {sovereign-0.29.3 → sovereign-0.30.0}/src/sovereign/dynamic_config/deser.py +1 -2
- {sovereign-0.29.3 → sovereign-0.30.0}/src/sovereign/dynamic_config/loaders.py +1 -2
- {sovereign-0.29.3 → sovereign-0.30.0}/src/sovereign/logging/access_logger.py +14 -1
- {sovereign-0.29.3 → sovereign-0.30.0}/src/sovereign/logging/application_logger.py +0 -1
- {sovereign-0.29.3 → sovereign-0.30.0}/src/sovereign/logging/base_logger.py +3 -27
- {sovereign-0.29.3 → sovereign-0.30.0}/src/sovereign/logging/bootstrapper.py +1 -1
- {sovereign-0.29.3 → sovereign-0.30.0}/src/sovereign/middlewares.py +3 -2
- {sovereign-0.29.3 → sovereign-0.30.0}/src/sovereign/modifiers/lib.py +1 -0
- {sovereign-0.29.3 → sovereign-0.30.0}/src/sovereign/schemas.py +86 -37
- {sovereign-0.29.3 → sovereign-0.30.0}/src/sovereign/sources/inline.py +1 -0
- {sovereign-0.29.3 → sovereign-0.30.0}/src/sovereign/sources/lib.py +1 -0
- {sovereign-0.29.3 → sovereign-0.30.0}/src/sovereign/sources/poller.py +8 -8
- sovereign-0.30.0/src/sovereign/static/panel.js +56 -0
- sovereign-0.30.0/src/sovereign/static/search_filter.js +20 -0
- {sovereign-0.29.3 → sovereign-0.30.0}/src/sovereign/templates/resources.html +39 -36
- sovereign-0.30.0/src/sovereign/tracing.py +85 -0
- sovereign-0.30.0/src/sovereign/utils/crypto/suites/base_cipher.py +21 -0
- {sovereign-0.29.3 → sovereign-0.30.0}/src/sovereign/utils/dictupdate.py +2 -1
- {sovereign-0.29.3 → sovereign-0.30.0}/src/sovereign/views/admin.py +1 -0
- {sovereign-0.29.3 → sovereign-0.30.0}/src/sovereign/views/crypto.py +2 -1
- {sovereign-0.29.3 → sovereign-0.30.0}/src/sovereign/views/healthchecks.py +2 -1
- {sovereign-0.29.3 → sovereign-0.30.0}/src/sovereign/views/interface.py +22 -6
- sovereign-0.29.3/src/sovereign/configuration.py +0 -66
- sovereign-0.29.3/src/sovereign/templates/ul_filter.html +0 -22
- sovereign-0.29.3/src/sovereign/tracing.py +0 -85
- sovereign-0.29.3/src/sovereign/utils/crypto/suites/base_cipher.py +0 -26
- {sovereign-0.29.3 → sovereign-0.30.0}/LICENSE.txt +0 -0
- {sovereign-0.29.3 → sovereign-0.30.0}/src/sovereign/constants.py +0 -0
- {sovereign-0.29.3 → sovereign-0.30.0}/src/sovereign/dynamic_config/__init__.py +0 -0
- {sovereign-0.29.3 → sovereign-0.30.0}/src/sovereign/error_info.py +0 -0
- {sovereign-0.29.3 → sovereign-0.30.0}/src/sovereign/logging/types.py +0 -0
- {sovereign-0.29.3 → sovereign-0.30.0}/src/sovereign/modifiers/__init__.py +0 -0
- {sovereign-0.29.3 → sovereign-0.30.0}/src/sovereign/response_class.py +0 -0
- {sovereign-0.29.3 → sovereign-0.30.0}/src/sovereign/server.py +0 -0
- {sovereign-0.29.3 → sovereign-0.30.0}/src/sovereign/sources/__init__.py +0 -0
- {sovereign-0.29.3 → sovereign-0.30.0}/src/sovereign/sources/file.py +0 -0
- {sovereign-0.29.3 → sovereign-0.30.0}/src/sovereign/static/sass/style.scss +0 -0
- {sovereign-0.29.3 → sovereign-0.30.0}/src/sovereign/static/style.css +0 -0
- {sovereign-0.29.3 → sovereign-0.30.0}/src/sovereign/statistics.py +0 -0
- {sovereign-0.29.3 → sovereign-0.30.0}/src/sovereign/templates/base.html +0 -0
- {sovereign-0.29.3 → sovereign-0.30.0}/src/sovereign/templates/err.html +0 -0
- {sovereign-0.29.3 → sovereign-0.30.0}/src/sovereign/testing/loaders.py +0 -0
- {sovereign-0.29.3 → sovereign-0.30.0}/src/sovereign/testing/modifiers.py +0 -0
- {sovereign-0.29.3 → sovereign-0.30.0}/src/sovereign/utils/__init__.py +0 -0
- {sovereign-0.29.3 → sovereign-0.30.0}/src/sovereign/utils/auth.py +0 -0
- {sovereign-0.29.3 → sovereign-0.30.0}/src/sovereign/utils/crypto/__init__.py +0 -0
- {sovereign-0.29.3 → sovereign-0.30.0}/src/sovereign/utils/crypto/crypto.py +0 -0
- {sovereign-0.29.3 → sovereign-0.30.0}/src/sovereign/utils/crypto/suites/__init__.py +0 -0
- {sovereign-0.29.3 → sovereign-0.30.0}/src/sovereign/utils/crypto/suites/aes_gcm_cipher.py +0 -0
- {sovereign-0.29.3 → sovereign-0.30.0}/src/sovereign/utils/crypto/suites/disabled_cipher.py +0 -0
- {sovereign-0.29.3 → sovereign-0.30.0}/src/sovereign/utils/crypto/suites/fernet_cipher.py +0 -0
- {sovereign-0.29.3 → sovereign-0.30.0}/src/sovereign/utils/eds.py +0 -0
- {sovereign-0.29.3 → sovereign-0.30.0}/src/sovereign/utils/entry_point_loader.py +0 -0
- {sovereign-0.29.3 → sovereign-0.30.0}/src/sovereign/utils/mock.py +0 -0
- {sovereign-0.29.3 → sovereign-0.30.0}/src/sovereign/utils/resources.py +0 -0
- {sovereign-0.29.3 → sovereign-0.30.0}/src/sovereign/utils/templates.py +0 -0
- {sovereign-0.29.3 → sovereign-0.30.0}/src/sovereign/utils/timer.py +0 -0
- {sovereign-0.29.3 → sovereign-0.30.0}/src/sovereign/utils/version_info.py +0 -0
- {sovereign-0.29.3 → sovereign-0.30.0}/src/sovereign/utils/weighted_clusters.py +0 -0
- {sovereign-0.29.3 → sovereign-0.30.0}/src/sovereign/views/__init__.py +0 -0
- {sovereign-0.29.3 → 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.
|
|
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
|
|
@@ -19,6 +19,7 @@ Classifier: Operating System :: POSIX :: Linux
|
|
|
19
19
|
Classifier: Programming Language :: Python :: 3
|
|
20
20
|
Classifier: Programming Language :: Python :: 3.11
|
|
21
21
|
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
22
23
|
Classifier: Programming Language :: Python :: 3.10
|
|
23
24
|
Classifier: Programming Language :: Python :: 3.8
|
|
24
25
|
Classifier: Programming Language :: Python :: 3.9
|
|
@@ -40,70 +41,80 @@ Requires-Dist: cashews[redis] (>=6.3.0,<7.0.0) ; extra == "caching"
|
|
|
40
41
|
Requires-Dist: croniter (>=1.4.1,<2.0.0)
|
|
41
42
|
Requires-Dist: cryptography (>=42.0.0,<43.0.0)
|
|
42
43
|
Requires-Dist: datadog (>=0.47.0,<0.48.0) ; extra == "statsd"
|
|
43
|
-
Requires-Dist: fastapi (>=0.
|
|
44
|
+
Requires-Dist: fastapi (>=0.115.2,<0.116.0)
|
|
44
45
|
Requires-Dist: glom (>=23.3.0,<24.0.0)
|
|
45
46
|
Requires-Dist: gunicorn (>=22.0.0,<23.0.0)
|
|
46
47
|
Requires-Dist: httptools (>=0.6.0,<0.7.0) ; extra == "httptools"
|
|
47
48
|
Requires-Dist: orjson (>=3.9.15,<4.0.0) ; extra == "orjson"
|
|
48
49
|
Requires-Dist: pydantic (>=2.7.2,<3.0.0)
|
|
49
|
-
Requires-Dist: pydantic-settings (
|
|
50
|
+
Requires-Dist: pydantic-settings (<2.6.0)
|
|
50
51
|
Requires-Dist: redis (<=5.0.0)
|
|
51
52
|
Requires-Dist: requests (>=2.31.0,<3.0.0)
|
|
52
53
|
Requires-Dist: sentry-sdk (>=2.14.0,<3.0.0) ; extra == "sentry"
|
|
54
|
+
Requires-Dist: starlette-context (>=0.3.6,<0.4.0)
|
|
53
55
|
Requires-Dist: structlog (>=23.1.0,<24.0.0)
|
|
54
56
|
Requires-Dist: ujson (>=5.8.0,<6.0.0) ; extra == "ujson"
|
|
55
57
|
Requires-Dist: uvicorn (>=0.23.2,<0.24.0)
|
|
56
58
|
Requires-Dist: uvloop (>=0.19.0,<0.20.0)
|
|
57
|
-
Project-URL: Documentation, https://
|
|
59
|
+
Project-URL: Documentation, https://developer.atlassian.com/platform/sovereign/
|
|
58
60
|
Project-URL: Repository, https://bitbucket.org/atlassian/sovereign/src/master/
|
|
59
61
|
Description-Content-Type: text/markdown
|
|
60
62
|
|
|
61
63
|
sovereign
|
|
62
64
|
=========
|
|
63
65
|
|
|
66
|
+
|
|
64
67
|
Mission statement
|
|
65
68
|
-----------------
|
|
66
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)
|
|
67
70
|
|
|
68
|
-
The purpose of `sovereign` is to supply downstream envoy proxies with
|
|
69
|
-
|
|
71
|
+
The purpose of `sovereign` is to supply downstream envoy proxies with dynamic configuration.
|
|
72
|
+
|
|
70
73
|
|
|
71
74
|
Mechanism of Operation
|
|
72
75
|
----------------------
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
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.
|
|
79
86
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
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.
|
|
84
90
|
|
|
85
|
-
This is performed in a semi-stateless way, where the only state is data cached in memory.
|
|
86
91
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
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
|
+
|
|
90
98
|
|
|
91
|
-
|
|
92
|
-
|
|
99
|
+
Release
|
|
100
|
+
------------
|
|
101
|
+
See [RELEASE.md]
|
|
93
102
|
|
|
94
|
-
Both modifiers and sources are pluggable, i.e. it's easy to write your own and
|
|
95
|
-
plug them into Sovereign for your use-case.
|
|
96
103
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
104
|
+
Roadmap
|
|
105
|
+
------------
|
|
106
|
+
* Performance improvements
|
|
107
|
+
* Data persistence
|
|
108
|
+
* Push API (versus polling)
|
|
109
|
+
* Client for Sovereign
|
|
110
|
+
* gRPC
|
|
100
111
|
|
|
101
|
-
The JSON configuration can be viewed in real-time with Sovereign's read-only web interface.
|
|
102
112
|
|
|
103
113
|
Requirements
|
|
104
114
|
------------
|
|
105
115
|
* Python 3.8+
|
|
106
116
|
|
|
117
|
+
|
|
107
118
|
Installation
|
|
108
119
|
------------
|
|
109
120
|
```
|
|
@@ -112,62 +123,52 @@ pip install sovereign
|
|
|
112
123
|
|
|
113
124
|
Documentation
|
|
114
125
|
-------------
|
|
115
|
-
[Read the docs here!](https://
|
|
126
|
+
[Read the docs here!](https://developer.atlassian.com/platform/sovereign/)
|
|
116
127
|
|
|
117
|
-
:new: Read-only user interface
|
|
118
|
-
------------------------
|
|
119
|
-
Added in `v0.5.3`!
|
|
120
128
|
|
|
121
|
-
This interface allows you to browse the resources currently returned by Sovereign.
|
|
122
|
-
|
|
123
|
-

|
|
124
129
|
|
|
125
130
|
Local development
|
|
126
131
|
=================
|
|
127
132
|
|
|
133
|
+
|
|
128
134
|
Requirements
|
|
129
135
|
------------
|
|
136
|
+
* Poetry
|
|
130
137
|
* Docker
|
|
131
138
|
* Docker-compose
|
|
132
139
|
|
|
140
|
+
|
|
133
141
|
Installing dependencies for dev
|
|
134
142
|
-------------------------------
|
|
135
|
-
|
|
136
|
-
|
|
143
|
+
Dependencies and creation of virtualenv is handled by poetry
|
|
137
144
|
```
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
pip install -r requirements-dev.txt
|
|
145
|
+
poetry install
|
|
146
|
+
poetry shell
|
|
141
147
|
```
|
|
142
148
|
|
|
143
149
|
Running locally
|
|
144
150
|
---------------
|
|
145
151
|
Running the test env
|
|
146
|
-
|
|
147
152
|
```
|
|
148
153
|
make run
|
|
149
154
|
```
|
|
150
155
|
|
|
151
156
|
Running the test env daemonized
|
|
152
|
-
|
|
153
157
|
```
|
|
154
158
|
make run-daemon
|
|
155
159
|
```
|
|
156
160
|
|
|
157
161
|
Pylint
|
|
158
|
-
|
|
159
162
|
```
|
|
160
163
|
make lint
|
|
161
164
|
```
|
|
162
165
|
|
|
163
166
|
Unit tests
|
|
164
|
-
|
|
165
167
|
```
|
|
166
168
|
make unit
|
|
167
169
|
```
|
|
168
170
|
|
|
169
171
|
Acceptance tests
|
|
170
|
-
|
|
171
172
|
```
|
|
172
173
|
make run-daemon acceptance
|
|
173
174
|
```
|
|
@@ -175,7 +176,6 @@ make run-daemon acceptance
|
|
|
175
176
|
|
|
176
177
|
Contributors
|
|
177
178
|
============
|
|
178
|
-
|
|
179
179
|
Pull requests, issues and comments welcome. For pull requests:
|
|
180
180
|
|
|
181
181
|
* Add tests for new features and bug fixes
|
|
@@ -204,7 +204,6 @@ those contributing as an individual.
|
|
|
204
204
|
|
|
205
205
|
License
|
|
206
206
|
========
|
|
207
|
-
|
|
208
207
|
Copyright (c) 2018 Atlassian and others.
|
|
209
208
|
Apache 2.0 licensed, see [LICENSE.txt](LICENSE.txt) file.
|
|
210
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
|
-
|
|
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
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
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
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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
|
-
|
|
28
|
-
|
|
29
|
-
|
|
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
|
-
|
|
32
|
-
|
|
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
|
-
|
|
38
|
-
|
|
39
|
-
|
|
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://
|
|
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
|
-

|
|
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
|
-
|
|
76
|
-
|
|
81
|
+
Dependencies and creation of virtualenv is handled by poetry
|
|
77
82
|
```
|
|
78
|
-
|
|
79
|
-
|
|
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.
|
|
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://
|
|
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
|
|
|
@@ -74,7 +76,7 @@ structlog = "^23.1.0"
|
|
|
74
76
|
cachelib = "^0.10.2"
|
|
75
77
|
glom = "^23.3.0"
|
|
76
78
|
cryptography = "^42.0.0"
|
|
77
|
-
fastapi = "^0.
|
|
79
|
+
fastapi = "^0.115.2"
|
|
78
80
|
uvloop = "^0.19.0"
|
|
79
81
|
sentry-sdk = "^2.14.0"
|
|
80
82
|
boto3 = {version = "^1.28.62", optional = true}
|
|
@@ -87,7 +89,8 @@ redis = {version = "<= 5.0.0", optional = true}
|
|
|
87
89
|
httptools = {version = "^0.6.0", optional = true}
|
|
88
90
|
cachetools = "^5.3.2"
|
|
89
91
|
pydantic = "^2.7.2"
|
|
90
|
-
pydantic-settings = "
|
|
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
|
-
|
|
103
|
-
|
|
104
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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 =
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
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
|
|
99
|
-
poller.
|
|
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
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
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:
|