sovereign 0.32.0__tar.gz → 1.0.0a3__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.
Files changed (109) hide show
  1. {sovereign-0.32.0 → sovereign-1.0.0a3}/PKG-INFO +43 -45
  2. {sovereign-0.32.0 → sovereign-1.0.0a3}/README.md +5 -4
  3. sovereign-1.0.0a3/pyproject.toml +161 -0
  4. sovereign-1.0.0a3/src/sovereign/__init__.py +32 -0
  5. {sovereign-0.32.0 → sovereign-1.0.0a3}/src/sovereign/app.py +53 -42
  6. sovereign-1.0.0a3/src/sovereign/cache/__init__.py +245 -0
  7. sovereign-1.0.0a3/src/sovereign/cache/backends/__init__.py +110 -0
  8. sovereign-1.0.0a3/src/sovereign/cache/backends/s3.py +161 -0
  9. sovereign-1.0.0a3/src/sovereign/cache/filesystem.py +74 -0
  10. sovereign-1.0.0a3/src/sovereign/cache/types.py +17 -0
  11. sovereign-1.0.0a3/src/sovereign/configuration.py +607 -0
  12. sovereign-1.0.0a3/src/sovereign/context.py +285 -0
  13. sovereign-1.0.0a3/src/sovereign/dynamic_config/__init__.py +112 -0
  14. {sovereign-0.32.0 → sovereign-1.0.0a3}/src/sovereign/error_info.py +2 -3
  15. sovereign-1.0.0a3/src/sovereign/events.py +49 -0
  16. {sovereign-0.32.0 → sovereign-1.0.0a3}/src/sovereign/logging/access_logger.py +1 -1
  17. {sovereign-0.32.0 → sovereign-1.0.0a3}/src/sovereign/logging/application_logger.py +1 -1
  18. {sovereign-0.32.0 → sovereign-1.0.0a3}/src/sovereign/logging/bootstrapper.py +3 -1
  19. {sovereign-0.32.0 → sovereign-1.0.0a3}/src/sovereign/middlewares.py +1 -1
  20. {sovereign-0.32.0 → sovereign-1.0.0a3}/src/sovereign/modifiers/lib.py +1 -1
  21. sovereign-1.0.0a3/src/sovereign/rendering.py +124 -0
  22. sovereign-1.0.0a3/src/sovereign/rendering_common.py +91 -0
  23. sovereign-1.0.0a3/src/sovereign/server.py +127 -0
  24. {sovereign-0.32.0 → sovereign-1.0.0a3}/src/sovereign/statistics.py +19 -21
  25. sovereign-1.0.0a3/src/sovereign/templates/base.html +77 -0
  26. sovereign-1.0.0a3/src/sovereign/templates/resources.html +260 -0
  27. {sovereign-0.32.0 → sovereign-1.0.0a3}/src/sovereign/testing/loaders.py +1 -0
  28. {sovereign-0.32.0 → sovereign-1.0.0a3}/src/sovereign/testing/modifiers.py +0 -2
  29. sovereign-1.0.0a3/src/sovereign/tracing.py +103 -0
  30. sovereign-1.0.0a3/src/sovereign/types.py +304 -0
  31. {sovereign-0.32.0 → sovereign-1.0.0a3}/src/sovereign/utils/auth.py +21 -6
  32. {sovereign-0.32.0 → sovereign-1.0.0a3}/src/sovereign/utils/crypto/crypto.py +1 -1
  33. {sovereign-0.32.0 → sovereign-1.0.0a3}/src/sovereign/utils/crypto/suites/disabled_cipher.py +2 -2
  34. {sovereign-0.32.0 → sovereign-1.0.0a3}/src/sovereign/utils/eds.py +5 -3
  35. {sovereign-0.32.0 → sovereign-1.0.0a3}/src/sovereign/utils/entry_point_loader.py +2 -2
  36. sovereign-1.0.0a3/src/sovereign/utils/mock.py +75 -0
  37. {sovereign-0.32.0 → sovereign-1.0.0a3}/src/sovereign/utils/templates.py +4 -2
  38. {sovereign-0.32.0 → sovereign-1.0.0a3}/src/sovereign/utils/timer.py +5 -3
  39. {sovereign-0.32.0 → sovereign-1.0.0a3}/src/sovereign/utils/version_info.py +8 -0
  40. {sovereign-0.32.0 → sovereign-1.0.0a3}/src/sovereign/utils/weighted_clusters.py +2 -1
  41. sovereign-1.0.0a3/src/sovereign/v2/data/data_store.py +621 -0
  42. sovereign-1.0.0a3/src/sovereign/v2/data/render_discovery_response.py +24 -0
  43. sovereign-1.0.0a3/src/sovereign/v2/data/repositories.py +90 -0
  44. sovereign-1.0.0a3/src/sovereign/v2/data/utils.py +33 -0
  45. sovereign-1.0.0a3/src/sovereign/v2/data/worker_queue.py +273 -0
  46. sovereign-1.0.0a3/src/sovereign/v2/jobs/refresh_context.py +117 -0
  47. sovereign-1.0.0a3/src/sovereign/v2/jobs/render_discovery_job.py +145 -0
  48. sovereign-1.0.0a3/src/sovereign/v2/logging.py +81 -0
  49. sovereign-1.0.0a3/src/sovereign/v2/types.py +41 -0
  50. sovereign-1.0.0a3/src/sovereign/v2/web.py +101 -0
  51. sovereign-1.0.0a3/src/sovereign/v2/worker.py +199 -0
  52. sovereign-1.0.0a3/src/sovereign/views/__init__.py +7 -0
  53. sovereign-1.0.0a3/src/sovereign/views/api.py +82 -0
  54. {sovereign-0.32.0 → sovereign-1.0.0a3}/src/sovereign/views/crypto.py +1 -1
  55. sovereign-1.0.0a3/src/sovereign/views/discovery.py +92 -0
  56. sovereign-1.0.0a3/src/sovereign/views/healthchecks.py +127 -0
  57. sovereign-1.0.0a3/src/sovereign/views/interface.py +261 -0
  58. sovereign-1.0.0a3/src/sovereign/worker.py +193 -0
  59. sovereign-1.0.0a3/src/sovereign_files/__init__.py +0 -0
  60. sovereign-1.0.0a3/src/sovereign_files/static/darkmode.js +51 -0
  61. sovereign-1.0.0a3/src/sovereign_files/static/node_expression.js +42 -0
  62. sovereign-1.0.0a3/src/sovereign_files/static/panel.js +76 -0
  63. sovereign-1.0.0a3/src/sovereign_files/static/resources.css +246 -0
  64. sovereign-1.0.0a3/src/sovereign_files/static/resources.js +642 -0
  65. sovereign-1.0.0a3/src/sovereign_files/static/sass/style.scss +33 -0
  66. sovereign-1.0.0a3/src/sovereign_files/static/style.css +16143 -0
  67. sovereign-1.0.0a3/src/sovereign_files/static/style.css.map +1 -0
  68. sovereign-0.32.0/LICENSE.txt +0 -13
  69. sovereign-0.32.0/pyproject.toml +0 -138
  70. sovereign-0.32.0/src/sovereign/__init__.py +0 -93
  71. sovereign-0.32.0/src/sovereign/context.py +0 -194
  72. sovereign-0.32.0/src/sovereign/discovery.py +0 -193
  73. sovereign-0.32.0/src/sovereign/dynamic_config/__init__.py +0 -88
  74. sovereign-0.32.0/src/sovereign/schemas.py +0 -918
  75. sovereign-0.32.0/src/sovereign/server.py +0 -50
  76. sovereign-0.32.0/src/sovereign/sources/__init__.py +0 -3
  77. sovereign-0.32.0/src/sovereign/sources/file.py +0 -21
  78. sovereign-0.32.0/src/sovereign/sources/inline.py +0 -39
  79. sovereign-0.32.0/src/sovereign/sources/lib.py +0 -41
  80. sovereign-0.32.0/src/sovereign/sources/poller.py +0 -296
  81. sovereign-0.32.0/src/sovereign/static/panel.js +0 -56
  82. sovereign-0.32.0/src/sovereign/static/sass/style.scss +0 -27
  83. sovereign-0.32.0/src/sovereign/static/search_filter.js +0 -20
  84. sovereign-0.32.0/src/sovereign/static/style.css +0 -13553
  85. sovereign-0.32.0/src/sovereign/templates/base.html +0 -64
  86. sovereign-0.32.0/src/sovereign/templates/resources.html +0 -200
  87. sovereign-0.32.0/src/sovereign/tracing.py +0 -85
  88. sovereign-0.32.0/src/sovereign/utils/mock.py +0 -34
  89. sovereign-0.32.0/src/sovereign/views/admin.py +0 -138
  90. sovereign-0.32.0/src/sovereign/views/discovery.py +0 -165
  91. sovereign-0.32.0/src/sovereign/views/healthchecks.py +0 -41
  92. sovereign-0.32.0/src/sovereign/views/interface.py +0 -223
  93. {sovereign-0.32.0 → sovereign-1.0.0a3}/src/sovereign/constants.py +0 -0
  94. {sovereign-0.32.0 → sovereign-1.0.0a3}/src/sovereign/dynamic_config/deser.py +1 -1
  95. {sovereign-0.32.0 → sovereign-1.0.0a3}/src/sovereign/dynamic_config/loaders.py +3 -3
  96. {sovereign-0.32.0 → sovereign-1.0.0a3}/src/sovereign/logging/base_logger.py +0 -0
  97. {sovereign-0.32.0 → sovereign-1.0.0a3}/src/sovereign/logging/types.py +0 -0
  98. {sovereign-0.32.0 → sovereign-1.0.0a3}/src/sovereign/modifiers/__init__.py +0 -0
  99. {sovereign-0.32.0 → sovereign-1.0.0a3}/src/sovereign/response_class.py +2 -2
  100. {sovereign-0.32.0 → sovereign-1.0.0a3}/src/sovereign/templates/err.html +0 -0
  101. {sovereign-0.32.0 → sovereign-1.0.0a3}/src/sovereign/utils/__init__.py +0 -0
  102. {sovereign-0.32.0 → sovereign-1.0.0a3}/src/sovereign/utils/crypto/__init__.py +0 -0
  103. {sovereign-0.32.0 → sovereign-1.0.0a3}/src/sovereign/utils/crypto/suites/__init__.py +0 -0
  104. {sovereign-0.32.0 → sovereign-1.0.0a3}/src/sovereign/utils/crypto/suites/aes_gcm_cipher.py +0 -0
  105. {sovereign-0.32.0 → sovereign-1.0.0a3}/src/sovereign/utils/crypto/suites/base_cipher.py +0 -0
  106. {sovereign-0.32.0 → sovereign-1.0.0a3}/src/sovereign/utils/crypto/suites/fernet_cipher.py +0 -0
  107. {sovereign-0.32.0 → sovereign-1.0.0a3}/src/sovereign/utils/dictupdate.py +1 -1
  108. {sovereign-0.32.0 → sovereign-1.0.0a3}/src/sovereign/utils/resources.py +1 -1
  109. {sovereign-0.32.0/src/sovereign/views → sovereign-1.0.0a3/src/sovereign/v2}/__init__.py +0 -0
