sovereign 0.19.3__py3-none-any.whl → 1.0.0b148__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.

Files changed (80) hide show
  1. sovereign/__init__.py +13 -81
  2. sovereign/app.py +59 -48
  3. sovereign/cache/__init__.py +172 -0
  4. sovereign/cache/backends/__init__.py +110 -0
  5. sovereign/cache/backends/s3.py +143 -0
  6. sovereign/cache/filesystem.py +73 -0
  7. sovereign/cache/types.py +15 -0
  8. sovereign/configuration.py +573 -0
  9. sovereign/constants.py +1 -0
  10. sovereign/context.py +271 -104
  11. sovereign/dynamic_config/__init__.py +113 -0
  12. sovereign/dynamic_config/deser.py +78 -0
  13. sovereign/dynamic_config/loaders.py +120 -0
  14. sovereign/events.py +49 -0
  15. sovereign/logging/access_logger.py +85 -0
  16. sovereign/logging/application_logger.py +54 -0
  17. sovereign/logging/base_logger.py +41 -0
  18. sovereign/logging/bootstrapper.py +36 -0
  19. sovereign/logging/types.py +10 -0
  20. sovereign/middlewares.py +8 -7
  21. sovereign/modifiers/lib.py +1 -0
  22. sovereign/rendering.py +192 -0
  23. sovereign/response_class.py +18 -0
  24. sovereign/server.py +93 -35
  25. sovereign/sources/file.py +1 -1
  26. sovereign/sources/inline.py +1 -0
  27. sovereign/sources/lib.py +1 -0
  28. sovereign/sources/poller.py +296 -53
  29. sovereign/statistics.py +17 -20
  30. sovereign/templates/base.html +59 -46
  31. sovereign/templates/resources.html +203 -102
  32. sovereign/testing/loaders.py +8 -0
  33. sovereign/{modifiers/test.py → testing/modifiers.py} +0 -2
  34. sovereign/tracing.py +102 -0
  35. sovereign/types.py +299 -0
  36. sovereign/utils/auth.py +26 -13
  37. sovereign/utils/crypto/__init__.py +0 -0
  38. sovereign/utils/crypto/crypto.py +135 -0
  39. sovereign/utils/crypto/suites/__init__.py +21 -0
  40. sovereign/utils/crypto/suites/aes_gcm_cipher.py +42 -0
  41. sovereign/utils/crypto/suites/base_cipher.py +21 -0
  42. sovereign/utils/crypto/suites/disabled_cipher.py +25 -0
  43. sovereign/utils/crypto/suites/fernet_cipher.py +29 -0
  44. sovereign/utils/dictupdate.py +2 -1
  45. sovereign/utils/eds.py +37 -21
  46. sovereign/utils/mock.py +54 -16
  47. sovereign/utils/resources.py +17 -0
  48. sovereign/utils/version_info.py +8 -0
  49. sovereign/views/__init__.py +4 -0
  50. sovereign/views/api.py +61 -0
  51. sovereign/views/crypto.py +46 -15
  52. sovereign/views/discovery.py +37 -116
  53. sovereign/views/healthchecks.py +87 -18
  54. sovereign/views/interface.py +112 -112
  55. sovereign/worker.py +204 -0
  56. {sovereign-0.19.3.dist-info → sovereign-1.0.0b148.dist-info}/METADATA +79 -76
  57. sovereign-1.0.0b148.dist-info/RECORD +77 -0
  58. {sovereign-0.19.3.dist-info → sovereign-1.0.0b148.dist-info}/WHEEL +1 -1
  59. sovereign-1.0.0b148.dist-info/entry_points.txt +38 -0
  60. sovereign_files/__init__.py +0 -0
  61. sovereign_files/static/darkmode.js +51 -0
  62. sovereign_files/static/node_expression.js +42 -0
  63. sovereign_files/static/panel.js +76 -0
  64. sovereign_files/static/resources.css +246 -0
  65. sovereign_files/static/resources.js +642 -0
  66. sovereign_files/static/sass/style.scss +33 -0
  67. sovereign_files/static/style.css +16143 -0
  68. sovereign_files/static/style.css.map +1 -0
  69. sovereign/config_loader.py +0 -225
  70. sovereign/discovery.py +0 -175
  71. sovereign/logs.py +0 -131
  72. sovereign/schemas.py +0 -780
  73. sovereign/static/sass/style.scss +0 -27
  74. sovereign/static/style.css +0 -13553
  75. sovereign/templates/ul_filter.html +0 -22
  76. sovereign/utils/crypto.py +0 -103
  77. sovereign/views/admin.py +0 -120
  78. sovereign-0.19.3.dist-info/LICENSE.txt +0 -13
  79. sovereign-0.19.3.dist-info/RECORD +0 -47
  80. sovereign-0.19.3.dist-info/entry_points.txt +0 -10
