sovereign 0.19.3__py3-none-any.whl → 1.0.0a4__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 (99) hide show
  1. sovereign/__init__.py +13 -81
  2. sovereign/app.py +62 -48
  3. sovereign/cache/__init__.py +245 -0
  4. sovereign/cache/backends/__init__.py +110 -0
  5. sovereign/cache/backends/s3.py +161 -0
  6. sovereign/cache/filesystem.py +74 -0
  7. sovereign/cache/types.py +17 -0
  8. sovereign/configuration.py +607 -0
  9. sovereign/constants.py +1 -0
  10. sovereign/context.py +270 -104
  11. sovereign/dynamic_config/__init__.py +112 -0
  12. sovereign/dynamic_config/deser.py +78 -0
  13. sovereign/dynamic_config/loaders.py +120 -0
  14. sovereign/error_info.py +2 -3
  15. sovereign/events.py +49 -0
  16. sovereign/logging/access_logger.py +85 -0
  17. sovereign/logging/application_logger.py +54 -0
  18. sovereign/logging/base_logger.py +41 -0
  19. sovereign/logging/bootstrapper.py +36 -0
  20. sovereign/logging/types.py +10 -0
  21. sovereign/middlewares.py +8 -7
  22. sovereign/modifiers/lib.py +2 -1
  23. sovereign/rendering.py +124 -0
  24. sovereign/rendering_common.py +91 -0
  25. sovereign/response_class.py +18 -0
  26. sovereign/server.py +112 -35
  27. sovereign/statistics.py +19 -21
  28. sovereign/templates/base.html +59 -46
  29. sovereign/templates/resources.html +203 -102
  30. sovereign/testing/loaders.py +9 -0
  31. sovereign/{modifiers/test.py → testing/modifiers.py} +0 -2
  32. sovereign/tracing.py +103 -0
  33. sovereign/types.py +304 -0
  34. sovereign/utils/auth.py +27 -13
  35. sovereign/utils/crypto/__init__.py +0 -0
  36. sovereign/utils/crypto/crypto.py +135 -0
  37. sovereign/utils/crypto/suites/__init__.py +21 -0
  38. sovereign/utils/crypto/suites/aes_gcm_cipher.py +42 -0
  39. sovereign/utils/crypto/suites/base_cipher.py +21 -0
  40. sovereign/utils/crypto/suites/disabled_cipher.py +25 -0
  41. sovereign/utils/crypto/suites/fernet_cipher.py +29 -0
  42. sovereign/utils/dictupdate.py +3 -2
  43. sovereign/utils/eds.py +40 -22
  44. sovereign/utils/entry_point_loader.py +2 -2
  45. sovereign/utils/mock.py +56 -17
  46. sovereign/utils/resources.py +17 -0
  47. sovereign/utils/templates.py +4 -2
  48. sovereign/utils/timer.py +5 -3
  49. sovereign/utils/version_info.py +8 -0
  50. sovereign/utils/weighted_clusters.py +2 -1
  51. sovereign/v2/__init__.py +0 -0
  52. sovereign/v2/data/data_store.py +621 -0
  53. sovereign/v2/data/render_discovery_response.py +24 -0
  54. sovereign/v2/data/repositories.py +90 -0
  55. sovereign/v2/data/utils.py +33 -0
  56. sovereign/v2/data/worker_queue.py +273 -0
  57. sovereign/v2/jobs/refresh_context.py +117 -0
  58. sovereign/v2/jobs/render_discovery_job.py +145 -0
  59. sovereign/v2/logging.py +81 -0
  60. sovereign/v2/types.py +41 -0
  61. sovereign/v2/web.py +101 -0
  62. sovereign/v2/worker.py +199 -0
  63. sovereign/views/__init__.py +7 -0
  64. sovereign/views/api.py +82 -0
  65. sovereign/views/crypto.py +46 -15
  66. sovereign/views/discovery.py +55 -119
  67. sovereign/views/healthchecks.py +107 -20
  68. sovereign/views/interface.py +171 -111
  69. sovereign/worker.py +193 -0
  70. {sovereign-0.19.3.dist-info → sovereign-1.0.0a4.dist-info}/METADATA +80 -76
  71. sovereign-1.0.0a4.dist-info/RECORD +85 -0
  72. {sovereign-0.19.3.dist-info → sovereign-1.0.0a4.dist-info}/WHEEL +1 -1
  73. sovereign-1.0.0a4.dist-info/entry_points.txt +46 -0
  74. sovereign_files/__init__.py +0 -0
  75. sovereign_files/static/darkmode.js +51 -0
  76. sovereign_files/static/node_expression.js +42 -0
  77. sovereign_files/static/panel.js +76 -0
  78. sovereign_files/static/resources.css +246 -0
  79. sovereign_files/static/resources.js +642 -0
  80. sovereign_files/static/sass/style.scss +33 -0
  81. sovereign_files/static/style.css +16143 -0
  82. sovereign_files/static/style.css.map +1 -0
  83. sovereign/config_loader.py +0 -225
  84. sovereign/discovery.py +0 -175
  85. sovereign/logs.py +0 -131
  86. sovereign/schemas.py +0 -780
  87. sovereign/sources/__init__.py +0 -3
  88. sovereign/sources/file.py +0 -21
  89. sovereign/sources/inline.py +0 -38
  90. sovereign/sources/lib.py +0 -40
  91. sovereign/sources/poller.py +0 -294
  92. sovereign/static/sass/style.scss +0 -27
  93. sovereign/static/style.css +0 -13553
  94. sovereign/templates/ul_filter.html +0 -22
  95. sovereign/utils/crypto.py +0 -103
  96. sovereign/views/admin.py +0 -120
  97. sovereign-0.19.3.dist-info/LICENSE.txt +0 -13
  98. sovereign-0.19.3.dist-info/RECORD +0 -47
  99. 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.0a4
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,103 @@ 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.129,>=0.128.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: rich>=14.2.0
40
+ Requires-Dist: starlette-context<0.4,>=0.3.6
41
+ Requires-Dist: starlette<0.50,>=0.49.1
42
+ Requires-Dist: structlog<24,>=23.1.0
43
+ Requires-Dist: supervisor<5,>=4.2.5
44
+ Requires-Dist: uvicorn<0.24,>=0.23.2
45
+ Requires-Dist: uvloop<1.0,>0.19.0
23
46
  Provides-Extra: boto