@@ -1,13 +1,13 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: sovereign
3
- Version: 0.32.0
3
+ Version: 1.0.0a3
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,48 +16,46 @@ 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
- Classifier: Programming Language :: Python :: 3.12
22
- Classifier: Programming Language :: Python :: 3.13
23
- Classifier: Programming Language :: Python :: 3.10
24
19
  Classifier: Programming Language :: Python :: 3.8
25
20
  Classifier: Programming Language :: Python :: 3.9
21
+ Classifier: Programming Language :: Python :: 3.10
22
+ Classifier: Programming Language :: Python :: 3.11
26
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
27
46
  Provides-Extra: boto
47
+ Requires-Dist: boto3<2,>=1.28.62; extra == 'boto'
28
48
  Provides-Extra: caching
29
49
  Provides-Extra: httptools
50
+ Requires-Dist: httptools<0.7,>=0.6.0; extra == 'httptools'
30
51
  Provides-Extra: orjson
52
+ Requires-Dist: orjson<4,>=3.9.15; extra == 'orjson'
31
53
  Provides-Extra: sentry
54
+ Requires-Dist: sentry-sdk<3,>=2.14.0; extra == 'sentry'
32
55
  Provides-Extra: statsd
56
+ Requires-Dist: datadog>=0.50.1; extra == 'statsd'
33
57
  Provides-Extra: ujson
