supervaizer 0.9.8__py3-none-any.whl → 0.10.1__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.
Files changed (56) hide show
  1. supervaizer/__init__.py +11 -2
  2. supervaizer/__version__.py +1 -1
  3. supervaizer/account.py +4 -0
  4. supervaizer/account_service.py +7 -1
  5. supervaizer/admin/routes.py +24 -8
  6. supervaizer/admin/templates/agents.html +74 -0
  7. supervaizer/admin/templates/agents_grid.html +5 -3
  8. supervaizer/admin/templates/navigation.html +11 -1
  9. supervaizer/admin/templates/supervaize_instructions.html +212 -0
  10. supervaizer/agent.py +28 -6
  11. supervaizer/case.py +46 -14
  12. supervaizer/cli.py +247 -7
  13. supervaizer/common.py +45 -4
  14. supervaizer/deploy/__init__.py +16 -0
  15. supervaizer/deploy/cli.py +296 -0
  16. supervaizer/deploy/commands/__init__.py +9 -0
  17. supervaizer/deploy/commands/clean.py +294 -0
  18. supervaizer/deploy/commands/down.py +119 -0
  19. supervaizer/deploy/commands/local.py +460 -0
  20. supervaizer/deploy/commands/plan.py +167 -0
  21. supervaizer/deploy/commands/status.py +169 -0
  22. supervaizer/deploy/commands/up.py +281 -0
  23. supervaizer/deploy/docker.py +378 -0
  24. supervaizer/deploy/driver_factory.py +42 -0
  25. supervaizer/deploy/drivers/__init__.py +39 -0
  26. supervaizer/deploy/drivers/aws_app_runner.py +607 -0
  27. supervaizer/deploy/drivers/base.py +196 -0
  28. supervaizer/deploy/drivers/cloud_run.py +570 -0
  29. supervaizer/deploy/drivers/do_app_platform.py +504 -0
  30. supervaizer/deploy/health.py +404 -0
  31. supervaizer/deploy/state.py +210 -0
  32. supervaizer/deploy/templates/Dockerfile.template +44 -0
  33. supervaizer/deploy/templates/debug_env.py +69 -0
  34. supervaizer/deploy/templates/docker-compose.yml.template +37 -0
  35. supervaizer/deploy/templates/dockerignore.template +66 -0
  36. supervaizer/deploy/templates/entrypoint.sh +20 -0
  37. supervaizer/deploy/utils.py +52 -0
  38. supervaizer/examples/controller_template.py +1 -1
  39. supervaizer/job.py +18 -5
  40. supervaizer/job_service.py +6 -5
  41. supervaizer/parameter.py +13 -1
  42. supervaizer/protocol/__init__.py +2 -2
  43. supervaizer/protocol/a2a/routes.py +1 -1
  44. supervaizer/routes.py +141 -17
  45. supervaizer/server.py +5 -11
  46. supervaizer/utils/__init__.py +16 -0
  47. supervaizer/utils/version_check.py +56 -0
  48. {supervaizer-0.9.8.dist-info → supervaizer-0.10.1.dist-info}/METADATA +105 -34
  49. supervaizer-0.10.1.dist-info/RECORD +76 -0
  50. {supervaizer-0.9.8.dist-info → supervaizer-0.10.1.dist-info}/WHEEL +1 -1
  51. supervaizer/protocol/acp/__init__.py +0 -21
  52. supervaizer/protocol/acp/model.py +0 -198
  53. supervaizer/protocol/acp/routes.py +0 -74
  54. supervaizer-0.9.8.dist-info/RECORD +0 -52
  55. {supervaizer-0.9.8.dist-info → supervaizer-0.10.1.dist-info}/entry_points.txt +0 -0
  56. {supervaizer-0.9.8.dist-info → supervaizer-0.10.1.dist-info}/licenses/LICENSE.md +0 -0
