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.
- supervaizer/__init__.py +11 -2
- supervaizer/__version__.py +1 -1
- supervaizer/account.py +4 -0
- supervaizer/account_service.py +7 -1
- supervaizer/admin/routes.py +24 -8
- supervaizer/admin/templates/agents.html +74 -0
- supervaizer/admin/templates/agents_grid.html +5 -3
- supervaizer/admin/templates/navigation.html +11 -1
- supervaizer/admin/templates/supervaize_instructions.html +212 -0
- supervaizer/agent.py +28 -6
- supervaizer/case.py +46 -14
- supervaizer/cli.py +247 -7
- supervaizer/common.py +45 -4
- supervaizer/deploy/__init__.py +16 -0
- supervaizer/deploy/cli.py +296 -0
- supervaizer/deploy/commands/__init__.py +9 -0
- supervaizer/deploy/commands/clean.py +294 -0
- supervaizer/deploy/commands/down.py +119 -0
- supervaizer/deploy/commands/local.py +460 -0
- supervaizer/deploy/commands/plan.py +167 -0
- supervaizer/deploy/commands/status.py +169 -0
- supervaizer/deploy/commands/up.py +281 -0
- supervaizer/deploy/docker.py +378 -0
- supervaizer/deploy/driver_factory.py +42 -0
- supervaizer/deploy/drivers/__init__.py +39 -0
- supervaizer/deploy/drivers/aws_app_runner.py +607 -0
- supervaizer/deploy/drivers/base.py +196 -0
- supervaizer/deploy/drivers/cloud_run.py +570 -0
- supervaizer/deploy/drivers/do_app_platform.py +504 -0
- supervaizer/deploy/health.py +404 -0
- supervaizer/deploy/state.py +210 -0
- supervaizer/deploy/templates/Dockerfile.template +44 -0
- supervaizer/deploy/templates/debug_env.py +69 -0
- supervaizer/deploy/templates/docker-compose.yml.template +37 -0
- supervaizer/deploy/templates/dockerignore.template +66 -0
- supervaizer/deploy/templates/entrypoint.sh +20 -0
- supervaizer/deploy/utils.py +52 -0
- supervaizer/examples/controller_template.py +1 -1
- supervaizer/job.py +18 -5
- supervaizer/job_service.py +6 -5
- supervaizer/parameter.py +13 -1
- supervaizer/protocol/__init__.py +2 -2
- supervaizer/protocol/a2a/routes.py +1 -1
- supervaizer/routes.py +141 -17
- supervaizer/server.py +5 -11
- supervaizer/utils/__init__.py +16 -0
- supervaizer/utils/version_check.py +56 -0
- {supervaizer-0.9.8.dist-info → supervaizer-0.10.1.dist-info}/METADATA +105 -34
- supervaizer-0.10.1.dist-info/RECORD +76 -0
- {supervaizer-0.9.8.dist-info → supervaizer-0.10.1.dist-info}/WHEEL +1 -1
- supervaizer/protocol/acp/__init__.py +0 -21
- supervaizer/protocol/acp/model.py +0 -198
- supervaizer/protocol/acp/routes.py +0 -74
- supervaizer-0.9.8.dist-info/RECORD +0 -52
- {supervaizer-0.9.8.dist-info → supervaizer-0.10.1.dist-info}/entry_points.txt +0 -0
- {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
|