34
- Requires-Dist: Jinja2 (>=3.1.2,<4.0.0)
35
- Requires-Dist: PyYAML (>=6.0.1,<7.0.0)
36
- Requires-Dist: aiofiles (>=23.2.1,<24.0.0)
37
- Requires-Dist: boto3 (>=1.28.62,<2.0.0) ; extra == "boto"
38
- Requires-Dist: cachelib (>=0.10.2,<0.11.0)
39
- Requires-Dist: cachetools (>=5.3.2,<6.0.0)
40
- Requires-Dist: cashews[redis] (>=6.3.0,<7.0.0) ; extra == "caching"
41
- Requires-Dist: croniter (>=1.4.1,<2.0.0)
42
- Requires-Dist: cryptography (>=42.0.0,<43.0.0)
43
- Requires-Dist: datadog (>=0.47.0,<0.48.0) ; extra == "statsd"
44
- Requires-Dist: fastapi (>=0.115.2,<0.116.0)
45
- Requires-Dist: glom (>=23.3.0,<24.0.0)
46
- Requires-Dist: gunicorn (>=23.0.0,<24.0.0)
47
- Requires-Dist: httptools (>=0.6.0,<0.7.0) ; extra == "httptools"
48
- Requires-Dist: orjson (>=3.9.15,<4.0.0) ; extra == "orjson"
49
- Requires-Dist: pydantic (>=2.7.2,<3.0.0)
50
- Requires-Dist: pydantic-settings (<2.6.0)
51
- Requires-Dist: redis (<=5.0.0)
52
- Requires-Dist: requests (>=2.31.0,<3.0.0)
53
- Requires-Dist: sentry-sdk (>=2.14.0,<3.0.0) ; extra == "sentry"
54
- Requires-Dist: starlette-context (>=0.3.6,<0.4.0)
55
- Requires-Dist: structlog (>=23.1.0,<24.0.0)
56
- Requires-Dist: ujson (>=5.8.0,<6.0.0) ; extra == "ujson"
57
- Requires-Dist: uvicorn (>=0.23.2,<0.24.0)
58
- Requires-Dist: uvloop (>=0.19.0,<0.20.0)
59
- Project-URL: Documentation, https://developer.atlassian.com/platform/sovereign/
60
- Project-URL: Repository, https://bitbucket.org/atlassian/sovereign/src/master/
58
+ Requires-Dist: ujson<6,>=5.8.0; extra == 'ujson'
61
59
  Description-Content-Type: text/markdown