@@ -1,13 +1,13 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: sovereign
3
- Version: 0.19.3
3
+ Version: 1.0.0b148
4
4
  Summary: Envoy Proxy control-plane written in Python
5
- Home-page: https://pypi.org/project/sovereign/
6
- License: Apache-2.0
7
- Keywords: envoy,envoyproxy,control-plane,management,server
8
- Author: Vasili Syrakis
9
- Author-email: vsyrakis@atlassian.com
10
- Requires-Python: >=3.11,<4.0
5
+ Project-URL: Homepage, https://pypi.org/project/sovereign/
6
+ Project-URL: Repository, https://bitbucket.org/atlassian/sovereign/src/master/
7
+ Project-URL: Documentation, https://developer.atlassian.com/platform/sovereign/
8
+ Author-email: Vasili Syrakis <vsyrakis@atlassian.com>
9
+ License-Expression: Apache-2.0
10
+ Keywords: control-plane,envoy,envoyproxy,management,server
11
11
  Classifier: Development Status :: 5 - Production/Stable
12
12
  Classifier: Environment :: No Input/Output (Daemon)
13
13
  Classifier: Intended Audience :: Developers
@@ -16,87 +16,102 @@ Classifier: Intended Audience :: System Administrators
16
16
  Classifier: License :: OSI Approved :: Apache Software License
17
17
  Classifier: Natural Language :: English
18
18
  Classifier: Operating System :: POSIX :: Linux
19
- Classifier: Programming Language :: Python :: 3
20
- Classifier: Programming Language :: Python :: 3.11
21
19
  Classifier: Programming Language :: Python :: 3.8
20
+ Classifier: Programming Language :: Python :: 3.9
21
+ Classifier: Programming Language :: Python :: 3.10
22
+ Classifier: Programming Language :: Python :: 3.11
22
23
  Classifier: Topic :: Internet :: Proxy Servers
24
+ Requires-Python: <4.0,>=3.11.0
25
+ Requires-Dist: aiofiles<24,>=23.2.1
26
+ Requires-Dist: cachelib<0.11,>=0.10.2
27
+ Requires-Dist: cachetools<6,>=5.3.2
28
+ Requires-Dist: croniter<2,>=1.4.1
29
+ Requires-Dist: cryptography>=45.0.2
30
+ Requires-Dist: fastapi<0.117,>=0.116.0
31
+ Requires-Dist: glom<24,>=23.3.0
32
+ Requires-Dist: h11<0.17,>=0.16.0
33
+ Requires-Dist: jinja2<4,>=3.1.2
34
+ Requires-Dist: jmespath<2,>=1.0.1
35
+ Requires-Dist: pydantic-settings<2.6.0
36
+ Requires-Dist: pydantic<3,>=2.7.2
37
+ Requires-Dist: pyyaml<7,>=6.0.1
38
+ Requires-Dist: requests<3,>=2.32.4
39
+ Requires-Dist: starlette-context<0.4,>=0.3.6
40
+ Requires-Dist: starlette<0.48,>=0.47.2
41
+ Requires-Dist: structlog<24,>=23.1.0
42
+ Requires-Dist: supervisor<5,>=4.2.5
43
+ Requires-Dist: uvicorn<0.24,>=0.23.2
44
+ Requires-Dist: uvloop<1.0,>0.19.0
23
45
  Provides-Extra: boto
46
+ Requires-Dist: boto3<2,>=1.28.62; extra == 'boto'
24
47
  Provides-Extra: caching
25
48
  Provides-Extra: httptools
49
+ Requires-Dist: httptools<0.7,>=0.6.0; extra == 'httptools'
26
50
  Provides-Extra: orjson
51
+ Requires-Dist: orjson<4,>=3.9.15; extra == 'orjson'
27
52
  Provides-Extra: sentry
53
+ Requires-Dist: sentry-sdk<3,>=2.14.0; extra == 'sentry'
28
54
  Provides-Extra: statsd
55
+ Requires-Dist: datadog>=0.50.1; extra == 'statsd'
29
56
  Provides-Extra: ujson
