geronimo.deploy
Geronimo Deploy Module.
This module provides the necessary tooling to deploy infrastructure and applications to cloud providers using Infrastructure as Code (IaC). It primarily integrates with Pulumi's Automation API to programmatically manage cloud resources.
It allows you to:
- Define infrastructure resources (S3 buckets, EC2 instances, SageMaker endpoints)
- Deploy entire stacks with a single Python command
- Manage deployment state and targeted environments (dev/stage/prod)
- Destroy resources when no longer needed
Note: Pulumi is an optional dependency. Install it with pip install geronimo[pulumi].
1"""Geronimo Deploy Module. 2 3This module provides the necessary tooling to deploy infrastructure and applications 4to cloud providers using Infrastructure as Code (IaC). It primarily integrates with 5Pulumi's Automation API to programmatically manage cloud resources. 6 7It allows you to: 8- Define infrastructure resources (S3 buckets, EC2 instances, SageMaker endpoints) 9- Deploy entire stacks with a single Python command 10- Manage deployment state and targeted environments (dev/stage/prod) 11- Destroy resources when no longer needed 12 13Note: Pulumi is an optional dependency. Install it with `pip install geronimo[pulumi]`. 14""" 15 16from geronimo.deploy.config import DeploymentConfig 17from geronimo.deploy.targets import deploy, destroy, get_available_targets 18from geronimo.deploy.protocol import DeploymentTarget, DeploymentInfo, DeploymentStatus 19 20__all__ = [ 21 "DeploymentConfig", 22 "deploy", 23 "destroy", 24 "get_available_targets", 25 "DeploymentTarget", 26 "DeploymentInfo", 27 "DeploymentStatus", 28] 29 30__docformat__ = "google"
33class DeploymentConfig(BaseModel): 34 """Complete deployment configuration. 35 36 Example: 37 config = DeploymentConfig( 38 project="iris-classifier", 39 target="aws", 40 region="us-west-2", 41 ) 42 """ 43 44 project: str 45 version: str = "1.0.0" 46 target: Literal["aws", "gcp", "azure"] = "aws" 47 region: str = "us-east-1" 48 49 # Component configs 50 artifacts: ArtifactStorageConfig = ArtifactStorageConfig() 51 serving: Optional[ServingConfig] = None 52 batch: Optional[BatchConfig] = None 53 54 # Pulumi settings 55 stack_name: str = "dev"
Complete deployment configuration.
Example:
config = DeploymentConfig( project="iris-classifier", target="aws", region="us-west-2", )
37def deploy(config: DeploymentConfig, component: str | None = None) -> dict: 38 """Deploy infrastructure using Pulumi. 39 40 Args: 41 config: Deployment configuration 42 component: Optional component to deploy (artifacts, serving, batch) 43 If None, deploys all configured components 44 45 Returns: 46 Dict with deployment outputs (URLs, resource IDs, etc.) 47 48 Raises: 49 PulumiNotInstalledError: If Pulumi is not installed 50 """ 51 if not _check_pulumi_available(): 52 raise PulumiNotInstalledError() 53 54 # Import Pulumi providers dynamically 55 if config.target == "aws": 56 from geronimo.deploy.providers.aws import deploy_aws 57 return deploy_aws(config, component) 58 elif config.target == "gcp": 59 from geronimo.deploy.providers.gcp import deploy_gcp 60 return deploy_gcp(config, component) 61 elif config.target == "azure": 62 from geronimo.deploy.providers.azure import deploy_azure 63 return deploy_azure(config, component) 64 elif config.target == "gdc": 65 from geronimo.deploy_cloud import GeronimoCloudTarget 66 target = GeronimoCloudTarget(config) 67 return target.deploy(component) 68 else: 69 raise ValueError(f"Unknown target: {config.target}")
Deploy infrastructure using Pulumi.
Arguments:
- config: Deployment configuration
- component: Optional component to deploy (artifacts, serving, batch) If None, deploys all configured components
Returns:
Dict with deployment outputs (URLs, resource IDs, etc.)
Raises:
- PulumiNotInstalledError: If Pulumi is not installed
72def destroy(config: DeploymentConfig) -> dict: 73 """Destroy deployed infrastructure. 74 75 Args: 76 config: Deployment configuration 77 78 Returns: 79 Dict with destruction summary 80 81 Raises: 82 PulumiNotInstalledError: If Pulumi is not installed (unless target is cloud) 83 """ 84 if config.target == "gdc": 85 from geronimo.deploy_cloud import GeronimoCloudTarget 86 target = GeronimoCloudTarget(config) 87 return target.destroy() 88 89 if not _check_pulumi_available(): 90 raise PulumiNotInstalledError() 91 92 if config.target == "aws": 93 from geronimo.deploy.providers.aws import destroy_aws 94 return destroy_aws(config) 95 elif config.target == "gcp": 96 from geronimo.deploy.providers.gcp import destroy_gcp 97 return destroy_gcp(config) 98 elif config.target == "azure": 99 from geronimo.deploy.providers.azure import destroy_azure 100 return destroy_azure(config) 101 else: 102 raise ValueError(f"Unknown target: {config.target}")
Destroy deployed infrastructure.
Arguments:
- config: Deployment configuration
Returns:
Dict with destruction summary
Raises:
- PulumiNotInstalledError: If Pulumi is not installed (unless target is cloud)
28def get_available_targets() -> list[str]: 29 """Get list of available deployment targets. 30 31 Returns: 32 List of target names (aws, gcp, azure) 33 """ 34 return ["aws", "gcp", "azure", "gdc"]
Get list of available deployment targets.
Returns:
List of target names (aws, gcp, azure)
30@runtime_checkable 31class DeploymentTarget(Protocol): 32 """Protocol for custom deployment targets. 33 34 Implement this protocol to deploy Geronimo models to your own 35 infrastructure (internal K8s, custom ECS, on-prem servers, etc.). 36 37 Example: 38 class InternalK8sTarget(DeploymentTarget): 39 def __init__(self, cluster: str, namespace: str): 40 self.cluster = cluster 41 self.namespace = namespace 42 43 def deploy(self, config, artifacts) -> DeploymentInfo: 44 # Use Helm, kubectl, or K8s API 45 return DeploymentInfo( 46 deployment_id=f"{self.namespace}/{config.project}", 47 status=DeploymentStatus.RUNNING, 48 endpoint_url=f"http://{config.project}.{self.namespace}.svc", 49 ) 50 51 def status(self, deployment_id) -> DeploymentInfo: 52 # Query K8s for pod status 53 ... 54 55 def teardown(self, deployment_id) -> None: 56 # Delete K8s resources 57 ... 58 59 Usage in geronimo.yaml: 60 deployment: 61 target: custom 62 custom_target: 63 class: my_company.deploy.InternalK8sTarget 64 config: 65 cluster: production-eks 66 namespace: ml-models 67 """ 68 69 def deploy(self, config: Any, artifacts: dict[str, str]) -> DeploymentInfo: 70 """Deploy a model. 71 72 Args: 73 config: DeploymentConfig or GeronimoConfig 74 artifacts: Dict of artifact name -> URI 75 76 Returns: 77 DeploymentInfo with endpoint URL and status 78 """ 79 ... 80 81 def status(self, deployment_id: str) -> DeploymentInfo: 82 """Check deployment status. 83 84 Args: 85 deployment_id: ID returned from deploy() 86 87 Returns: 88 Current deployment status 89 """ 90 ... 91 92 def teardown(self, deployment_id: str) -> None: 93 """Remove a deployment. 94 95 Args: 96 deployment_id: ID of deployment to remove 97 """ 98 ... 99 100 def logs(self, deployment_id: str, lines: int = 100) -> list[str]: 101 """Get deployment logs. 102 103 Args: 104 deployment_id: ID of deployment 105 lines: Number of log lines to retrieve 106 107 Returns: 108 List of log lines 109 """ 110 ...
Protocol for custom deployment targets.
Implement this protocol to deploy Geronimo models to your own infrastructure (internal K8s, custom ECS, on-prem servers, etc.).
Example:
class InternalK8sTarget(DeploymentTarget): def __init__(self, cluster: str, namespace: str): self.cluster = cluster self.namespace = namespace
def deploy(self, config, artifacts) -> DeploymentInfo: # Use Helm, kubectl, or K8s API return DeploymentInfo( deployment_id=f"{self.namespace}/{config.project}", status=DeploymentStatus.RUNNING, endpoint_url=f"http://{config.project}.{self.namespace}.svc", ) def status(self, deployment_id) -> DeploymentInfo: # Query K8s for pod status ... def teardown(self, deployment_id) -> None: # Delete K8s resources ...
Usage in geronimo.yaml: deployment: target: custom custom_target: class: my_company.deploy.InternalK8sTarget config: cluster: production-eks namespace: ml-models
1953def _no_init_or_replace_init(self, *args, **kwargs): 1954 cls = type(self) 1955 1956 if cls._is_protocol: 1957 raise TypeError('Protocols cannot be instantiated') 1958 1959 # Already using a custom `__init__`. No need to calculate correct 1960 # `__init__` to call. This can lead to RecursionError. See bpo-45121. 1961 if cls.__init__ is not _no_init_or_replace_init: 1962 return 1963 1964 # Initially, `__init__` of a protocol subclass is set to `_no_init_or_replace_init`. 1965 # The first instantiation of the subclass will call `_no_init_or_replace_init` which 1966 # searches for a proper new `__init__` in the MRO. The new `__init__` 1967 # replaces the subclass' old `__init__` (ie `_no_init_or_replace_init`). Subsequent 1968 # instantiation of the protocol subclass will thus use the new 1969 # `__init__` and no longer call `_no_init_or_replace_init`. 1970 for base in cls.__mro__: 1971 init = base.__dict__.get('__init__', _no_init_or_replace_init) 1972 if init is not _no_init_or_replace_init: 1973 cls.__init__ = init 1974 break 1975 else: 1976 # should not happen 1977 cls.__init__ = object.__init__ 1978 1979 cls.__init__(self, *args, **kwargs)
69 def deploy(self, config: Any, artifacts: dict[str, str]) -> DeploymentInfo: 70 """Deploy a model. 71 72 Args: 73 config: DeploymentConfig or GeronimoConfig 74 artifacts: Dict of artifact name -> URI 75 76 Returns: 77 DeploymentInfo with endpoint URL and status 78 """ 79 ...
Deploy a model.
Arguments:
- config: DeploymentConfig or GeronimoConfig
- artifacts: Dict of artifact name -> URI
Returns:
DeploymentInfo with endpoint URL and status
81 def status(self, deployment_id: str) -> DeploymentInfo: 82 """Check deployment status. 83 84 Args: 85 deployment_id: ID returned from deploy() 86 87 Returns: 88 Current deployment status 89 """ 90 ...
Check deployment status.
Arguments:
- deployment_id: ID returned from deploy()
Returns:
Current deployment status
92 def teardown(self, deployment_id: str) -> None: 93 """Remove a deployment. 94 95 Args: 96 deployment_id: ID of deployment to remove 97 """ 98 ...
Remove a deployment.
Arguments:
- deployment_id: ID of deployment to remove
100 def logs(self, deployment_id: str, lines: int = 100) -> list[str]: 101 """Get deployment logs. 102 103 Args: 104 deployment_id: ID of deployment 105 lines: Number of log lines to retrieve 106 107 Returns: 108 List of log lines 109 """ 110 ...
Get deployment logs.
Arguments:
- deployment_id: ID of deployment
- lines: Number of log lines to retrieve
Returns:
List of log lines
20class DeploymentInfo(BaseModel): 21 """Information about a deployment.""" 22 23 deployment_id: str 24 status: DeploymentStatus 25 endpoint_url: str | None = None 26 message: str | None = None 27 resources: dict[str, Any] = {}
Information about a deployment.
9class DeploymentStatus(str, Enum): 10 """Status of a deployment.""" 11 12 PENDING = "pending" 13 DEPLOYING = "deploying" 14 RUNNING = "running" 15 FAILED = "failed" 16 STOPPING = "stopping" 17 STOPPED = "stopped"
Status of a deployment.