62
60
 
63
61
  sovereign
@@ -133,17 +131,18 @@ Local development
133
131
 
134
132
  Requirements
135
133
  ------------
136
- * Poetry
134
+ * uv
137
135
  * Docker
138
136
  * Docker-compose
139
137
 
140
138
 
141
139
  Installing dependencies for dev
142
140
  -------------------------------
143
- Dependencies and creation of virtualenv is handled by poetry
141
+ Dependencies and creation of virtualenv is handled by uv
144
142
  ```
145
- poetry install
146
- poetry shell
143
+ uv sync
144
+ uv venv activate
145
+ uv run <command>
147
146
  ```
148
147
 
149
148
  Running locally
@@ -208,4 +207,3 @@ Copyright (c) 2018 Atlassian and others.
208
207
  Apache 2.0 licensed, see [LICENSE.txt](LICENSE.txt) file.
209
208
 
210
209
 
211
-
@@ -71,17 +71,18 @@ Local development
71
71
 
72
72
  Requirements
73
73
  ------------
74
- * Poetry
74
+ * uv
75
75
  * Docker
76
76
  * Docker-compose
77
77
 
78
78
 
79
79
  Installing dependencies for dev
80
80
  -------------------------------
81
- Dependencies and creation of virtualenv is handled by poetry
81
+ Dependencies and creation of virtualenv is handled by uv
82
82
  ```
83
- poetry install
84
- poetry shell
83
+ uv sync
84
+ uv venv activate
85
+ uv run <command>
85
86
  ```
