|
| 1 | +//! Cloud provider regions and machine types for the deployment wizard |
| 2 | +//! |
| 3 | +//! This module contains static data for cloud provider options, |
| 4 | +//! matching the frontend's cloudProviderData.ts for consistency. |
| 5 | +
|
| 6 | +use crate::platform::api::types::CloudProvider; |
| 7 | + |
| 8 | +/// A cloud region/location option |
| 9 | +#[derive(Debug, Clone)] |
| 10 | +pub struct CloudRegion { |
| 11 | + /// Region ID (e.g., "nbg1", "us-central1") |
| 12 | + pub id: &'static str, |
| 13 | + /// Human-readable name (e.g., "Nuremberg", "Iowa") |
| 14 | + pub name: &'static str, |
| 15 | + /// Geographic location (e.g., "Germany", "US Central") |
| 16 | + pub location: &'static str, |
| 17 | +} |
| 18 | + |
| 19 | +/// A machine/instance type option |
| 20 | +#[derive(Debug, Clone)] |
| 21 | +pub struct MachineType { |
| 22 | + /// Machine type ID (e.g., "cx22", "e2-small") |
| 23 | + pub id: &'static str, |
| 24 | + /// Display name |
| 25 | + pub name: &'static str, |
| 26 | + /// Number of vCPUs (as string to handle fractional) |
| 27 | + pub cpu: &'static str, |
| 28 | + /// Memory amount (e.g., "4 GB") |
| 29 | + pub memory: &'static str, |
| 30 | + /// Optional description (e.g., "Shared Intel", "ARM64") |
| 31 | + pub description: Option<&'static str>, |
| 32 | +} |
| 33 | + |
| 34 | +// ============================================================================= |
| 35 | +// Hetzner Cloud |
| 36 | +// ============================================================================= |
| 37 | + |
| 38 | +/// Hetzner Cloud locations |
| 39 | +pub static HETZNER_LOCATIONS: &[CloudRegion] = &[ |
| 40 | + // Europe |
| 41 | + CloudRegion { id: "nbg1", name: "Nuremberg", location: "Germany" }, |
| 42 | + CloudRegion { id: "fsn1", name: "Falkenstein", location: "Germany" }, |
| 43 | + CloudRegion { id: "hel1", name: "Helsinki", location: "Finland" }, |
| 44 | + // Americas |
| 45 | + CloudRegion { id: "ash", name: "Ashburn", location: "US East" }, |
| 46 | + CloudRegion { id: "hil", name: "Hillsboro", location: "US West" }, |
| 47 | + // Asia Pacific |
| 48 | + CloudRegion { id: "sin", name: "Singapore", location: "Southeast Asia" }, |
| 49 | +]; |
| 50 | + |
| 51 | +/// Hetzner Cloud server types (updated January 2026 naming) |
| 52 | +pub static HETZNER_SERVER_TYPES: &[MachineType] = &[ |
| 53 | + // Shared vCPU - CX Series (Intel/AMD cost-optimized) |
| 54 | + MachineType { id: "cx23", name: "CX23", cpu: "2", memory: "4 GB", description: Some("Shared Intel/AMD") }, |
| 55 | + MachineType { id: "cx33", name: "CX33", cpu: "4", memory: "8 GB", description: Some("Shared Intel/AMD") }, |
| 56 | + MachineType { id: "cx43", name: "CX43", cpu: "8", memory: "16 GB", description: Some("Shared Intel/AMD") }, |
| 57 | + MachineType { id: "cx53", name: "CX53", cpu: "16", memory: "32 GB", description: Some("Shared Intel/AMD") }, |
| 58 | + // Shared vCPU - CPX Series (AMD regular) |
| 59 | + MachineType { id: "cpx22", name: "CPX22", cpu: "2", memory: "4 GB", description: Some("Shared AMD") }, |
| 60 | + MachineType { id: "cpx32", name: "CPX32", cpu: "4", memory: "8 GB", description: Some("Shared AMD") }, |
| 61 | + MachineType { id: "cpx42", name: "CPX42", cpu: "8", memory: "16 GB", description: Some("Shared AMD") }, |
| 62 | + MachineType { id: "cpx52", name: "CPX52", cpu: "12", memory: "24 GB", description: Some("Shared AMD") }, |
| 63 | + MachineType { id: "cpx62", name: "CPX62", cpu: "16", memory: "32 GB", description: Some("Shared AMD") }, |
| 64 | + // Dedicated vCPU - CCX Series (AMD) |
| 65 | + MachineType { id: "ccx13", name: "CCX13", cpu: "2", memory: "8 GB", description: Some("Dedicated AMD") }, |
| 66 | + MachineType { id: "ccx23", name: "CCX23", cpu: "4", memory: "16 GB", description: Some("Dedicated AMD") }, |
| 67 | + MachineType { id: "ccx33", name: "CCX33", cpu: "8", memory: "32 GB", description: Some("Dedicated AMD") }, |
| 68 | + MachineType { id: "ccx43", name: "CCX43", cpu: "16", memory: "64 GB", description: Some("Dedicated AMD") }, |
| 69 | + MachineType { id: "ccx53", name: "CCX53", cpu: "32", memory: "128 GB", description: Some("Dedicated AMD") }, |
| 70 | + MachineType { id: "ccx63", name: "CCX63", cpu: "48", memory: "192 GB", description: Some("Dedicated AMD") }, |
| 71 | + // ARM - CAX Series (Ampere) |
| 72 | + MachineType { id: "cax11", name: "CAX11", cpu: "2", memory: "4 GB", description: Some("ARM64 Ampere") }, |
| 73 | + MachineType { id: "cax21", name: "CAX21", cpu: "4", memory: "8 GB", description: Some("ARM64 Ampere") }, |
| 74 | + MachineType { id: "cax31", name: "CAX31", cpu: "8", memory: "16 GB", description: Some("ARM64 Ampere") }, |
| 75 | + MachineType { id: "cax41", name: "CAX41", cpu: "16", memory: "32 GB", description: Some("ARM64 Ampere") }, |
| 76 | +]; |
| 77 | + |
| 78 | +// ============================================================================= |
| 79 | +// GCP (Google Cloud Platform) |
| 80 | +// ============================================================================= |
| 81 | + |
| 82 | +/// GCP regions |
| 83 | +pub static GCP_REGIONS: &[CloudRegion] = &[ |
| 84 | + // Americas |
| 85 | + CloudRegion { id: "us-central1", name: "Iowa", location: "US Central" }, |
| 86 | + CloudRegion { id: "us-east1", name: "South Carolina", location: "US East" }, |
| 87 | + CloudRegion { id: "us-east4", name: "Virginia", location: "US East" }, |
| 88 | + CloudRegion { id: "us-west1", name: "Oregon", location: "US West" }, |
| 89 | + CloudRegion { id: "us-west2", name: "Los Angeles", location: "US West" }, |
| 90 | + // Europe |
| 91 | + CloudRegion { id: "europe-west1", name: "Belgium", location: "Europe" }, |
| 92 | + CloudRegion { id: "europe-west2", name: "London", location: "UK" }, |
| 93 | + CloudRegion { id: "europe-west3", name: "Frankfurt", location: "Germany" }, |
| 94 | + CloudRegion { id: "europe-west4", name: "Netherlands", location: "Europe" }, |
| 95 | + CloudRegion { id: "europe-north1", name: "Finland", location: "Europe" }, |
| 96 | + // Asia Pacific |
| 97 | + CloudRegion { id: "asia-east1", name: "Taiwan", location: "Asia Pacific" }, |
| 98 | + CloudRegion { id: "asia-northeast1", name: "Tokyo", location: "Japan" }, |
| 99 | + CloudRegion { id: "asia-southeast1", name: "Singapore", location: "Southeast Asia" }, |
| 100 | + CloudRegion { id: "australia-southeast1", name: "Sydney", location: "Australia" }, |
| 101 | +]; |
| 102 | + |
| 103 | +/// GCP machine types (Compute Engine) |
| 104 | +pub static GCP_MACHINE_TYPES: &[MachineType] = &[ |
| 105 | + // E2 Series (Cost-optimized) |
| 106 | + MachineType { id: "e2-micro", name: "e2-micro", cpu: "0.25", memory: "1 GB", description: Some("Shared-core") }, |
| 107 | + MachineType { id: "e2-small", name: "e2-small", cpu: "0.5", memory: "2 GB", description: Some("Shared-core") }, |
| 108 | + MachineType { id: "e2-medium", name: "e2-medium", cpu: "1", memory: "4 GB", description: Some("Shared-core") }, |
| 109 | + MachineType { id: "e2-standard-2", name: "e2-standard-2", cpu: "2", memory: "8 GB", description: None }, |
| 110 | + MachineType { id: "e2-standard-4", name: "e2-standard-4", cpu: "4", memory: "16 GB", description: None }, |
| 111 | + MachineType { id: "e2-standard-8", name: "e2-standard-8", cpu: "8", memory: "32 GB", description: None }, |
| 112 | + // N2 Series (Balanced) |
| 113 | + MachineType { id: "n2-standard-2", name: "n2-standard-2", cpu: "2", memory: "8 GB", description: None }, |
| 114 | + MachineType { id: "n2-standard-4", name: "n2-standard-4", cpu: "4", memory: "16 GB", description: None }, |
| 115 | + MachineType { id: "n2-standard-8", name: "n2-standard-8", cpu: "8", memory: "32 GB", description: None }, |
| 116 | +]; |
| 117 | + |
| 118 | +// ============================================================================= |
| 119 | +// Helper Functions |
| 120 | +// ============================================================================= |
| 121 | + |
| 122 | +/// Get regions for a cloud provider |
| 123 | +pub fn get_regions_for_provider(provider: &CloudProvider) -> &'static [CloudRegion] { |
| 124 | + match provider { |
| 125 | + CloudProvider::Hetzner => HETZNER_LOCATIONS, |
| 126 | + CloudProvider::Gcp => GCP_REGIONS, |
| 127 | + _ => &[], // AWS, Azure not yet supported for Cloud Runner |
| 128 | + } |
| 129 | +} |
| 130 | + |
| 131 | +/// Get machine types for a cloud provider |
| 132 | +pub fn get_machine_types_for_provider(provider: &CloudProvider) -> &'static [MachineType] { |
| 133 | + match provider { |
| 134 | + CloudProvider::Hetzner => HETZNER_SERVER_TYPES, |
| 135 | + CloudProvider::Gcp => GCP_MACHINE_TYPES, |
| 136 | + _ => &[], // AWS, Azure not yet supported for Cloud Runner |
| 137 | + } |
| 138 | +} |
| 139 | + |
| 140 | +/// Get default region for a provider |
| 141 | +pub fn get_default_region(provider: &CloudProvider) -> &'static str { |
| 142 | + match provider { |
| 143 | + CloudProvider::Hetzner => "nbg1", |
| 144 | + CloudProvider::Gcp => "us-central1", |
| 145 | + _ => "", |
| 146 | + } |
| 147 | +} |
| 148 | + |
| 149 | +/// Get default machine type for a provider |
| 150 | +pub fn get_default_machine_type(provider: &CloudProvider) -> &'static str { |
| 151 | + match provider { |
| 152 | + CloudProvider::Hetzner => "cx23", |
| 153 | + CloudProvider::Gcp => "e2-small", |
| 154 | + _ => "", |
| 155 | + } |
| 156 | +} |
| 157 | + |
| 158 | +/// Format region for display: "Nuremberg (Germany)" |
| 159 | +pub fn format_region_display(region: &CloudRegion) -> String { |
| 160 | + format!("{} ({})", region.name, region.location) |
| 161 | +} |
| 162 | + |
| 163 | +/// Format machine type for display: "cx22 · 2 vCPU · 4 GB" |
| 164 | +pub fn format_machine_type_display(machine: &MachineType) -> String { |
| 165 | + let base = format!("{} · {} vCPU · {}", machine.name, machine.cpu, machine.memory); |
| 166 | + if let Some(desc) = machine.description { |
| 167 | + format!("{} · {}", base, desc) |
| 168 | + } else { |
| 169 | + base |
| 170 | + } |
| 171 | +} |
| 172 | + |
| 173 | +#[cfg(test)] |
| 174 | +mod tests { |
| 175 | + use super::*; |
| 176 | + |
| 177 | + #[test] |
| 178 | + fn test_hetzner_locations() { |
| 179 | + assert!(!HETZNER_LOCATIONS.is_empty()); |
| 180 | + assert!(HETZNER_LOCATIONS.iter().any(|r| r.id == "nbg1")); |
| 181 | + } |
| 182 | + |
| 183 | + #[test] |
| 184 | + fn test_hetzner_machine_types() { |
| 185 | + assert!(!HETZNER_SERVER_TYPES.is_empty()); |
| 186 | + assert!(HETZNER_SERVER_TYPES.iter().any(|m| m.id == "cx23")); |
| 187 | + } |
| 188 | + |
| 189 | + #[test] |
| 190 | + fn test_gcp_regions() { |
| 191 | + assert!(!GCP_REGIONS.is_empty()); |
| 192 | + assert!(GCP_REGIONS.iter().any(|r| r.id == "us-central1")); |
| 193 | + } |
| 194 | + |
| 195 | + #[test] |
| 196 | + fn test_gcp_machine_types() { |
| 197 | + assert!(!GCP_MACHINE_TYPES.is_empty()); |
| 198 | + assert!(GCP_MACHINE_TYPES.iter().any(|m| m.id == "e2-small")); |
| 199 | + } |
| 200 | + |
| 201 | + #[test] |
| 202 | + fn test_get_regions_for_provider() { |
| 203 | + let hetzner_regions = get_regions_for_provider(&CloudProvider::Hetzner); |
| 204 | + assert!(!hetzner_regions.is_empty()); |
| 205 | + |
| 206 | + let gcp_regions = get_regions_for_provider(&CloudProvider::Gcp); |
| 207 | + assert!(!gcp_regions.is_empty()); |
| 208 | + } |
| 209 | + |
| 210 | + #[test] |
| 211 | + fn test_format_region_display() { |
| 212 | + let region = &HETZNER_LOCATIONS[0]; |
| 213 | + let display = format_region_display(region); |
| 214 | + assert!(display.contains("Nuremberg")); |
| 215 | + assert!(display.contains("Germany")); |
| 216 | + } |
| 217 | + |
| 218 | + #[test] |
| 219 | + fn test_format_machine_type_display() { |
| 220 | + let machine = &HETZNER_SERVER_TYPES[0]; |
| 221 | + let display = format_machine_type_display(machine); |
| 222 | + assert!(display.contains("CX23")); |
| 223 | + assert!(display.contains("2 vCPU")); |
| 224 | + assert!(display.contains("4 GB")); |
| 225 | + } |
| 226 | +} |
0 commit comments