30
- Requires-Dist: Jinja2 (>=3.1.2,<4.0.0)
31
- Requires-Dist: PyYAML (>=6.0.1,<7.0.0)
32
- Requires-Dist: aiofiles (>=23.1.0,<24.0.0)
33
- Requires-Dist: boto3 (>=1.26.136,<2.0.0) ; extra == "boto"
34
- Requires-Dist: cachelib (>=0.10.2,<0.11.0)
35
- Requires-Dist: cashews[redis] (>=6.1.0,<7.0.0) ; extra == "caching"
36
- Requires-Dist: croniter (>=1.3.14,<2.0.0)
37
- Requires-Dist: cryptography (>=41.0.2,<42.0.0)
38
- Requires-Dist: datadog (>=0.45.0,<0.46.0) ; extra == "statsd"
39
- Requires-Dist: fastapi (>=0.95.2,<0.96.0)
40
- Requires-Dist: glom (>=23.3.0,<24.0.0)
41
- Requires-Dist: gunicorn (>=20.1.0,<21.0.0)
42
- Requires-Dist: httptools (>=0.5.0,<0.6.0) ; extra == "httptools"
43
- Requires-Dist: orjson (>=3.8.12,<4.0.0) ; extra == "orjson"
44
- Requires-Dist: requests (>=2.30.0,<3.0.0)
45
- Requires-Dist: sentry-sdk (>=1.23.1,<2.0.0) ; extra == "sentry"
46
- Requires-Dist: structlog (==21.5.0)
47
- Requires-Dist: ujson (>=5.7.0,<6.0.0) ; extra == "ujson"
48
- Requires-Dist: uvicorn (>=0.22.0,<0.23.0)
49
- Requires-Dist: uvloop (>=0.17.0,<0.18.0)
50
- Project-URL: Documentation, https://vsyrakis.bitbucket.io/sovereign/docs/
51
- Project-URL: Repository, https://bitbucket.org/atlassian/sovereign/src/master/
57
+ Requires-Dist: ujson<6,>=5.8.0; extra == 'ujson'
52
58
  Description-Content-Type: text/markdown
53
59
 
54
60
  sovereign
55
61
  =========
56
62
 
63
+
57
64
  Mission statement
58
65
  -----------------