86
87
 
87
88
  Running locally
@@ -0,0 +1,161 @@
1
+ [project]
2
+ name = "sovereign"
3
+ version = "1.0.0a3"
4
+ description = "Envoy Proxy control-plane written in Python"
5
+ authors = [{ name = "Vasili Syrakis", email = "vsyrakis@atlassian.com" }]
6
+ requires-python = ">=3.11.0, <4.0"
7
+ readme = "README.md"
8
+ license = "Apache-2.0"
9
+ keywords = [
10
+ "envoy",
11
+ "envoyproxy",
12
+ "control-plane",
13
+ "management",
14
+ "server",
15
+ ]
16
+ classifiers = [
17
+ "Development Status :: 5 - Production/Stable",
18
+ "Environment :: No Input/Output (Daemon)",
19
+ "Intended Audience :: Developers",
20
+ "Intended Audience :: Information Technology",
21
+ "Intended Audience :: System Administrators",
22
+ "License :: OSI Approved :: Apache Software License",
23
+ "Natural Language :: English",
24
+ "Operating System :: POSIX :: Linux",
25
+ "Programming Language :: Python :: 3.8",
26
+ "Programming Language :: Python :: 3.9",
27
+ "Programming Language :: Python :: 3.10",
28
+ "Programming Language :: Python :: 3.11",
29
+ "Topic :: Internet :: Proxy Servers",
30
+ ]
31
+ dependencies = [
32
+ "uvicorn>=0.23.2,<0.24",
33
+ "aiofiles>=23.2.1,<24",
34
+ "requests>=2.32.4,<3",
35
+ "PyYAML>=6.0.1,<7",
36
+ "Jinja2>=3.1.2,<4",
37
+ "structlog>=23.1.0,<24",
38
+ "cachelib>=0.10.2,<0.11",
39
+ "glom>=23.3.0,<24",
40
+ "cryptography>=45.0.2",
41
+ "fastapi>=0.128.0,<0.129",
42
+ "uvloop>0.19.0,<1.0",
43
+ "croniter>=1.4.1,<2",
44
+ "cachetools>=5.3.2,<6",
45
+ "pydantic>=2.7.2,<3",
46
+ "pydantic-settings<2.6.0",
47
+ "starlette-context>=0.3.6,<0.4",
48
+ "starlette>=0.49.1,<0.50",
49
+ "h11>=0.16.0,<0.17",
50
+ "supervisor>=4.2.5,<5",
51
+ "jmespath>=1.0.1,<2",
52
+ "rich>=14.2.0",
53
+ ]
54
+
55
+ [project.optional-dependencies]
56
+ sentry = ["sentry-sdk>=2.14.0,<3"]
57
+ boto = ["boto3>=1.28.62,<2"]
58
+ statsd = ["datadog>=0.50.1"]
59
+ ujson = ["ujson>=5.8.0,<6"]
60
+ orjson = ["orjson>=3.9.15,<4"]
61
+ caching = []
62
+ httptools = ["httptools>=0.6.0,<0.7"]
63
+
64
+ [project.urls]
65
+ Homepage = "https://pypi.org/project/sovereign/"
66
+ Repository = "https://bitbucket.org/atlassian/sovereign/src/master/"
67
+ Documentation = "https://developer.atlassian.com/platform/sovereign/"
68
+
69
+ [project.scripts]
70
+ sovereign = "sovereign.server:main"
71
+ sovereign-web = "sovereign.server:web"
72
+ sovereign-worker = "sovereign.server:worker"
73
+
74
+ [project.entry-points."sovereign.sources"]
75
+ file = "sovereign.sources.file:File"
76
+ inline = "sovereign.sources.inline:Inline"
77
+
78
+ [project.entry-points."sovereign.modifiers"]
79
+ sovereign_3rd_party_test = "sovereign.testing.modifiers:Test"
80
+
81
+ [project.entry-points."sovereign.loaders"]
82
+ example = "sovereign.testing.loaders:Multiply"
83
+ file = "sovereign.dynamic_config.loaders:File"
84
+ pkgdata = "sovereign.dynamic_config.loaders:PackageData"
85
+ http = "sovereign.dynamic_config.loaders:Web"
86
+ https = "sovereign.dynamic_config.loaders:Web"
87
+ env = "sovereign.dynamic_config.loaders:EnvironmentVariable"
88
+ module = "sovereign.dynamic_config.loaders:PythonModule"
89
+ s3 = "sovereign.dynamic_config.loaders:S3Bucket"
90
+ python = "sovereign.dynamic_config.loaders:PythonInlineCode"
91
+ inline = "sovereign.dynamic_config.loaders:Inline"
92
+
93
+ [project.entry-points."sovereign.deserializers"]
94
+ yaml = "sovereign.dynamic_config.deser:YamlDeserializer"
95
+ json = "sovereign.dynamic_config.deser:JsonDeserializer"
96
+ jinja = "sovereign.dynamic_config.deser:JinjaDeserializer"
97
+ jinja2 = "sovereign.dynamic_config.deser:JinjaDeserializer"
98
+ string = "sovereign.dynamic_config.deser:StringDeserializer"
99
+ raw = "sovereign.dynamic_config.deser:PassthroughDeserializer"
100
+ none = "sovereign.dynamic_config.deser:PassthroughDeserializer"
101
+ passthrough = "sovereign.dynamic_config.deser:PassthroughDeserializer"
102
+ ujson = "sovereign.dynamic_config.deser:UjsonDeserializer"
103
+ orjson = "sovereign.dynamic_config.deser:OrjsonDeserializer"
104
+
105
+ [project.entry-points."sovereign.cache.backends"]
106
+ s3 = "sovereign.cache.backends.s3:S3Backend"
107
+
108
+ [project.entry-points."sovereign.data_stores"]
109
+ memory = "sovereign.v2.data.data_store:InMemoryDataStore"
110
+ sqlite = "sovereign.v2.data.data_store:SqliteDataStore"
111
+
112
+ [project.entry-points."sovereign.queues"]
113
+ memory = "sovereign.v2.data.worker_queue:InMemoryQueue"
114
+ sqlite = "sovereign.v2.data.worker_queue:SqliteQueue"
115
+
116
+ [dependency-groups]
117
+ dev = [
118
+ "freezegun",
119
+ "httpx",
120
+ "moto>=5.0.0",
121
+ "pytest-asyncio",
122
+ "pytest-mock",
123
+ "ruff",
124
+ "tavern",
125
+ "toml",
126
+ "ty",
127
+ "ty==0.0.1a26",
128
+ "types-PyYAML",
129
+ "types-cachetools",
130
+ "types-croniter",
131
+ "types-mock>=5.2.0.20250306,<6",
132
+ "types-requests",
133
+ "types-setuptools",
134
+ "types-ujson",
135
+ ]
136
+
137
+ [tool.hatch.build.targets.sdist]
138
+ include = [
139
+ "src/sovereign",
140
+ "src/sovereign_files",
141
+ "src/sovereign_files/**/*",
142
+ ]
143
+
144
+ [tool.hatch.build.targets.wheel]
145
+ include = [
146
+ "src/sovereign",
147
+ "src/sovereign_files",
148
+ "src/sovereign_files/**/*",
149
+ ]
150
+
151
+ [tool.hatch.build.targets.wheel.sources]
152
+ "src/sovereign" = "sovereign"
153
+ "src/sovereign_files" = "sovereign_files"
154
+
155
+ [[tool.uv.index]]
156
+ url = "https://pypi.org/simple"
157
+ default = true
158
+
159
+ [build-system]
160
+ requires = ["hatchling"]
161
+ build-backend = "hatchling.build"
@@ -0,0 +1,32 @@
1
+ from contextvars import ContextVar
2
+ from importlib.metadata import version
3
+
4
+ from sovereign.configuration import EncryptionConfig, config
5
+ from sovereign.logging.bootstrapper import LoggerBootstrapper
6
+ from sovereign.statistics import configure_statsd
7
+ from sovereign.utils.crypto.crypto import CipherContainer
8
+ from sovereign.utils.crypto.suites import EncryptionType
9
+
10
+ _request_id_ctx_var: ContextVar[str] = ContextVar("request_id", default="")
11
+
12
+
13
+ def get_request_id() -> str:
14
+ return _request_id_ctx_var.get()
15
+
16
+
17
+ WORKER_URL = "http://localhost:9080"
18
+ DIST_NAME = "sovereign"
19
+ __version__ = version(DIST_NAME)
20
+
21
+ stats = configure_statsd()
22
+ logs = LoggerBootstrapper(config)
23
+ application_logger = logs.application_logger.logger
24
+
25
+ encryption_configs = config.authentication.encryption_configs
26
+ server_cipher_container = CipherContainer.from_encryption_configs(
27
+ encryption_configs, logger=application_logger
28
+ )
29
+ disabled_ciphersuite = CipherContainer.from_encryption_configs(
30
+ encryption_configs=[EncryptionConfig("", EncryptionType.DISABLED)],
31
+ logger=application_logger,
32
+ )
@@ -1,4 +1,3 @@
1
- import asyncio
2
1
  import traceback