47
+ Requires-Dist: boto3<2,>=1.28.62; extra == 'boto'
24
48
  Provides-Extra: caching
25
49
  Provides-Extra: httptools
50
+ Requires-Dist: httptools<0.7,>=0.6.0; extra == 'httptools'
26
51
  Provides-Extra: orjson
52
+ Requires-Dist: orjson<4,>=3.9.15; extra == 'orjson'
27
53
  Provides-Extra: sentry
54
+ Requires-Dist: sentry-sdk<3,>=2.14.0; extra == 'sentry'
28
55
  Provides-Extra: statsd
56
+ Requires-Dist: datadog>=0.50.1; extra == 'statsd'
29
57
  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/
58
+ Requires-Dist: ujson<6,>=5.8.0; extra == 'ujson'
52
59
  Description-Content-Type: text/markdown
53
60
 
54
61
  sovereign
55
62
  =========
56
63
 
64
+
57
65
  Mission statement
58
66
  -----------------
59
67
  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
68
 
61
- The purpose of `sovereign` is to supply downstream envoy proxies with
62
- configuration in near-realtime by responding to discovery requests.
69
+ The purpose of `sovereign` is to supply downstream envoy proxies with dynamic configuration.
70
+
63
71
 
64
72
  Mechanism of Operation
65
73
  ----------------------
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
- ```
74
+ Sovereign allows you to define templates that represent each resource type
75
+ provided by Envoy. For example, clusters, routes, listeners, secrets,
76
+ extension_configs, etc.
77
+
78
+ In order to enrich the templates with data, Sovereign has ways of polling data
79
+ out-of-band which it then includes as variables that can be accessed within the
80
+ templates.
72
81
 
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.
82
+ This allows Sovereign to provide configuration to Envoy that changes over time
83
+ depending on the data sources, without needing to redeploy the control-plane.
77
84
 
78
- This is performed in a semi-stateless way, where the only state is data cached in memory.
85
+ Sovereign provides some built-in ways of polling data (such as over HTTP, or
86
+ on-disk) but also exposes extension points, allowing you to write your own
87
+ plugins in Python.
79
88
 
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
89
 
84
- *Modifiers* can mutate the data retrieved from sources, just in case the data
85
- is in a less than favorable structure.
90
+ Support
91
+ ------------
92
+ [Submit new issues here](https://bitbucket.org/atlassian/sovereign/issues/new)
93
+
94
+ If you're unable to submit an issue on Bitbucket, send an email to [vsyrakis@atlassian.com](mailto:vsyrakis@atlassian.com)
95
+
96
+
97
+ Release
98
+ ------------
99
+ See [RELEASE.md]
86
100
 
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
101
 
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!
102
+ Roadmap
103
+ ------------
104
+ * Performance improvements
105
+ * Data persistence
106
+ * Push API (versus polling)
107
+ * Client for Sovereign
108
+ * gRPC
93
109
 
94
- The JSON configuration can be viewed in real-time with Sovereign's read-only web interface.
95
110
 
96
111
  Requirements
97
112
  ------------
98
113
  * Python 3.8+
99
114
 
115
+
100
116
  Installation
101
117
  ------------
102
118
  ```