@@ -0,0 +1,196 @@
1
+ # Copyright (c) 2024-2025 Alain Prasquier - Supervaize.com. All rights reserved.
2
+ #
3
+ # This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
4
+ # If a copy of the MPL was not distributed with this file, you can obtain one at
5
+ # https://mozilla.org/MPL/2.0/.
6
+
7
+ """
8
+ Base Driver Interface
9
+
10
+ This module defines the base interface for deployment drivers.
11
+ """
12
+
13
+ from abc import ABC, abstractmethod
14
+ from dataclasses import dataclass
15
+ from enum import Enum
16
+ from typing import Any, Dict, List, Optional
17
+
18
+ from pydantic import BaseModel
19
+
20
+
21
+ class ActionType(str, Enum):
22
+ """Type of deployment action."""
23
+
24
+ CREATE = "create"
25
+ UPDATE = "update"
26
+ NOOP = "noop"
27
+ DELETE = "delete"
28
+
29
+
30
+ class ResourceType(str, Enum):
31
+ """Type of cloud resource."""
32
+
33
+ SERVICE = "service"
34
+ SECRET = "secret"
35
+ REGISTRY = "registry"
36
+ IMAGE = "image"
37
+
38
+
39
+ @dataclass
40
+ class ResourceAction:
41
+ """Represents an action to be taken on a resource."""
42
+
43
+ resource_type: ResourceType
44
+ action_type: ActionType
45
+ resource_name: str
46
+ description: str
47
+ cost_estimate: Optional[str] = None
48
+ metadata: Optional[Dict[str, Any]] = None
49
+
50
+
51
+ class DeploymentPlan(BaseModel):
52
+ """Deployment plan containing all actions to be taken."""
53
+
54
+ platform: str
55
+ service_name: str
56
+ environment: str
57
+ region: str
58
+ project_id: Optional[str] = None
59
+
60
+ # Plan details
61
+ actions: List[ResourceAction] = []
62
+ total_cost_estimate: Optional[str] = None
63
+ estimated_duration: Optional[str] = None
64
+
65
+ # Current state
66
+ current_image: Optional[str] = None
67
+ current_url: Optional[str] = None
68
+ current_status: Optional[str] = None
69
+
70
+ # Target state
71
+ target_image: str
72
+ target_port: int = 8000
73
+ target_env_vars: Dict[str, str] = {}
74
+ target_secrets: Dict[str, str] = {}
75
+
76
+
77
+ class DeploymentResult(BaseModel):
78
+ """Result of a deployment operation."""
79
+
80
+ success: bool
81
+ service_url: Optional[str] = None
82
+ service_id: Optional[str] = None
83
+ revision: Optional[str] = None
84
+ image_digest: Optional[str] = None
85
+
86
+ # Status information
87
+ status: str = "unknown"
88
+ health_status: str = "unknown"
89
+
90
+ # Timing
91
+ deployment_time: Optional[float] = None
92
+
93
+ # Error information
94
+ error_message: Optional[str] = None
95
+ error_details: Optional[Dict[str, Any]] = None
96
+
97
+
98
+ class BaseDriver(ABC):
99
+ """Base interface for deployment drivers."""
100
+
101
+ def __init__(self, region: str, project_id: Optional[str] = None):
102
+ """Initialize the driver."""
103
+ self.region = region
104
+ self.project_id = project_id
105
+
106
+ @abstractmethod
107
+ def plan_deployment(
108
+ self,
109
+ service_name: str,
110
+ environment: str,
111
+ image_tag: str,
112
+ port: int = 8000,
113
+ env_vars: Optional[Dict[str, str]] = None,
114
+ secrets: Optional[Dict[str, str]] = None,
115
+ ) -> DeploymentPlan:
116
+ """Plan deployment changes without applying them."""
117
+ pass
118
+
119
+ @abstractmethod
120
+ def deploy_service(
121
+ self,
122
+ service_name: str,
123
+ environment: str,
124
+ image_tag: str,
125
+ port: int = 8000,
126
+ env_vars: Optional[Dict[str, str]] = None,
127
+ secrets: Optional[Dict[str, str]] = None,
128
+ timeout: int = 300,
129
+ ) -> DeploymentResult:
130
+ """Deploy or update the service."""
131
+ pass
132
+
133
+ @abstractmethod
134
+ def destroy_service(
135
+ self,
136
+ service_name: str,
137
+ environment: str,
138
+ keep_secrets: bool = False,
139
+ ) -> DeploymentResult:
140
+ """Destroy the service and cleanup resources."""
141
+ pass
142
+
143
+ @abstractmethod
144
+ def get_service_status(
145
+ self,
146
+ service_name: str,
147
+ environment: str,
148
+ ) -> DeploymentResult:
149
+ """Get current service status and health."""
150
+ pass
151
+
152
+ @abstractmethod
153
+ def verify_health(self, service_url: str, timeout: int = 60) -> bool:
154
+ """Verify service health by checking the health endpoint."""
155
+ pass
156
+
157
+ def verify_health_enhanced(
158
+ self,
159
+ service_url: str,
160
+ api_key: Optional[str] = None,
161
+ timeout: int = 60,
162
+ max_retries: int = 5,
163
+ ) -> bool:
164
+ """
165
+ Enhanced health verification with retry logic and exponential backoff.
166
+
167
+ Args:
168
+ service_url: Base URL of the service
169
+ api_key: Optional API key for authenticated endpoints
170
+ timeout: Request timeout in seconds
171
+ max_retries: Maximum number of retry attempts
172
+
173
+ Returns:
174
+ True if service is healthy, False otherwise
175
+ """
176
+ from supervaizer.deploy.health import verify_service_health
177
+
178
+ return verify_service_health(service_url, api_key, timeout, max_retries)
179
+
180
+ @abstractmethod
181
+ def check_prerequisites(self) -> List[str]:
182
+ """Check prerequisites and return list of missing requirements."""
183
+ pass
184
+
185
+ def get_service_key(self, service_name: str, environment: str) -> str:
186
+ """Generate a unique key for the service."""
187
+ return f"{service_name}-{environment}"
188
+
189
+ def validate_configuration(self, **kwargs: Any) -> List[str]:
190
+ """Validate driver configuration and return list of errors."""
191
+ errors = []
192
+
193
+ if not self.region:
194
+ errors.append("Region is required")
195
+
196
+ return errors