3
2
  from collections import namedtuple
4
3
 
@@ -7,32 +6,17 @@ from fastapi import FastAPI, Request
7
6
  from fastapi.responses import FileResponse, JSONResponse, RedirectResponse, Response
8
7
  from starlette_context.middleware import RawContextMiddleware
9
8
 
10
- from sovereign import (
11
- __version__,
12
- asgi_config,
13
- config,
14
- logs,
15
- poller,
16
- template_context,
17
- )
18
- from sovereign.response_class import json_response_class
9
+ from sovereign import __version__, logs
10
+ from sovereign.configuration import ConfiguredResourceTypes, config
19
11
  from sovereign.error_info import ErrorInfo
20
12
  from sovereign.middlewares import LoggingMiddleware, RequestContextLogMiddleware
13
+ from sovereign.response_class import json_response_class
21
14
  from sovereign.utils.resources import get_package_file
22
- from sovereign.views import admin, crypto, discovery, healthchecks, interface
15
+ from sovereign.views import api, crypto, discovery, healthchecks, interface
23
16
 
24
17
  Router = namedtuple("Router", "module tags prefix")
25
18
 
26
19
  DEBUG = config.debug
27
- SENTRY_DSN = config.sentry_dsn.get_secret_value()
28
-
29
- try:
30
- import sentry_sdk
31
- from sentry_sdk.integrations.asgi import SentryAsgiMiddleware
32
-
33
- SENTRY_INSTALLED = True
34
- except ImportError: # pragma: no cover
35
- SENTRY_INSTALLED = False
36
20
 
