use crate::core::error::{Error, Result};
use crate::core::resources::ResourceSpec;
use crate::deployment::ssh::{
ContainerRuntime, DeploymentConfig, SshConnection, SshDeploymentClient,
};
use crate::infra::traits::BlueprintDeploymentResult;
use crate::infra::types::ProvisionedInstance;
use blueprint_core::{info, warn};
use blueprint_std::collections::HashMap;
pub struct SharedSshDeployment;
impl SharedSshDeployment {
pub async fn deploy_to_instance(
instance: &ProvisionedInstance,
blueprint_image: &str,
resource_spec: &ResourceSpec,
env_vars: HashMap<String, String>,
ssh_config: SshDeploymentConfig,
) -> Result<BlueprintDeploymentResult> {
let public_ip = instance
.public_ip
.as_ref()
.ok_or_else(|| Error::Other("Instance has no public IP".into()))?;
let connection = SshConnection {
host: public_ip.clone(),
user: ssh_config.username,
key_path: ssh_config.key_path.map(|p| p.into()),
port: 22,
password: None,
jump_host: None,
};
let deployment_config = DeploymentConfig {
name: format!("blueprint-{}", uuid::Uuid::new_v4()),
namespace: ssh_config.namespace,
restart_policy: crate::deployment::ssh::RestartPolicy::OnFailure,
health_check: None,
};
let ssh_client =
SshDeploymentClient::new(connection, ContainerRuntime::Docker, deployment_config)
.await
.map_err(|e| Error::Other(format!("Failed to establish SSH connection: {e}")))?;
let deployment = ssh_client
.deploy_blueprint(blueprint_image, resource_spec, env_vars)
.await
.map_err(|e| Error::Other(format!("Blueprint deployment failed: {e}")))?;
let mut port_mappings = HashMap::new();
for (internal_port_str, external_port_str) in &deployment.ports {
if let (Ok(internal), Ok(external)) = (
internal_port_str.trim_end_matches("/tcp").parse::<u16>(),
external_port_str.parse::<u16>(),
) {
port_mappings.insert(internal, external);
}
}
if !port_mappings.contains_key(&9615) {
warn!(
"QoS metrics port 9615 not exposed in {} deployment",
ssh_config.provider_name
);
}
let mut metadata = HashMap::new();
metadata.insert("provider".to_string(), ssh_config.provider_name.clone());
metadata.insert("container_id".to_string(), deployment.container_id.clone());
metadata.insert("ssh_host".to_string(), deployment.host.clone());
for (key, value) in ssh_config.additional_metadata {
metadata.insert(key, value);
}
info!(
"Successfully deployed blueprint {} to {} instance {}",
deployment.container_id, ssh_config.provider_name, instance.id
);
Ok(BlueprintDeploymentResult {
instance: instance.clone(),
blueprint_id: deployment.container_id,
port_mappings,
metadata,
})
}
}
pub struct SshDeploymentConfig {
pub username: String,
pub key_path: Option<String>,
pub namespace: String,
pub provider_name: String,
pub additional_metadata: HashMap<String, String>,
}
impl SshDeploymentConfig {
pub fn aws() -> Self {
Self {
username: "ec2-user".to_string(),
key_path: std::env::var("AWS_SSH_KEY_PATH").ok(),
namespace: "blueprint-aws".to_string(),
provider_name: "aws".to_string(),
additional_metadata: {
let mut metadata = HashMap::new();
metadata.insert("security_hardened".to_string(), "true".to_string());
metadata
},
}
}
pub fn gcp(project_id: &str) -> Self {
Self {
username: "ubuntu".to_string(),
key_path: std::env::var("GCP_SSH_KEY_PATH").ok(),
namespace: "blueprint-gcp".to_string(),
provider_name: "gcp".to_string(),
additional_metadata: {
let mut metadata = HashMap::new();
metadata.insert("project_id".to_string(), project_id.to_string());
metadata.insert("security_hardened".to_string(), "true".to_string());
metadata
},
}
}
pub fn azure() -> Self {
Self {
username: "azureuser".to_string(),
key_path: std::env::var("AZURE_SSH_KEY_PATH").ok(),
namespace: "blueprint-azure".to_string(),
provider_name: "azure-vm".to_string(),
additional_metadata: HashMap::new(),
}
}
pub fn digitalocean() -> Self {
Self {
username: "root".to_string(),
key_path: std::env::var("DO_SSH_KEY_PATH").ok(),
namespace: "blueprint-do".to_string(),
provider_name: "digitalocean-droplet".to_string(),
additional_metadata: HashMap::new(),
}
}
pub fn vultr() -> Self {
Self {
username: "root".to_string(),
key_path: std::env::var("VULTR_SSH_KEY_PATH").ok(),
namespace: "blueprint-vultr".to_string(),
provider_name: "vultr-instance".to_string(),
additional_metadata: HashMap::new(),
}
}
pub fn lambda_labs() -> Self {
Self {
username: "ubuntu".to_string(),
key_path: std::env::var("LAMBDA_LABS_SSH_KEY_PATH").ok(),
namespace: "blueprint-lambda".to_string(),
provider_name: "lambda-labs".to_string(),
additional_metadata: HashMap::new(),
}
}
pub fn runpod() -> Self {
Self {
username: "root".to_string(),
key_path: std::env::var("RUNPOD_SSH_KEY_PATH").ok(),
namespace: "blueprint-runpod".to_string(),
provider_name: "runpod".to_string(),
additional_metadata: HashMap::new(),
}
}
pub fn vast_ai() -> Self {
Self {
username: "root".to_string(),
key_path: std::env::var("VAST_AI_SSH_KEY_PATH").ok(),
namespace: "blueprint-vastai".to_string(),
provider_name: "vast-ai".to_string(),
additional_metadata: HashMap::new(),
}
}
pub fn coreweave() -> Self {
Self {
username: "coreweave".to_string(),
key_path: std::env::var("COREWEAVE_SSH_KEY_PATH").ok(),
namespace: "blueprint-coreweave".to_string(),
provider_name: "coreweave".to_string(),
additional_metadata: HashMap::new(),
}
}
pub fn paperspace() -> Self {
Self {
username: "paperspace".to_string(),
key_path: std::env::var("PAPERSPACE_SSH_KEY_PATH").ok(),
namespace: "blueprint-paperspace".to_string(),
provider_name: "paperspace".to_string(),
additional_metadata: HashMap::new(),
}
}
pub fn fluidstack() -> Self {
Self {
username: "ubuntu".to_string(),
key_path: std::env::var("FLUIDSTACK_SSH_KEY_PATH").ok(),
namespace: "blueprint-fluidstack".to_string(),
provider_name: "fluidstack".to_string(),
additional_metadata: HashMap::new(),
}
}
pub fn tensordock() -> Self {
Self {
username: "user".to_string(),
key_path: std::env::var("TENSORDOCK_SSH_KEY_PATH").ok(),
namespace: "blueprint-tensordock".to_string(),
provider_name: "tensordock".to_string(),
additional_metadata: HashMap::new(),
}
}
pub fn akash() -> Self {
Self {
username: "root".to_string(),
key_path: std::env::var("AKASH_SSH_KEY_PATH").ok(),
namespace: "blueprint-akash".to_string(),
provider_name: "akash".to_string(),
additional_metadata: HashMap::new(),
}
}
pub fn io_net() -> Self {
Self {
username: "root".to_string(),
key_path: std::env::var("IO_NET_SSH_KEY_PATH").ok(),
namespace: "blueprint-ionet".to_string(),
provider_name: "io-net".to_string(),
additional_metadata: HashMap::new(),
}
}
pub fn prime_intellect() -> Self {
Self {
username: "ubuntu".to_string(),
key_path: std::env::var("PRIME_INTELLECT_SSH_KEY_PATH").ok(),
namespace: "blueprint-prime".to_string(),
provider_name: "prime-intellect".to_string(),
additional_metadata: HashMap::new(),
}
}
pub fn render() -> Self {
Self {
username: "render".to_string(),
key_path: std::env::var("RENDER_SSH_KEY_PATH").ok(),
namespace: "blueprint-render".to_string(),
provider_name: "render".to_string(),
additional_metadata: HashMap::new(),
}
}
pub fn bittensor_lium() -> Self {
Self {
username: "root".to_string(),
key_path: std::env::var("LIUM_SSH_KEY_PATH").ok(),
namespace: "blueprint-lium".to_string(),
provider_name: "bittensor-lium".to_string(),
additional_metadata: HashMap::new(),
}
}
}