59
66
  This project implements a JSON control-plane based on the [envoy](https://envoyproxy.io) [data-plane-api](https://github.com/envoyproxy/data-plane-api)
60
67
 
61
- The purpose of `sovereign` is to supply downstream envoy proxies with
62
- configuration in near-realtime by responding to discovery requests.
68
+ The purpose of `sovereign` is to supply downstream envoy proxies with dynamic configuration.
69
+
63
70
 
64
71
  Mechanism of Operation
65
72
  ----------------------
66
- tl;dr version:
67
- ```
68
- * Polls HTTP/File/Other for data
69
- * (optional) Applies transforms to the data
70
- * Uses the data to generate Envoy configuration from templates
71
- ```
73
+ Sovereign allows you to define templates that represent each resource type
74
+ provided by Envoy. For example, clusters, routes, listeners, secrets,
75
+ extension_configs, etc.
76
+
77
+ In order to enrich the templates with data, Sovereign has ways of polling data
78
+ out-of-band which it then includes as variables that can be accessed within the
79
+ templates.
72
80
 
73
- In a nutshell, Sovereign
74
- gathers contextual data (*"sources"* and *"template context"*),
75
- optionally applies transforms to that data (using *"modifiers"*) and finally
76
- uses the data to generate envoy configuration from either python code, or jinja2 templates.
81
+ This allows Sovereign to provide configuration to Envoy that changes over time
82
+ depending on the data sources, without needing to redeploy the control-plane.
77
83
 
78
- This is performed in a semi-stateless way, where the only state is data cached in memory.
84
+ Sovereign provides some built-in ways of polling data (such as over HTTP, or
85
+ on-disk) but also exposes extension points, allowing you to write your own
86
+ plugins in Python.
79
87
 
80
- Template context is intended to be statically configured, whereas *Sources*
81
- are meant to be dynamic - for example, fetching from an API, an S3 bucket,
82
- or a file that receives updates.
83
88
 
84
- *Modifiers* can mutate the data retrieved from sources, just in case the data
85
- is in a less than favorable structure.
89
+ Support
90
+ ------------
91
+ [Submit new issues here](https://bitbucket.org/atlassian/sovereign/issues/new)
92
+
93
+ If you're unable to submit an issue on Bitbucket, send an email to [vsyrakis@atlassian.com](mailto:vsyrakis@atlassian.com)
94
+
95
+
96
+ Release
97
+ ------------
98
+ See [RELEASE.md]
86
99
 
87
- Both modifiers and sources are pluggable, i.e. it's easy to write your own and
88
- plug them into Sovereign for your use-case.
89
100
 
90
- Currently, Sovereign supports only providing configuration to Envoy as JSON.
91
- That is to say, gRPC is not supported yet. Contributions in this area are highly
92
- appreciated!
101
+ Roadmap
102
+ ------------
103
+ * Performance improvements
104
+ * Data persistence
105
+ * Push API (versus polling)
106
+ * Client for Sovereign
107
+ * gRPC
93
108
 
94
- The JSON configuration can be viewed in real-time with Sovereign's read-only web interface.
95
109
 
96
110
  Requirements
97
111
  ------------
98
112
  * Python 3.8+
99
113
 
114
+
100
115
  Installation
101
116
  ------------
102
117
  ```
@@ -105,62 +120,53 @@ pip install sovereign
105
120
 
106
121
  Documentation
107
122
  -------------
108
- [Read the docs here!](https://vsyrakis.bitbucket.io/sovereign/docs/)
123
+ [Read the docs here!](https://developer.atlassian.com/platform/sovereign/)
109
124
 
110
- :new: Read-only user interface
111
- ------------------------
112
- Added in `v0.5.3`!
113
125
 
114
- This interface allows you to browse the resources currently returned by Sovereign.
115
-
116
- ![Sovereign User Interface Screenshot](https://bitbucket.org/atlassian/sovereign/src/master/assets/sovereign_ui.png)
117
126
 
118
127
  Local development
119
128
  =================
120
129
 
130
+
121
131
  Requirements
122
132
  ------------
133
+ * uv
123
134
  * Docker
124
135
  * Docker-compose
125
136
 
137
+
126
138
  Installing dependencies for dev
127
139
  -------------------------------
128
- I recommend creating a virtualenv before doing any dev work
129
-
140
+ Dependencies and creation of virtualenv is handled by uv
130
141
  ```
131
- python3 -m venv venv
132
- source venv/bin/activate
133
- pip install -r requirements-dev.txt
142
+ uv sync
143
+ uv venv activate
144
+ uv run <command>
134
145
  ```
135
146
 
136
147
  Running locally
137
148
  ---------------
138
149
  Running the test env
139
-
140
150
  ```
141
151
  make run
142
152
  ```
143
153
 
144
154
  Running the test env daemonized
145
-
146
155
  ```
147
156
  make run-daemon
148
157
  ```
149
158
 
150
159
  Pylint
151
-
152
160
  ```
153
161
  make lint
154
162
  ```
155
163
 
156
164
  Unit tests
157
-
158
165
  ```
159
166
  make unit
160
167
  ```
161
168
 
162
169
  Acceptance tests
163
-
164
170
  ```
165
171
  make run-daemon acceptance
166
172
  ```
@@ -168,7 +174,6 @@ make run-daemon acceptance
168
174
 
169
175
  Contributors
170
176
  ============
171
-
172
177
  Pull requests, issues and comments welcome. For pull requests:
173
178
 
174
179
  * Add tests for new features and bug fixes
@@ -197,9 +202,7 @@ those contributing as an individual.
197
202
 
198
203
  License
199
204
  ========
200
-
201
205
  Copyright (c) 2018 Atlassian and others.
202
206
  Apache 2.0 licensed, see [LICENSE.txt](LICENSE.txt) file.
203
207
 
204
208
 
205
-
@@ -0,0 +1,77 @@
1
+ sovereign/__init__.py,sha256=9fOh4r27OcCcKWKvNBp3CcHmADJhc1sJIi7qsbNY97g,1069
2
+ sovereign/app.py,sha256=07CJEiqCMlz9R32r0_nh9Y426uztw1tY81mBCgEOeoY,5030
3
+ sovereign/configuration.py,sha256=lBRUyep4VBRj1VDDfOhYv50kH7qup_Di6HQQn6XOHrs,20053
4
+ sovereign/constants.py,sha256=qdWD1lTvkaW5JGF7TmZhfksQHlRAJFVqbG7v6JQA9k8,46
5
+ sovereign/context.py,sha256=m2-VAZANSlnLbcJ6mmTl2XipE6l-BXyYeQiy3WN8jtY,9077
6
+ sovereign/error_info.py,sha256=r2KXBYq9Fo7AI2pmIpATWFm0pykr2MqfrKH0WWW5Sfk,1488
7
+ sovereign/events.py,sha256=8WEIJo0C7mnx-pLjOTXPUFWYySvVXqDsj6p2e9LR9Jg,1203
8
+ sovereign/middlewares.py,sha256=6w4JpvtNGvQA4rocQsYQjuu-ckhpKT6gKYA16T-kiqA,3082
9
+ sovereign/rendering.py,sha256=kzNSv6Rszz-sy5rCAL9hq3Z7xvqcT39BnXPNxv58pQs,6940
10
+ sovereign/response_class.py,sha256=beMAFV-4L6DwyWzJzy71GkEW4gb7fzH1jd8-Tul13cU,427
11
+ sovereign/server.py,sha256=6aZEaGn1RibMMqJ1uBDvaXKsw9-DCRiyp9j9TNkPyo8,2985
12
+ sovereign/statistics.py,sha256=wZ7skpaKE4Zk8jvFpVdrSFqlW_hG8qWH3HE5pYeBhP0,2044
13
+ sovereign/tracing.py,sha256=egA8O5VryajsI90NXVdQVVT7sGWIrclgEd559qznDn0,2685
14
+ sovereign/types.py,sha256=u0BYH5ldcvGMCJrY_zWffDpo2gd8GSJV5eGMDwuuCHg,9898
15
+ sovereign/worker.py,sha256=dzXd3fckYYcKVKv_-3YnZf40o1Z5cMvA6a1DMV85Sw4,6072
16
+ sovereign/cache/__init__.py,sha256=UjcRkreQrm0FcBmaZ0868eYffIueZ_rDG3ToxzounqU,6337
17
+ sovereign/cache/filesystem.py,sha256=LrywZkmiV_SCdpu4nz6ru4LdbaJPtkD2Wn4RBuZstDw,2395
18
+ sovereign/cache/types.py,sha256=UdJRlARVLWidFWEfMvaa5NnGHONCGB-xStbFdBb2B-M,241
19
+ sovereign/cache/backends/__init__.py,sha256=6mPpf9OzyCBvRqpZzIBNy6jrDimEmg8yIiUYpNVTkQk,3160
20
+ sovereign/cache/backends/s3.py,sha256=LoChgNI_Ht1gg9K3RiN2tL41ANHke9GIlESs6loo7MI,5206
21
+ sovereign/dynamic_config/__init__.py,sha256=NXCG_-IM_TKCApJns-GsZka8jv_EqKUiF5S8kRSd7Y0,3547
22
+ sovereign/dynamic_config/deser.py,sha256=N3iUvDpuNHWjxUbGFydMVKicx4o8DyfvNukorqnQdt8,1834
23
+ sovereign/dynamic_config/loaders.py,sha256=gPkxTL7gep20HIMRvjgOqAdUWqtb3970VBCAcUrIM4c,2915
24
+ sovereign/logging/access_logger.py,sha256=QVjrN6tmAemmCQ1NDWoarVrl7vogaHoCPL7SjwjthNk,2989
25
+ sovereign/logging/application_logger.py,sha256=BAEmm9Iszz9AL3a32g8t6fTbgZTzJuN5zyZB2kNaj78,1806
26
+ sovereign/logging/base_logger.py,sha256=ScOzHs8Rt1RZaUZGvaJSAlDEjD0BxkD5sLKSm2GgM0I,1243
27
+ sovereign/logging/bootstrapper.py,sha256=2eawwirMH_3gN3K8Gy9DZojBnk38NQaccCrvdMqPO4M,1302
28
+ sovereign/logging/types.py,sha256=rGqJAEVvgvzHy4aPfvEH6yQ-yblXNkEcWG7G8l9ALEA,282
29
+ sovereign/modifiers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
30
+ sovereign/modifiers/lib.py,sha256=Cx0VrpTKbSjb3YmHyG4Jy6YEaPlrwpeqNaom3zu1_hw,2885
31
+ sovereign/sources/__init__.py,sha256=g9hEpFk8j5i1ApHQpbc9giTyJW41Ppgsqv5P9zGxOJk,78
32
+ sovereign/sources/file.py,sha256=prUThsDCSPNwZaZpkKXhAm-GVRZWbBoGKGU0It4HHXs,690
33
+ sovereign/sources/inline.py,sha256=pP77m7bHjqE3sSoqZthcuw1ARVMf9gooVwbz4B8OAek,1003
34
+ sovereign/sources/lib.py,sha256=0hk_G6mKJrB65WokVZnqF5kdJ3vsQZMNPuJqJO0mBsI,1031
35
+ sovereign/sources/poller.py,sha256=Cy3zx3xS2JcihOlZ16Nymkw3SWQAgOLjeSWsw2K9IPI,19347
36
+ sovereign/templates/base.html,sha256=MMhhvvClTixKibYfhXm8Ezx6ttu6Sqki44niciCPMO4,2990
37
+ sovereign/templates/err.html,sha256=a3cEzOqyqWOIe3YxfTEjkxbTfxBxq1knD6GwzEFljfs,603
38
+ sovereign/templates/resources.html,sha256=5MfXHW8s3tAWda66Q48zVgDhZNLwHGsdCKkKHLZohIs,10420
39
+ sovereign/testing/loaders.py,sha256=mcmErhI9ZkJUBZl8jv2qP-PCBRFeAIgyBFlfCgU4Vvk,199
40
+ sovereign/testing/modifiers.py,sha256=YI0aJOEbb1C_1T5VDrZKyLopk8JiIlKtUtxXMFfsCtk,290
41
+ sovereign/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
42
+ sovereign/utils/auth.py,sha256=7cc-WrIJBWfUkF5xvV98rRDU8BcKVL1ERinDqNqTGs0,2286
43
+ sovereign/utils/dictupdate.py,sha256=Bi7QaC7en-k3EOepwNJqpOKRNBgp6ZsBZVOvH_0nMtc,2558
44
+ sovereign/utils/eds.py,sha256=QkBf-_zOj3w5-fJkhvr_uYeltpLn5kiCj-A2bRPsCig,4389
45
+ sovereign/utils/entry_point_loader.py,sha256=BEVodk-um70RvT1nSOu_IB-hr1K4ppthXod0VZEiZJ8,526
46
+ sovereign/utils/mock.py,sha256=U0ydUX9Tv4dUOjd96tsXMUqiZ-i6S2CFOny3uo4h6_Q,2395
47
+ sovereign/utils/resources.py,sha256=rPrWgcIt4YhV-Dz88_kr5WrQNiSKt-jTlOZ8EIJxJx8,472
48
+ sovereign/utils/templates.py,sha256=FE_H_oE7VrS3X_VN1z_g10b9-rpmi1_gL-cMxi5XtXU,1057
49
+ sovereign/utils/timer.py,sha256=_dUtEasj0BKbWYuQ_T3HFIyjurXXj-La-dNSMAwKMSo,795
50
+ sovereign/utils/version_info.py,sha256=adBfu0z6jsg8E5-BIUjZyBwZvfLASj7fpCpYeIvBeMY,576
51
+ sovereign/utils/weighted_clusters.py,sha256=bPzuRE7Qgvv04HcR2AhMDvBrFlZ8AfteweLKhY9SvWg,1166
52
+ sovereign/utils/crypto/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
53
+ sovereign/utils/crypto/crypto.py,sha256=FMo4TikqWcPJ5fyc6j2WEHkkwZU3WY3qJKr7VLfckv0,4532
54
+ sovereign/utils/crypto/suites/__init__.py,sha256=smMvNa1VsQ0PvsNj6lnRNh4ktB7dMnas1CqeTOFqgGA,526
55
+ sovereign/utils/crypto/suites/aes_gcm_cipher.py,sha256=Yjfj1LCQDGTzHBjrZR3-koh29L_N34v65kPoIfta0aw,1239
56
+ sovereign/utils/crypto/suites/base_cipher.py,sha256=kUOZh_ZIILyo5zv99-qzbJZDpeMmt76vhkBDEPvAt4A,454
57
+ sovereign/utils/crypto/suites/disabled_cipher.py,sha256=0_vzydVdVIUlX4pYEAMgB_RvHpyZ25uDC4pz1jRJ5wE,573
58
+ sovereign/utils/crypto/suites/fernet_cipher.py,sha256=rP6M5ys1vctyadOxDGNFoyerWPUOunLQdZ2jjS1pxzc,701
59
+ sovereign/views/__init__.py,sha256=oe_kK9egBp9jghG4EujFsAx6c2-eeZurjEtQ3dTlJRo,59
60
+ sovereign/views/api.py,sha256=gKz3ad1tdKlL1Dg01yRu6X2A5Fs_PJbDwpEHy-M-yek,2239
61
+ sovereign/views/crypto.py,sha256=nGD0Bac6jQeK8u0Qe71EJfbY1a-rYqN7wz7BulrOrFw,3366
62
+ sovereign/views/discovery.py,sha256=tR1D1HX8PyZdzjC1XdqYs8-YWeSYZMoJ1Npow5PC_Gc,2512
63
+ sovereign/views/healthchecks.py,sha256=Md4UTiZE9JoZJofrPM2jV-9bJfxDiViRSQmoyTw7SO0,3447
64
+ sovereign/views/interface.py,sha256=ZOnYCxyab6VagwCewQL3oBDaCqgoQRcE32h3ui9uZFw,7241
65
+ sovereign_files/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
66
+ sovereign_files/static/darkmode.js,sha256=3ip-eKGctDvNhN7UgmaHhzls7r5qIY-Jvh2EpefHbQ0,1449
67
+ sovereign_files/static/node_expression.js,sha256=GKxKTSRc_96IbL3H4L_31ueJFXq4N7scm5R1RNqxP24,1489
68
+ sovereign_files/static/panel.js,sha256=i5mGExjv-I4Gtt9dQiTyFwPZa8pg5rXeuTeidXNUiTE,2695
69
+ sovereign_files/static/resources.css,sha256=Rt_ir_FkoI-VIAOqPhk0vILy8kB2egAYbQU26SOs1io,4500
70
+ sovereign_files/static/resources.js,sha256=-TaXZ6tohyKA1SkX5YwrTcV5M8mOZ68cvEXpvZWznTo,24506
71
+ sovereign_files/static/style.css,sha256=kmvkJ2820RKehWxhddkucbgFkvnpUgBMteOtpEuXjvQ,601347
72
+ sovereign_files/static/style.css.map,sha256=h1ufjfDVX-8z-FuJqFG2-U9AVdi66U-e8uyiGdUZjDw,66576
73
+ sovereign_files/static/sass/style.scss,sha256=LdGXXuHi_tyMc7XhijIOrlIxyfLt827AAs2Z7DYpFpg,990
74
+ sovereign-1.0.0b148.dist-info/METADATA,sha256=oem0ksW8OtXbGl21BjKSJUi4sKmVqWjXCtIYrAUnHX0,5917
75
+ sovereign-1.0.0b148.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
76
+ sovereign-1.0.0b148.dist-info/entry_points.txt,sha256=Rt_U9pHxxYT132TIfj6ESPKxfM0d5hByvggUcuFk_NI,1526
77
+ sovereign-1.0.0b148.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 1.6.1
2
+ Generator: hatchling 1.28.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -0,0 +1,38 @@
1
+ [console_scripts]
2
+ sovereign = sovereign.server:main
3
+ sovereign-web = sovereign.server:web
4
+ sovereign-worker = sovereign.server:worker
5
+
6
+ [sovereign.cache.backends]
7
+ s3 = sovereign.cache.backends.s3:S3Backend
8
+
9
+ [sovereign.deserializers]
10
+ jinja = sovereign.dynamic_config.deser:JinjaDeserializer
11
+ jinja2 = sovereign.dynamic_config.deser:JinjaDeserializer
12
+ json = sovereign.dynamic_config.deser:JsonDeserializer
13
+ none = sovereign.dynamic_config.deser:PassthroughDeserializer
14
+ orjson = sovereign.dynamic_config.deser:OrjsonDeserializer
15
+ passthrough = sovereign.dynamic_config.deser:PassthroughDeserializer
16
+ raw = sovereign.dynamic_config.deser:PassthroughDeserializer
17
+ string = sovereign.dynamic_config.deser:StringDeserializer
18
+ ujson = sovereign.dynamic_config.deser:UjsonDeserializer
19
+ yaml = sovereign.dynamic_config.deser:YamlDeserializer
20
+
21
+ [sovereign.loaders]
22
+ env = sovereign.dynamic_config.loaders:EnvironmentVariable
23
+ example = sovereign.testing.loaders:Multiply
24
+ file = sovereign.dynamic_config.loaders:File
25
+ http = sovereign.dynamic_config.loaders:Web
26
+ https = sovereign.dynamic_config.loaders:Web
27
+ inline = sovereign.dynamic_config.loaders:Inline
28
+ module = sovereign.dynamic_config.loaders:PythonModule
29
+ pkgdata = sovereign.dynamic_config.loaders:PackageData
30
+ python = sovereign.dynamic_config.loaders:PythonInlineCode
31
+ s3 = sovereign.dynamic_config.loaders:S3Bucket
32
+
33
+ [sovereign.modifiers]
34
+ sovereign_3rd_party_test = sovereign.testing.modifiers:Test
35
+
36
+ [sovereign.sources]
37
+ file = sovereign.sources.file:File
38
+ inline = sovereign.sources.inline:Inline
File without changes
@@ -0,0 +1,51 @@
1
+ document.addEventListener('DOMContentLoaded', function() {
2
+ const darkmode = "theme-dark";
3
+ const lightmode = "theme-light";
4
+ const toggle = document.getElementById('dark-mode-toggle');
5
+ const htmlTag = document.documentElement;
6
+
7
+ function preferredTheme() {
8
+ const preference = localStorage.getItem("theme");
9
+ if (preference) {
10
+ return preference;
11
+ }
12
+ if (window.matchMedia("(prefers-color-scheme: dark)").matches) {
13
+ return "dark";
14
+ } else {
15
+ return "light";
16
+ };
17
+ }
18
+
19
+ function currentTheme() {
20
+ if (htmlTag.classList.contains(darkmode)) {
21
+ return "dark"
22
+ } else {
23
+ return "light"
24
+ }
25
+ }
26
+
27
+ function setTheme(theme) {
28
+ localStorage.setItem("theme", theme);
29
+ if (theme === "dark") {
30
+ htmlTag.classList.remove(lightmode);
31
+ htmlTag.classList.add(darkmode);
32
+ toggle.textContent = '🌘';
33
+ } else {
34
+ htmlTag.classList.remove(darkmode);
35
+ htmlTag.classList.add(lightmode);
36
+ toggle.textContent = '🌞';
37
+ }
38
+ }
39
+
40
+ setTheme(preferredTheme());
41
+
42
+ toggle.addEventListener("click", function() {
43
+ let current = currentTheme();
44
+ console.log("Current theme: " + current);
45
+ if (current === "dark") {
46
+ setTheme("light");
47
+ } else {
48
+ setTheme("dark");
49
+ }
50
+ });
51
+ });
@@ -0,0 +1,42 @@
1
+ const input = document.getElementById('filterInput');
2
+ const inputMessage = document.getElementById('filterMessage');
3
+ const form = document.getElementById('filterForm');
4
+
5
+ function validateInput(inputString) {
6
+ if (!inputString || inputString.trim() === '') {
7
+ return "empty";
8
+ }
9
+ const validationRegex = /^(?:(?:id|cluster|metadata\.[\w\.\=\-]+|locality\.?(?:zone|sub_zone|region))=[a-zA-Z0-9_-]+ ?)*$/;
10
+ return validationRegex.test(inputString);
11
+ }
12
+
13
+ window.addEventListener('DOMContentLoaded', () => {
14
+ const match = document.cookie.match(/(?:^|; )node_expression=([^;]*)/);
15
+ if (match) {
16
+ input.value = match[1];
17
+ }
18
+ });
19
+
20
+ input.addEventListener('input', (event) => {
21
+ const result = validateInput(event.target.value);
22
+ if (result === "empty") {
23
+ input.className = "input is-dark";
24
+ inputMessage.className = "help is-dark";
25
+ inputMessage.innerHTML = "";
26
+ } else if (result === true) {
27
+ input.className = "input is-success";
28
+ inputMessage.className = "help is-success";
29
+ inputMessage.innerHTML = "Press enter to apply filter expression";
30
+ } else {
31
+ input.className = "input is-danger";
32
+ inputMessage.className = "help is-danger";
33
+ inputMessage.innerHTML = "The node filter expression may have no effect, or be invalid";
34
+ }
35
+ });
36
+
37
+ form.addEventListener('submit', (event) => {
38
+ event.preventDefault();
39
+ const value = input.value.trim();
40
+ document.cookie = `node_expression=${value}; path=/ui/resources/; max-age=31536000`;
41
+ location.reload();
42
+ });
@@ -0,0 +1,76 @@
1
+ document.addEventListener('DOMContentLoaded', function() {
2
+ let currentTabFilter = 'all'; // Track the current tab filter
3
+
4
+ function clearSearch() {
5
+ const searchInput = document.getElementById('searchInput');
6
+ if (searchInput) {
7
+ searchInput.value = '';
8
+ }
9
+ }
10
+
11
+ // Function to apply both tab and search filters
12
+ function applyFilters() {
13
+ const searchInput = document.getElementById('searchInput');
14
+ const query = searchInput ? searchInput.value.toLowerCase() : '';
15
+ const virtualHosts = document.querySelectorAll('.virtualhost');
16
+
17
+ virtualHosts.forEach(vh => {
18
+ const text = vh.textContent.toLowerCase();
19
+ const category = vh.getAttribute("data-category");
20
+
21
+ // Check if it passes the tab filter
22
+ const passesTabFilter = (currentTabFilter === 'all') || (category === currentTabFilter);
23
+
24
+ // Check if it passes the search filter
25
+ const passesSearchFilter = query === '' || text.includes(query);
26
+
27
+ // Show only if it passes both filters
28
+ if (passesTabFilter && passesSearchFilter) {
29
+ vh.classList.remove('filtered');
30
+ } else {
31
+ vh.classList.add('filtered');
32
+ }
33
+ });
34
+ }
35
+
36
+ // Function to hide all panels except active
37
+ function updateVisibility() {
38
+ const panelBlocks = document.querySelectorAll('.virtualhost');
39
+ panelBlocks.forEach(block => {
40
+ if (!block.classList.contains('is-active')) {
41
+ block.classList.add('filtered');
42
+ } else {
43
+ block.classList.remove('filtered');
44
+ }
45
+ });
46
+ }
47
+ updateVisibility();
48
+
49
+ window.filterTabs = function(element, filter) {
50
+ const tabs = document.querySelectorAll('.panel-tabs a');
51
+ tabs.forEach(tab => tab.classList.remove('is-active'));
52
+ element.classList.add('is-active');
53
+
54
+ currentTabFilter = filter; // Update the current tab filter
55
+
56
+ // Clear virtual hosts search input when switching tabs
57
+ const searchInput = document.getElementById('searchInput');
58
+ if (searchInput) {
59
+ searchInput.value = null;
60
+ }
61
+
62
+ applyFilters();
63
+ };
64
+
65
+ const searchInput = document.getElementById('searchInput');
66
+ if (searchInput) {
67
+ searchInput.addEventListener('input', function() {
68
+ applyFilters(); // Apply both filters when searching
69
+ });
70
+ }
71
+
72
+ const allTab = document.querySelector('.panel-tabs a.is-active');
73
+ if (allTab) {
74
+ filterTabs(allTab, 'all');
75
+ }
76
+ });