37
21
 
38
22
  def generic_error_response(e: Exception) -> JSONResponse:
@@ -69,25 +53,35 @@ def init_app() -> FastAPI:
69
53
 
70
54
  routers = (
71
55
  Router(discovery.router, ["Configuration Discovery"], ""),
72
- Router(crypto.router, ["Cryptographic Utilities"], "/crypto"),
73
- Router(admin.router, ["Debugging Endpoints"], "/admin"),
74
- Router(interface.router, ["User Interface"], "/ui"),
56
+ Router(api.router, ["API"], "/api"),
75
57
  Router(healthchecks.router, ["Healthchecks"], ""),
58
+ Router(interface.router, ["User Interface"], "/ui"),
59
+ Router(crypto.router, ["Cryptographic Utilities"], "/crypto"),
76
60
  )
77
61
  for router in routers:
78
62
  application.include_router(
79
63
  router.module, tags=router.tags, prefix=router.prefix
80
64
  )
81
65
 
82
- application.add_middleware(RequestContextLogMiddleware)
83
- application.add_middleware(LoggingMiddleware)
66
+ application.add_middleware(RequestContextLogMiddleware) # type: ignore
67
+ application.add_middleware(LoggingMiddleware) # type: ignore
84
68
 
85
- if SENTRY_INSTALLED and SENTRY_DSN:
86
- sentry_sdk.init(SENTRY_DSN)
87
- application.add_middleware(SentryAsgiMiddleware)
88
- logs.application_logger.logger.info("Sentry middleware enabled")
69
+ if dsn := config.sentry_dsn.get_secret_value():
70
+ try:
71
+ # noinspection PyUnusedImports
72
+ import sentry_sdk
89
73
 