@@ -105,62 +121,53 @@ pip install sovereign
105
121
 
106
122
  Documentation
107
123
  -------------
108
- [Read the docs here!](https://vsyrakis.bitbucket.io/sovereign/docs/)
124
+ [Read the docs here!](https://developer.atlassian.com/platform/sovereign/)
109
125
 
110
- :new: Read-only user interface
111
- ------------------------
112
- Added in `v0.5.3`!
113
126
 
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
127
 
118
128
  Local development
119
129
  =================
120
130
 
131
+
121
132
  Requirements
122
133
  ------------
134
+ * uv
123
135
  * Docker
124
136
  * Docker-compose
125
137
 
138
+
126
139
  Installing dependencies for dev
127
140
  -------------------------------
128
- I recommend creating a virtualenv before doing any dev work
129
-
141
+ Dependencies and creation of virtualenv is handled by uv
130
142
  ```
131
- python3 -m venv venv
132
- source venv/bin/activate
133
- pip install -r requirements-dev.txt
143
+ uv sync
144
+ uv venv activate
145
+ uv run <command>
134
146
  ```
135
147
 
136
148
  Running locally
137
149
  ---------------
138
150
  Running the test env
139
-
140
151
  ```
141
152
  make run
142
153
  ```
143
154
 
144
155
  Running the test env daemonized
145
-
146
156
  ```
147
157
  make run-daemon
148
158
  ```
149
159
 
150
160
  Pylint
151
-
152
161
  ```
153
162
  make lint
154
163
  ```
155
164
 
156
165
  Unit tests
157
-
158
166
  ```
159
167
  make unit
160
168
  ```
161
169
 
162
170
  Acceptance tests
163
-
164
171
  ```
165
172
  make run-daemon acceptance
166
173
  ```
@@ -168,7 +175,6 @@ make run-daemon acceptance
168
175
 
169
176
  Contributors
170
177
  ============
171
-
172
178
  Pull requests, issues and comments welcome. For pull requests:
173
179
 
174
180
  * Add tests for new features and bug fixes
@@ -197,9 +203,7 @@ those contributing as an individual.
197
203
 
198
204
  License
199
205
  ========
200
-
201
206
  Copyright (c) 2018 Atlassian and others.
202
207
  Apache 2.0 licensed, see [LICENSE.txt](LICENSE.txt) file.
203
208
 
204
209
 
205
-
@@ -0,0 +1,85 @@
1
+ sovereign/__init__.py,sha256=D6-BdAO7EyeQ7KU3sl9oiBYsGXDBkc5UM7I1kkas1Eg,1069
2
+ sovereign/app.py,sha256=l7AO8PtHsiVIN6ybWKj0qgzPJ-cNX8q9_syLfIG9XHY,5117
3
+ sovereign/configuration.py,sha256=AqDOVc7eOgEsP8BOvW5UsMhbC2j2FR72Uios76gK6Ao,21177
4
+ sovereign/constants.py,sha256=qdWD1lTvkaW5JGF7TmZhfksQHlRAJFVqbG7v6JQA9k8,46
5
+ sovereign/context.py,sha256=nwLJ_gvXFoKZJMCt4NX3KRkM381XMq_DJfTedceToJQ,9076
6
+ sovereign/error_info.py,sha256=_xfwYCV10zpAa0XP_zz0FoGtjj-1S_f4IgOf78-6wcw,1487
7
+ sovereign/events.py,sha256=gSWxaEqRdYfA_y7iFEzQPPrg3N5jy9svpfHzn6kBdRk,1203
8
+ sovereign/middlewares.py,sha256=6w4JpvtNGvQA4rocQsYQjuu-ckhpKT6gKYA16T-kiqA,3082
9
+ sovereign/rendering.py,sha256=qKtO0BUoqRs_FqDGsw2o0_756Uj59aBhfeKRpNjFlQM,4103
10
+ sovereign/rendering_common.py,sha256=WvZ_vCHD3ODiAX3Hw6Q6GwTklH4a2BFY3-zwqDNnmjg,3395
11
+ sovereign/response_class.py,sha256=S-8xziWdWVk8jbde_2OdxV1XWdrw6EwInLLhFmaYgkA,427
12
+ sovereign/server.py,sha256=5JQJ72yyOA4rjVs4rFznwYvh7zFEsg48cTDBqCvmsQo,3650
13
+ sovereign/statistics.py,sha256=0bbL7eLGOC-_hOY_ilx2uV_VpSJTIYjBGvEztDlgQDs,2045
14
+ sovereign/tracing.py,sha256=xL1blm4u2gmahpkFKhwY-pA-hE976rDXi9QxaOdRnoI,2686
15
+ sovereign/types.py,sha256=j8w3tXfkm0FHcMP8WXcXd99D1YhJ-cIuc-oVV0LuBSc,10245
16
+ sovereign/worker.py,sha256=ecLm_LDnbJPVzQPLmBhF3J-cWpzPKo6H2HAncDNbneE,5615
17
+ sovereign/cache/__init__.py,sha256=bq5BPiO-oCpSmiQ7GoXDk3PckVqYNS2NADguWBcRzeQ,9536
18
+ sovereign/cache/filesystem.py,sha256=GQP34jhJP2JsaEQgnI4O80EuN6sdK7lnKbP37jrI4d8,2416
19
+ sovereign/cache/types.py,sha256=JOLrPI8X209Fndt5xtLtEWMB6Fh7cvnzwsEBAoBV06c,243
20
+ sovereign/cache/backends/__init__.py,sha256=3oKlNWuHd5KyETor1napzq6nIJv0KGbOEPUrIZf35So,3160
21
+ sovereign/cache/backends/s3.py,sha256=92YPCBW9t4wLNQuCiES29GJ36lUP1IWIJDMHWFGNJDA,5865
22
+ sovereign/dynamic_config/__init__.py,sha256=VU71zUxc6zwioX3zm9VTzj_XQl8ye6FJGPuna3BaieY,3546
23
+ sovereign/dynamic_config/deser.py,sha256=uJsv6vWEPb-dJ9PIDZ51J-KC8J-IikbTvUM8hmvKAyY,1834
24
+ sovereign/dynamic_config/loaders.py,sha256=hp8drF4jXaotO-7CGudgs_enkg63vrXW34nTzP4MHlY,2915
25
+ sovereign/logging/access_logger.py,sha256=W5GE0fOjkYTwdA8KVsbPzof_FcPfJ8kCOpnL_tEi9gw,2989
26
+ sovereign/logging/application_logger.py,sha256=DKrLVX8sl7ckGYCUlSJLwJ9K9nomNoLBitzhEj2s_K8,1806
27
+ sovereign/logging/base_logger.py,sha256=ScOzHs8Rt1RZaUZGvaJSAlDEjD0BxkD5sLKSm2GgM0I,1243
28
+ sovereign/logging/bootstrapper.py,sha256=9a13x8gDEH0fiDkpEkwxmQYzWmb8jqPJKx4QCgdT7II,1302
29
+ sovereign/logging/types.py,sha256=rGqJAEVvgvzHy4aPfvEH6yQ-yblXNkEcWG7G8l9ALEA,282
30
+ sovereign/modifiers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
31
+ sovereign/modifiers/lib.py,sha256=tck5rw6PNqLofBtm3GTRMmrfrV9eSj_Rwhn5tM3Q2UA,2885
32
+ sovereign/templates/base.html,sha256=MMhhvvClTixKibYfhXm8Ezx6ttu6Sqki44niciCPMO4,2990
33
+ sovereign/templates/err.html,sha256=a3cEzOqyqWOIe3YxfTEjkxbTfxBxq1knD6GwzEFljfs,603
34
+ sovereign/templates/resources.html,sha256=5MfXHW8s3tAWda66Q48zVgDhZNLwHGsdCKkKHLZohIs,10420
35
+ sovereign/testing/loaders.py,sha256=JEjoxPSy0O-SUowW1U7P_BX6ABuqrmUrCuAxsUZaMos,200
36
+ sovereign/testing/modifiers.py,sha256=YI0aJOEbb1C_1T5VDrZKyLopk8JiIlKtUtxXMFfsCtk,290
37
+ sovereign/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
38
+ sovereign/utils/auth.py,sha256=e9lMNo8KqScTBITz4upQ0qL8A-4DTl-ybCy9DPwpfoM,2307
39
+ sovereign/utils/dictupdate.py,sha256=R60mHb3qf4r-KT-SyxQJv7KQktmtzp-bRtVOjebo0To,2558
40
+ sovereign/utils/eds.py,sha256=eykFVKaLXoMeieJ2TnArx3q5KIJeQYiB-OYQrTWtslw,4391
41
+ sovereign/utils/entry_point_loader.py,sha256=OPvaLfwUH0XGYw9WM3hdi_-uBAwmibBoq2NEjLFtnKs,526
42
+ sovereign/utils/mock.py,sha256=Oc5p8conSku2t6b75m7nMHsESepLmnv_itHcAE8cIXw,2396
43
+ sovereign/utils/resources.py,sha256=otKaJZIDQa4So_cKkFN9gBsLZaG6rH0hg9hjELn1Qic,472
44
+ sovereign/utils/templates.py,sha256=yML5rU-BUY-2oQx6gOK7fOkLjtD5VSmaH8vzPKnetSc,1059
45
+ sovereign/utils/timer.py,sha256=DvbjDOSXZsGXigWpuRxE1NyVrpq4qktIRQhJIOt2Dcs,919
46
+ sovereign/utils/version_info.py,sha256=adBfu0z6jsg8E5-BIUjZyBwZvfLASj7fpCpYeIvBeMY,576
47
+ sovereign/utils/weighted_clusters.py,sha256=RTRLX5TFvL426_B-M8XhC7FeGelHzpgGpHwQaVFEHRQ,1167
48
+ sovereign/utils/crypto/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
49
+ sovereign/utils/crypto/crypto.py,sha256=FMo4TikqWcPJ5fyc6j2WEHkkwZU3WY3qJKr7VLfckv0,4532
50
+ sovereign/utils/crypto/suites/__init__.py,sha256=smMvNa1VsQ0PvsNj6lnRNh4ktB7dMnas1CqeTOFqgGA,526
51
+ sovereign/utils/crypto/suites/aes_gcm_cipher.py,sha256=Yjfj1LCQDGTzHBjrZR3-koh29L_N34v65kPoIfta0aw,1239
52
+ sovereign/utils/crypto/suites/base_cipher.py,sha256=kUOZh_ZIILyo5zv99-qzbJZDpeMmt76vhkBDEPvAt4A,454
53
+ sovereign/utils/crypto/suites/disabled_cipher.py,sha256=3uagd2IkE-IHLkfOgX1rofatHIBVLryV_hGvdJPmuTM,579
54
+ sovereign/utils/crypto/suites/fernet_cipher.py,sha256=rP6M5ys1vctyadOxDGNFoyerWPUOunLQdZ2jjS1pxzc,701
55
+ sovereign/v2/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
56
+ sovereign/v2/logging.py,sha256=ia8ntWngTKXlMzFhkVNScIDaFTrL0HkIkUT-afQGEJE,2639
57
+ sovereign/v2/types.py,sha256=0qclM0aylR1-FjCVCzlYlZShNICWt6wI-52B3SkSC1w,800
58
+ sovereign/v2/web.py,sha256=dzjLJ0lXdGZqkGc237QHVe930Hmls9m_e-clas9mOps,3443
59
+ sovereign/v2/worker.py,sha256=rGqDsinDCtGNbCmBDF1mHIik4KJH0rKpH4WLzL-VDAo,7467
60
+ sovereign/v2/data/data_store.py,sha256=IDjV3ouYjVxWdcvcAUIPrfnXVwAbbyMmkbXjdfKfnw8,20310
61
+ sovereign/v2/data/render_discovery_response.py,sha256=3AFMXBu1aBRaSLjUTxVUI9Lt-to0B5eXY5m1SMO7dB8,949
62
+ sovereign/v2/data/repositories.py,sha256=KsdFvOIDZmkZDe-SmatX4GialhRk4LWD_2pOBeOTAQs,3292
63
+ sovereign/v2/data/utils.py,sha256=cJ93ioHXPHquMhqvYY4SulbWVgTPxY6t_gvYhOt6T1s,1075
64
+ sovereign/v2/data/worker_queue.py,sha256=aDTLqeXM-qx-CJ0VpOaNVKkGmlEllVQxERXIaS0Kv9w,10407
65
+ sovereign/v2/jobs/refresh_context.py,sha256=lhzP9zl8U4fA0ND-SFJs4HefnEAtv8d7no4u5cFI-L4,4277
66
+ sovereign/v2/jobs/render_discovery_job.py,sha256=Z5L4Qj54tg8FVlaMaBBCZiJgAqJIS-Rl28ekxoJ1o58,5451
67
+ sovereign/views/__init__.py,sha256=0niB6LnhAZQzI4nk_xXsWk95Idm0YFINLoL8WhNdA70,183
68
+ sovereign/views/api.py,sha256=dcNy9HKEB9n6DAQI_gP5cyVLn_4YFOODMx1zIu2-J6Y,2954
69
+ sovereign/views/crypto.py,sha256=0UX0mEGQmiwRcR8gMeIkNYY2ykEGpPC09xmfFRsh-bY,3366
70
+ sovereign/views/discovery.py,sha256=1yIKSIuVnPT7wtPd0fJ7KdEp5ZZf8PdWP67XoI_4R6s,3111
71
+ sovereign/views/healthchecks.py,sha256=56exKqRz4Qdz3KJlbwHWZNIQ-yJUOgpDnzROrzQn3rg,4108
72
+ sovereign/views/interface.py,sha256=vHTdboqhBMGyX4COnExKbal51hOXFX4txaK0nmz8bs8,9294
73
+ sovereign_files/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
74
+ sovereign_files/static/darkmode.js,sha256=3ip-eKGctDvNhN7UgmaHhzls7r5qIY-Jvh2EpefHbQ0,1449
75
+ sovereign_files/static/node_expression.js,sha256=GKxKTSRc_96IbL3H4L_31ueJFXq4N7scm5R1RNqxP24,1489
76
+ sovereign_files/static/panel.js,sha256=i5mGExjv-I4Gtt9dQiTyFwPZa8pg5rXeuTeidXNUiTE,2695
77
+ sovereign_files/static/resources.css,sha256=Rt_ir_FkoI-VIAOqPhk0vILy8kB2egAYbQU26SOs1io,4500
78
+ sovereign_files/static/resources.js,sha256=-TaXZ6tohyKA1SkX5YwrTcV5M8mOZ68cvEXpvZWznTo,24506
79
+ sovereign_files/static/style.css,sha256=kmvkJ2820RKehWxhddkucbgFkvnpUgBMteOtpEuXjvQ,601347
80
+ sovereign_files/static/style.css.map,sha256=h1ufjfDVX-8z-FuJqFG2-U9AVdi66U-e8uyiGdUZjDw,66576
81
+ sovereign_files/static/sass/style.scss,sha256=LdGXXuHi_tyMc7XhijIOrlIxyfLt827AAs2Z7DYpFpg,990
82
+ sovereign-1.0.0a4.dist-info/METADATA,sha256=i7YfqN62JPqLC2-55IdBfaXkhZaajFwufE6XG6glcG0,5943
83
+ sovereign-1.0.0a4.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
84
+ sovereign-1.0.0a4.dist-info/entry_points.txt,sha256=Mj1IvDg3Y61lasbqkGtEWpPn_xgYWCyeuMnOl8hTLVQ,1787
85
+ sovereign-1.0.0a4.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,46 @@
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.data_stores]
10
+ memory = sovereign.v2.data.data_store:InMemoryDataStore
11
+ sqlite = sovereign.v2.data.data_store:SqliteDataStore
12
+
13
+ [sovereign.deserializers]
14
+ jinja = sovereign.dynamic_config.deser:JinjaDeserializer
15
+ jinja2 = sovereign.dynamic_config.deser:JinjaDeserializer
16
+ json = sovereign.dynamic_config.deser:JsonDeserializer
17
+ none = sovereign.dynamic_config.deser:PassthroughDeserializer
18
+ orjson = sovereign.dynamic_config.deser:OrjsonDeserializer
19
+ passthrough = sovereign.dynamic_config.deser:PassthroughDeserializer
20
+ raw = sovereign.dynamic_config.deser:PassthroughDeserializer
21
+ string = sovereign.dynamic_config.deser:StringDeserializer
22
+ ujson = sovereign.dynamic_config.deser:UjsonDeserializer
23
+ yaml = sovereign.dynamic_config.deser:YamlDeserializer
24
+
25
+ [sovereign.loaders]
26
+ env = sovereign.dynamic_config.loaders:EnvironmentVariable
27
+ example = sovereign.testing.loaders:Multiply
28
+ file = sovereign.dynamic_config.loaders:File
29
+ http = sovereign.dynamic_config.loaders:Web
30
+ https = sovereign.dynamic_config.loaders:Web
31
+ inline = sovereign.dynamic_config.loaders:Inline
32
+ module = sovereign.dynamic_config.loaders:PythonModule
33
+ pkgdata = sovereign.dynamic_config.loaders:PackageData
34
+ python = sovereign.dynamic_config.loaders:PythonInlineCode
35
+ s3 = sovereign.dynamic_config.loaders:S3Bucket
36
+
37
+ [sovereign.modifiers]
38
+ sovereign_3rd_party_test = sovereign.testing.modifiers:Test
39
+
40
+ [sovereign.queues]
41
+ memory = sovereign.v2.data.worker_queue:InMemoryQueue
42
+ sqlite = sovereign.v2.data.worker_queue:SqliteQueue
43
+
44
+ [sovereign.sources]
45
+ file = sovereign.sources.file:File
46
+ 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
+ });