spring-ready-python 0.1.0__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.
- spring_ready/__init__.py +30 -0
- spring_ready/actuator/__init__.py +68 -0
- spring_ready/actuator/auditevents.py +114 -0
- spring_ready/actuator/beans.py +141 -0
- spring_ready/actuator/caches.py +111 -0
- spring_ready/actuator/configprops.py +109 -0
- spring_ready/actuator/discovery.py +131 -0
- spring_ready/actuator/env.py +205 -0
- spring_ready/actuator/health.py +145 -0
- spring_ready/actuator/heapdump.py +80 -0
- spring_ready/actuator/httptrace.py +138 -0
- spring_ready/actuator/info.py +123 -0
- spring_ready/actuator/logfile.py +201 -0
- spring_ready/actuator/loggers.py +184 -0
- spring_ready/actuator/mappings.py +88 -0
- spring_ready/actuator/metrics.py +260 -0
- spring_ready/actuator/prometheus.py +354 -0
- spring_ready/actuator/refresh.py +86 -0
- spring_ready/actuator/scheduledtasks.py +95 -0
- spring_ready/actuator/threaddump.py +116 -0
- spring_ready/config/__init__.py +5 -0
- spring_ready/config/loader.py +215 -0
- spring_ready/core.py +479 -0
- spring_ready/eureka/__init__.py +15 -0
- spring_ready/eureka/client.py +291 -0
- spring_ready/eureka/discovery.py +198 -0
- spring_ready/eureka/instance.py +200 -0
- spring_ready/eureka/registry.py +191 -0
- spring_ready/exceptions.py +26 -0
- spring_ready/integrations/__init__.py +8 -0
- spring_ready/integrations/fastapi.py +521 -0
- spring_ready/retry.py +97 -0
- spring_ready_python-0.1.0.dist-info/METADATA +459 -0
- spring_ready_python-0.1.0.dist-info/RECORD +35 -0
- spring_ready_python-0.1.0.dist-info/WHEEL +4 -0
spring_ready/__init__.py
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Spring-Ready Python
|
|
3
|
+
A lightweight library to make Python apps Spring Boot ecosystem compatible.
|
|
4
|
+
|
|
5
|
+
Provides:
|
|
6
|
+
- Eureka service registration
|
|
7
|
+
- Config Server integration with discovery
|
|
8
|
+
- Actuator endpoints (health, info, prometheus)
|
|
9
|
+
- FastAPI integration
|
|
10
|
+
|
|
11
|
+
Usage:
|
|
12
|
+
from spring_ready import SpringReadyApp
|
|
13
|
+
|
|
14
|
+
app = SpringReadyApp()
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
from .core import SpringReadyApp
|
|
18
|
+
from .exceptions import (
|
|
19
|
+
SpringReadyException,
|
|
20
|
+
EurekaRegistrationError,
|
|
21
|
+
ConfigServerError,
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
__version__ = "0.1.0"
|
|
25
|
+
__all__ = [
|
|
26
|
+
"SpringReadyApp",
|
|
27
|
+
"SpringReadyException",
|
|
28
|
+
"EurekaRegistrationError",
|
|
29
|
+
"ConfigServerError",
|
|
30
|
+
]
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"""Spring Boot Actuator-compatible endpoints"""
|
|
2
|
+
|
|
3
|
+
from .health import HealthEndpoint, HealthIndicator, HealthStatus, create_default_health_endpoint
|
|
4
|
+
from .info import InfoEndpoint, create_default_info_endpoint
|
|
5
|
+
from .prometheus import PrometheusEndpoint, create_default_prometheus_endpoint
|
|
6
|
+
from .discovery import ActuatorDiscoveryEndpoint, create_default_discovery_endpoint
|
|
7
|
+
from .metrics import MetricsEndpoint, create_default_metrics_endpoint
|
|
8
|
+
from .env import EnvEndpoint, create_default_env_endpoint
|
|
9
|
+
from .loggers import LoggersEndpoint, create_default_loggers_endpoint
|
|
10
|
+
from .mappings import MappingsEndpoint, create_default_mappings_endpoint
|
|
11
|
+
from .threaddump import ThreadDumpEndpoint, create_default_threaddump_endpoint
|
|
12
|
+
from .httptrace import (
|
|
13
|
+
HttpTraceEndpoint,
|
|
14
|
+
HttpExchangesEndpoint,
|
|
15
|
+
create_default_httptrace_endpoint,
|
|
16
|
+
create_default_httpexchanges_endpoint
|
|
17
|
+
)
|
|
18
|
+
from .logfile import LogfileEndpoint, create_default_logfile_endpoint
|
|
19
|
+
from .refresh import RefreshEndpoint, create_default_refresh_endpoint
|
|
20
|
+
from .beans import BeansEndpoint, create_default_beans_endpoint
|
|
21
|
+
from .configprops import ConfigPropsEndpoint, create_default_configprops_endpoint
|
|
22
|
+
from .scheduledtasks import ScheduledTasksEndpoint, create_default_scheduledtasks_endpoint
|
|
23
|
+
from .heapdump import HeapdumpEndpoint, create_default_heapdump_endpoint
|
|
24
|
+
from .caches import CachesEndpoint, create_default_caches_endpoint
|
|
25
|
+
from .auditevents import AuditEventsEndpoint, create_default_auditevents_endpoint
|
|
26
|
+
|
|
27
|
+
__all__ = [
|
|
28
|
+
"HealthEndpoint",
|
|
29
|
+
"HealthIndicator",
|
|
30
|
+
"HealthStatus",
|
|
31
|
+
"create_default_health_endpoint",
|
|
32
|
+
"InfoEndpoint",
|
|
33
|
+
"create_default_info_endpoint",
|
|
34
|
+
"PrometheusEndpoint",
|
|
35
|
+
"create_default_prometheus_endpoint",
|
|
36
|
+
"ActuatorDiscoveryEndpoint",
|
|
37
|
+
"create_default_discovery_endpoint",
|
|
38
|
+
"MetricsEndpoint",
|
|
39
|
+
"create_default_metrics_endpoint",
|
|
40
|
+
"EnvEndpoint",
|
|
41
|
+
"create_default_env_endpoint",
|
|
42
|
+
"LoggersEndpoint",
|
|
43
|
+
"create_default_loggers_endpoint",
|
|
44
|
+
"MappingsEndpoint",
|
|
45
|
+
"create_default_mappings_endpoint",
|
|
46
|
+
"ThreadDumpEndpoint",
|
|
47
|
+
"create_default_threaddump_endpoint",
|
|
48
|
+
"HttpTraceEndpoint",
|
|
49
|
+
"HttpExchangesEndpoint",
|
|
50
|
+
"create_default_httptrace_endpoint",
|
|
51
|
+
"create_default_httpexchanges_endpoint",
|
|
52
|
+
"LogfileEndpoint",
|
|
53
|
+
"create_default_logfile_endpoint",
|
|
54
|
+
"RefreshEndpoint",
|
|
55
|
+
"create_default_refresh_endpoint",
|
|
56
|
+
"BeansEndpoint",
|
|
57
|
+
"create_default_beans_endpoint",
|
|
58
|
+
"ConfigPropsEndpoint",
|
|
59
|
+
"create_default_configprops_endpoint",
|
|
60
|
+
"ScheduledTasksEndpoint",
|
|
61
|
+
"create_default_scheduledtasks_endpoint",
|
|
62
|
+
"HeapdumpEndpoint",
|
|
63
|
+
"create_default_heapdump_endpoint",
|
|
64
|
+
"CachesEndpoint",
|
|
65
|
+
"create_default_caches_endpoint",
|
|
66
|
+
"AuditEventsEndpoint",
|
|
67
|
+
"create_default_auditevents_endpoint",
|
|
68
|
+
]
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Actuator AuditEvents Endpoint.
|
|
3
|
+
Provides information about security-related audit events.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import time
|
|
7
|
+
from typing import Dict, Any, List, Optional
|
|
8
|
+
from dataclasses import dataclass, field
|
|
9
|
+
from collections import deque
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@dataclass
|
|
13
|
+
class AuditEvent:
|
|
14
|
+
"""Single audit event"""
|
|
15
|
+
timestamp: str
|
|
16
|
+
principal: str
|
|
17
|
+
type: str
|
|
18
|
+
data: Dict[str, Any] = field(default_factory=dict)
|
|
19
|
+
|
|
20
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
21
|
+
return {
|
|
22
|
+
"timestamp": self.timestamp,
|
|
23
|
+
"principal": self.principal,
|
|
24
|
+
"type": self.type,
|
|
25
|
+
"data": self.data
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class AuditEventsEndpoint:
|
|
30
|
+
"""
|
|
31
|
+
AuditEvents endpoint for Spring Boot Actuator compatibility.
|
|
32
|
+
|
|
33
|
+
Tracks security-related events like authentication, authorization, etc.
|
|
34
|
+
Stores events in memory with configurable max size.
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
def __init__(self, max_events: int = 1000):
|
|
38
|
+
"""
|
|
39
|
+
Args:
|
|
40
|
+
max_events: Maximum number of events to keep in memory
|
|
41
|
+
"""
|
|
42
|
+
self.max_events = max_events
|
|
43
|
+
self.events: deque = deque(maxlen=max_events)
|
|
44
|
+
|
|
45
|
+
def add_event(
|
|
46
|
+
self,
|
|
47
|
+
principal: str,
|
|
48
|
+
event_type: str,
|
|
49
|
+
data: Optional[Dict[str, Any]] = None
|
|
50
|
+
) -> None:
|
|
51
|
+
"""
|
|
52
|
+
Add an audit event.
|
|
53
|
+
|
|
54
|
+
Args:
|
|
55
|
+
principal: Principal (user/system) that triggered the event
|
|
56
|
+
event_type: Event type (e.g., "AUTHENTICATION_SUCCESS", "AUTHORIZATION_FAILURE")
|
|
57
|
+
data: Additional event data
|
|
58
|
+
"""
|
|
59
|
+
timestamp = time.strftime("%Y-%m-%dT%H:%M:%S.000Z", time.gmtime())
|
|
60
|
+
|
|
61
|
+
event = AuditEvent(
|
|
62
|
+
timestamp=timestamp,
|
|
63
|
+
principal=principal,
|
|
64
|
+
type=event_type,
|
|
65
|
+
data=data or {}
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
self.events.append(event)
|
|
69
|
+
|
|
70
|
+
def get_events(
|
|
71
|
+
self,
|
|
72
|
+
principal: Optional[str] = None,
|
|
73
|
+
after: Optional[str] = None,
|
|
74
|
+
event_type: Optional[str] = None
|
|
75
|
+
) -> Dict[str, Any]:
|
|
76
|
+
"""
|
|
77
|
+
Get audit events with optional filtering.
|
|
78
|
+
|
|
79
|
+
Args:
|
|
80
|
+
principal: Filter by principal name
|
|
81
|
+
after: Filter events after this timestamp
|
|
82
|
+
event_type: Filter by event type
|
|
83
|
+
|
|
84
|
+
Returns:
|
|
85
|
+
Dictionary with filtered audit events
|
|
86
|
+
"""
|
|
87
|
+
filtered_events = list(self.events)
|
|
88
|
+
|
|
89
|
+
# Apply filters
|
|
90
|
+
if principal:
|
|
91
|
+
filtered_events = [e for e in filtered_events if e.principal == principal]
|
|
92
|
+
|
|
93
|
+
if after:
|
|
94
|
+
filtered_events = [e for e in filtered_events if e.timestamp > after]
|
|
95
|
+
|
|
96
|
+
if event_type:
|
|
97
|
+
filtered_events = [e for e in filtered_events if e.type == event_type]
|
|
98
|
+
|
|
99
|
+
return {
|
|
100
|
+
"events": [event.to_dict() for event in filtered_events]
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def create_default_auditevents_endpoint(max_events: int = 1000) -> AuditEventsEndpoint:
|
|
105
|
+
"""
|
|
106
|
+
Create auditevents endpoint with default configuration.
|
|
107
|
+
|
|
108
|
+
Args:
|
|
109
|
+
max_events: Maximum number of events to keep
|
|
110
|
+
|
|
111
|
+
Returns:
|
|
112
|
+
AuditEventsEndpoint instance
|
|
113
|
+
"""
|
|
114
|
+
return AuditEventsEndpoint(max_events=max_events)
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Actuator Beans Endpoint.
|
|
3
|
+
Shows information about application beans/components.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import sys
|
|
7
|
+
from typing import Dict, Any, Optional, TYPE_CHECKING
|
|
8
|
+
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from fastapi import FastAPI
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class BeansEndpoint:
|
|
14
|
+
"""
|
|
15
|
+
Beans endpoint for Spring Boot Actuator compatibility.
|
|
16
|
+
|
|
17
|
+
Shows information about application components, similar to Spring's bean registry.
|
|
18
|
+
In Python/FastAPI context, this includes:
|
|
19
|
+
- Registered routes
|
|
20
|
+
- Middleware components
|
|
21
|
+
- Dependency injection components
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
def __init__(self, app: Optional['FastAPI'] = None):
|
|
25
|
+
"""
|
|
26
|
+
Args:
|
|
27
|
+
app: FastAPI application instance
|
|
28
|
+
"""
|
|
29
|
+
self.app = app
|
|
30
|
+
|
|
31
|
+
def get_beans(self) -> Dict[str, Any]:
|
|
32
|
+
"""
|
|
33
|
+
Get all beans/components.
|
|
34
|
+
|
|
35
|
+
Returns:
|
|
36
|
+
Dictionary with application contexts and bean definitions
|
|
37
|
+
"""
|
|
38
|
+
beans = {}
|
|
39
|
+
|
|
40
|
+
if self.app:
|
|
41
|
+
# Add FastAPI app itself
|
|
42
|
+
beans["fastapi_app"] = {
|
|
43
|
+
"type": "fastapi.applications.FastAPI",
|
|
44
|
+
"scope": "singleton",
|
|
45
|
+
"attributes": {
|
|
46
|
+
"title": self.app.title,
|
|
47
|
+
"version": self.app.version,
|
|
48
|
+
"openapi_url": self.app.openapi_url,
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
# Add middleware
|
|
53
|
+
middleware_beans = self._get_middleware_beans()
|
|
54
|
+
beans.update(middleware_beans)
|
|
55
|
+
|
|
56
|
+
# Add routes as beans
|
|
57
|
+
route_beans = self._get_route_beans()
|
|
58
|
+
beans.update(route_beans)
|
|
59
|
+
|
|
60
|
+
# Add Python system components
|
|
61
|
+
system_beans = self._get_system_beans()
|
|
62
|
+
beans.update(system_beans)
|
|
63
|
+
|
|
64
|
+
return {
|
|
65
|
+
"contexts": {
|
|
66
|
+
"application": {
|
|
67
|
+
"beans": beans,
|
|
68
|
+
"parentId": None
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
def _get_middleware_beans(self) -> Dict[str, Any]:
|
|
74
|
+
"""Get middleware components as beans"""
|
|
75
|
+
middleware_beans = {}
|
|
76
|
+
|
|
77
|
+
if not self.app or not hasattr(self.app, 'user_middleware'):
|
|
78
|
+
return middleware_beans
|
|
79
|
+
|
|
80
|
+
for idx, middleware in enumerate(self.app.user_middleware):
|
|
81
|
+
middleware_cls = middleware.cls if hasattr(middleware, 'cls') else middleware
|
|
82
|
+
bean_name = f"middleware_{idx}_{middleware_cls.__name__}"
|
|
83
|
+
|
|
84
|
+
middleware_beans[bean_name] = {
|
|
85
|
+
"type": f"{middleware_cls.__module__}.{middleware_cls.__name__}",
|
|
86
|
+
"scope": "singleton",
|
|
87
|
+
"attributes": {}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return middleware_beans
|
|
91
|
+
|
|
92
|
+
def _get_route_beans(self) -> Dict[str, Any]:
|
|
93
|
+
"""Get routes as beans"""
|
|
94
|
+
route_beans = {}
|
|
95
|
+
|
|
96
|
+
if not self.app:
|
|
97
|
+
return route_beans
|
|
98
|
+
|
|
99
|
+
for route in self.app.routes:
|
|
100
|
+
if hasattr(route, 'endpoint') and hasattr(route, 'path'):
|
|
101
|
+
endpoint_name = route.endpoint.__name__ if hasattr(route.endpoint, '__name__') else str(route.endpoint)
|
|
102
|
+
bean_name = f"route_{endpoint_name}_{route.path.replace('/', '_').replace('{', '').replace('}', '')}"
|
|
103
|
+
|
|
104
|
+
route_beans[bean_name] = {
|
|
105
|
+
"type": "fastapi.routing.APIRoute",
|
|
106
|
+
"scope": "singleton",
|
|
107
|
+
"attributes": {
|
|
108
|
+
"path": route.path,
|
|
109
|
+
"methods": list(route.methods) if hasattr(route, 'methods') else [],
|
|
110
|
+
"name": route.name if hasattr(route, 'name') else None
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return route_beans
|
|
115
|
+
|
|
116
|
+
def _get_system_beans(self) -> Dict[str, Any]:
|
|
117
|
+
"""Get Python system components"""
|
|
118
|
+
return {
|
|
119
|
+
"python_interpreter": {
|
|
120
|
+
"type": "system.python.interpreter",
|
|
121
|
+
"scope": "singleton",
|
|
122
|
+
"attributes": {
|
|
123
|
+
"version": sys.version.split()[0],
|
|
124
|
+
"executable": sys.executable,
|
|
125
|
+
"platform": sys.platform
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def create_default_beans_endpoint(app: Optional['FastAPI'] = None) -> BeansEndpoint:
|
|
132
|
+
"""
|
|
133
|
+
Create beans endpoint with default configuration.
|
|
134
|
+
|
|
135
|
+
Args:
|
|
136
|
+
app: FastAPI application instance
|
|
137
|
+
|
|
138
|
+
Returns:
|
|
139
|
+
BeansEndpoint instance
|
|
140
|
+
"""
|
|
141
|
+
return BeansEndpoint(app=app)
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Actuator Caches Endpoint.
|
|
3
|
+
Provides access to application caches.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from typing import Dict, Any, Optional, List
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class CachesEndpoint:
|
|
10
|
+
"""
|
|
11
|
+
Caches endpoint for Spring Boot Actuator compatibility.
|
|
12
|
+
|
|
13
|
+
Provides access to application caches.
|
|
14
|
+
Currently returns empty structure as no cache manager is configured by default.
|
|
15
|
+
Can be extended to integrate with Redis, Memcached, or in-memory caches.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
def __init__(self):
|
|
19
|
+
"""Initialize caches endpoint"""
|
|
20
|
+
self.cache_managers: Dict[str, Dict[str, Any]] = {}
|
|
21
|
+
|
|
22
|
+
def get_caches(self) -> Dict[str, Any]:
|
|
23
|
+
"""
|
|
24
|
+
Get all caches.
|
|
25
|
+
|
|
26
|
+
Returns:
|
|
27
|
+
Dictionary with cache managers and caches
|
|
28
|
+
"""
|
|
29
|
+
caches = {}
|
|
30
|
+
|
|
31
|
+
for manager_name, manager_info in self.cache_managers.items():
|
|
32
|
+
for cache_name in manager_info.get("caches", []):
|
|
33
|
+
caches[cache_name] = {
|
|
34
|
+
"target": f"{manager_name}::{cache_name}",
|
|
35
|
+
"cacheManager": manager_name
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return {
|
|
39
|
+
"cacheManagers": self.cache_managers,
|
|
40
|
+
"caches": caches
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
def get_cache(self, cache_name: str, cache_manager: Optional[str] = None) -> Optional[Dict[str, Any]]:
|
|
44
|
+
"""
|
|
45
|
+
Get a specific cache.
|
|
46
|
+
|
|
47
|
+
Args:
|
|
48
|
+
cache_name: Cache name
|
|
49
|
+
cache_manager: Optional cache manager name
|
|
50
|
+
|
|
51
|
+
Returns:
|
|
52
|
+
Cache details or None if not found
|
|
53
|
+
"""
|
|
54
|
+
for manager_name, manager_info in self.cache_managers.items():
|
|
55
|
+
if cache_manager and manager_name != cache_manager:
|
|
56
|
+
continue
|
|
57
|
+
|
|
58
|
+
if cache_name in manager_info.get("caches", []):
|
|
59
|
+
return {
|
|
60
|
+
"target": f"{manager_name}::{cache_name}",
|
|
61
|
+
"name": cache_name,
|
|
62
|
+
"cacheManager": manager_name
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return None
|
|
66
|
+
|
|
67
|
+
def evict_cache(self, cache_name: str, cache_manager: Optional[str] = None) -> bool:
|
|
68
|
+
"""
|
|
69
|
+
Evict a specific cache.
|
|
70
|
+
|
|
71
|
+
Args:
|
|
72
|
+
cache_name: Cache name
|
|
73
|
+
cache_manager: Optional cache manager name
|
|
74
|
+
|
|
75
|
+
Returns:
|
|
76
|
+
True if cache was evicted, False otherwise
|
|
77
|
+
"""
|
|
78
|
+
# Placeholder - actual eviction would depend on cache implementation
|
|
79
|
+
return self.get_cache(cache_name, cache_manager) is not None
|
|
80
|
+
|
|
81
|
+
def evict_all_caches(self) -> bool:
|
|
82
|
+
"""
|
|
83
|
+
Evict all caches.
|
|
84
|
+
|
|
85
|
+
Returns:
|
|
86
|
+
True if successful
|
|
87
|
+
"""
|
|
88
|
+
# Placeholder - actual eviction would depend on cache implementation
|
|
89
|
+
return True
|
|
90
|
+
|
|
91
|
+
def add_cache_manager(self, name: str, caches: List[str]) -> None:
|
|
92
|
+
"""
|
|
93
|
+
Register a cache manager.
|
|
94
|
+
|
|
95
|
+
Args:
|
|
96
|
+
name: Cache manager name
|
|
97
|
+
caches: List of cache names
|
|
98
|
+
"""
|
|
99
|
+
self.cache_managers[name] = {
|
|
100
|
+
"caches": caches
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def create_default_caches_endpoint() -> CachesEndpoint:
|
|
105
|
+
"""
|
|
106
|
+
Create caches endpoint with default configuration.
|
|
107
|
+
|
|
108
|
+
Returns:
|
|
109
|
+
CachesEndpoint instance
|
|
110
|
+
"""
|
|
111
|
+
return CachesEndpoint()
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Actuator ConfigProps Endpoint.
|
|
3
|
+
Shows configuration properties grouped by prefix.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import os
|
|
7
|
+
from typing import Dict, Any
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class ConfigPropsEndpoint:
|
|
11
|
+
"""
|
|
12
|
+
ConfigProps endpoint for Spring Boot Actuator compatibility.
|
|
13
|
+
|
|
14
|
+
Shows configuration properties similar to Spring Boot's @ConfigurationProperties.
|
|
15
|
+
Groups environment variables and settings by common prefixes.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
def get_config_props(self) -> Dict[str, Any]:
|
|
19
|
+
"""
|
|
20
|
+
Get all configuration properties grouped by prefix.
|
|
21
|
+
|
|
22
|
+
Returns:
|
|
23
|
+
Dictionary with configuration property beans
|
|
24
|
+
"""
|
|
25
|
+
# Group environment variables by common prefixes
|
|
26
|
+
grouped_props = self._group_by_prefix(dict(os.environ))
|
|
27
|
+
|
|
28
|
+
beans = {}
|
|
29
|
+
for prefix, props in grouped_props.items():
|
|
30
|
+
bean_name = f"{prefix}_properties"
|
|
31
|
+
beans[bean_name] = {
|
|
32
|
+
"prefix": prefix,
|
|
33
|
+
"properties": props
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return {
|
|
37
|
+
"contexts": {
|
|
38
|
+
"application": {
|
|
39
|
+
"beans": beans
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
def get_config_props_by_prefix(self, prefix: str) -> Dict[str, Any]:
|
|
45
|
+
"""
|
|
46
|
+
Get configuration properties filtered by prefix.
|
|
47
|
+
|
|
48
|
+
Args:
|
|
49
|
+
prefix: Prefix to filter by
|
|
50
|
+
|
|
51
|
+
Returns:
|
|
52
|
+
Dictionary with matching configuration properties
|
|
53
|
+
"""
|
|
54
|
+
matching_props = {}
|
|
55
|
+
|
|
56
|
+
for key, value in os.environ.items():
|
|
57
|
+
if key.startswith(prefix.upper()) or key.lower().startswith(prefix.lower()):
|
|
58
|
+
matching_props[key] = value
|
|
59
|
+
|
|
60
|
+
if not matching_props:
|
|
61
|
+
return {}
|
|
62
|
+
|
|
63
|
+
bean_name = f"{prefix}_properties"
|
|
64
|
+
return {
|
|
65
|
+
"contexts": {
|
|
66
|
+
"application": {
|
|
67
|
+
"beans": {
|
|
68
|
+
bean_name: {
|
|
69
|
+
"prefix": prefix,
|
|
70
|
+
"properties": matching_props
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
def _group_by_prefix(self, env_vars: Dict[str, str]) -> Dict[str, Dict[str, str]]:
|
|
78
|
+
"""
|
|
79
|
+
Group environment variables by common prefixes.
|
|
80
|
+
|
|
81
|
+
Args:
|
|
82
|
+
env_vars: Environment variables dictionary
|
|
83
|
+
|
|
84
|
+
Returns:
|
|
85
|
+
Dictionary grouped by prefix
|
|
86
|
+
"""
|
|
87
|
+
grouped = {}
|
|
88
|
+
|
|
89
|
+
for key, value in env_vars.items():
|
|
90
|
+
# Extract prefix (first part before _)
|
|
91
|
+
parts = key.split('_', 1)
|
|
92
|
+
prefix = parts[0] if parts else key
|
|
93
|
+
|
|
94
|
+
if prefix not in grouped:
|
|
95
|
+
grouped[prefix] = {}
|
|
96
|
+
|
|
97
|
+
grouped[prefix][key] = value
|
|
98
|
+
|
|
99
|
+
return grouped
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def create_default_configprops_endpoint() -> ConfigPropsEndpoint:
|
|
103
|
+
"""
|
|
104
|
+
Create configprops endpoint with default configuration.
|
|
105
|
+
|
|
106
|
+
Returns:
|
|
107
|
+
ConfigPropsEndpoint instance
|
|
108
|
+
"""
|
|
109
|
+
return ConfigPropsEndpoint()
|