90
- application.add_middleware(RawContextMiddleware)
74
+ # noinspection PyUnusedImports
75
+ from sentry_sdk.integrations.asgi import SentryAsgiMiddleware
76
+
77
+ sentry_sdk.init(dsn)
78
+ application.add_middleware(SentryAsgiMiddleware) # type: ignore
79
+ except ImportError:
80
+ logs.application_logger.logger.error(
81
+ "Sentry DSN configured but failed to attach to webserver"
82
+ )
83
+
84
+ application.add_middleware(RawContextMiddleware) # type: ignore
91
85
 
92
86
  @application.exception_handler(500)
93
87
  async def exception_handler(_: Request, exc: Exception) -> JSONResponse:
@@ -105,24 +99,41 @@ def init_app() -> FastAPI:
105
99
 
106
100
  @application.get("/static/{filename}", summary="Return a static asset")
107
101
  async def static(filename: str) -> Response:
108
- return FileResponse(get_package_file("sovereign", f"static/{filename}")) # type: ignore[arg-type]
102
+ return FileResponse(get_package_file("sovereign_files", f"static/{filename}")) # type: ignore[arg-type]
109
103
 
110
- @application.on_event("startup")
111
- async def keep_sources_uptodate() -> None:
112
- if poller is not None:
113
- asyncio.create_task(poller.poll_forever())
114
-
115
- @application.on_event("startup")
116
- async def refresh_template_context() -> None:
117
- asyncio.create_task(template_context.start_refresh_context())
104
+ @application.get(
105
+ "/admin/xds_dump",
106
+ summary="Deprecated API, please use /api/resources/{resource_type}",
107
+ )
108
+ async def dump_resources(request: Request) -> Response:
109
+ resource_type = ConfiguredResourceTypes(
110
+ request.query_params.get("xds_type", "cluster")
111
+ )
112
+ resource_name = request.query_params.get("name")
113
+ api_version = request.query_params.get("api_version", "v3")
114
+ service_cluster = request.query_params.get("service_cluster", "*")
115
+ region = request.query_params.get("region")
116
+ version = request.query_params.get("version")
117
+ response = await api.resource(
118
+ resource_type=resource_type,
119
+ resource_name=resource_name,
120
+ api_version=api_version,
121
+ service_cluster=service_cluster,
122
+ region=region,
123
+ version=version,
124
+ )
125
+ response.headers["Deprecation"] = "true"
126
+ response.headers["Link"] = f'</api/resources/{resource_type}>; rel="alternate"'
127
+ response.headers["Warning"] = (
128
+ f'299 - "Deprecated API: please use /api/resources/{resource_type}"'
129
+ )
130
+ response.status_code = 299
131
+ return response
118
132
 
119
133
  return application
120
134
 
121
135
 
122
136
  app = init_app()
123
- logs.application_logger.logger.info(
124
- f"Sovereign started and listening on {asgi_config.host}:{asgi_config.port}"
125
- )
126
137
 
127
138
 
128
139
  if __name__ == "__main__": # pragma: no cover