1use serde::{Deserialize, Serialize};
7#[cfg(feature = "openapi")]
8use utoipa::ToSchema;
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq)]
12pub enum CargoBuildStrategy {
13 Native,
15 Zigbuild,
17 Xwin,
19}
20
21impl CargoBuildStrategy {
22 pub fn cargo_subcommand(&self) -> &'static str {
24 match self {
25 Self::Native => "build",
26 Self::Zigbuild => "zigbuild",
27 Self::Xwin => "xwin",
28 }
29 }
30
31 pub fn cargo_args(&self) -> Vec<&'static str> {
33 match self {
34 Self::Native => vec!["build"],
35 Self::Zigbuild => vec!["zigbuild"],
36 Self::Xwin => vec!["xwin", "build"],
37 }
38 }
39
40 pub fn display_name(&self) -> &'static str {
42 match self {
43 Self::Native => "cargo build",
44 Self::Zigbuild => "cargo zigbuild",
45 Self::Xwin => "cargo xwin build",
46 }
47 }
48
49 pub fn install_package(&self) -> Option<&'static str> {
51 match self {
52 Self::Native => None,
53 Self::Zigbuild => Some("cargo-zigbuild"),
54 Self::Xwin => Some("cargo-xwin"),
55 }
56 }
57}
58
59#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
61#[cfg_attr(feature = "openapi", derive(ToSchema))]
62#[serde(rename_all = "kebab-case")]
63pub enum SourceBinaryType {
64 Cli,
66 Terraform,
68 Operator,
70}
71
72impl SourceBinaryType {
73 pub fn binary_name(&self) -> &'static str {
75 match self {
76 SourceBinaryType::Cli => "alien-deploy",
77 SourceBinaryType::Terraform => "alien-terraform",
78 SourceBinaryType::Operator => "alien-operator",
79 }
80 }
81}
82
83impl std::fmt::Display for SourceBinaryType {
84 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
85 match self {
86 SourceBinaryType::Cli => write!(f, "cli"),
87 SourceBinaryType::Terraform => write!(f, "terraform"),
88 SourceBinaryType::Operator => write!(f, "operator"),
89 }
90 }
91}
92
93#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
98#[cfg_attr(feature = "openapi", derive(ToSchema))]
99#[serde(rename_all = "kebab-case")]
100pub enum BinaryTarget {
101 WindowsX64,
103 LinuxX64,
105 LinuxArm64,
107 DarwinArm64,
109}
110
111impl BinaryTarget {
112 pub const ALL: &'static [BinaryTarget] = &[
114 BinaryTarget::WindowsX64,
115 BinaryTarget::LinuxX64,
116 BinaryTarget::LinuxArm64,
117 BinaryTarget::DarwinArm64,
118 ];
119
120 pub const LINUX: &'static [BinaryTarget] = &[BinaryTarget::LinuxX64, BinaryTarget::LinuxArm64];
122
123 pub fn rust_target_triple(&self) -> &'static str {
125 match self {
126 Self::WindowsX64 => "x86_64-pc-windows-msvc",
127 Self::LinuxX64 => "x86_64-unknown-linux-musl",
128 Self::LinuxArm64 => "aarch64-unknown-linux-musl",
129 Self::DarwinArm64 => "aarch64-apple-darwin",
130 }
131 }
132
133 pub fn cargo_build_strategy(&self) -> CargoBuildStrategy {
140 match self {
141 Self::LinuxX64 | Self::LinuxArm64 => CargoBuildStrategy::Zigbuild,
142 Self::WindowsX64 => {
143 if cfg!(target_os = "windows") {
144 CargoBuildStrategy::Native
145 } else {
146 CargoBuildStrategy::Xwin
147 }
148 }
149 Self::DarwinArm64 => CargoBuildStrategy::Native,
150 }
151 }
152
153 pub fn binary_extension(&self) -> &'static str {
155 match self {
156 Self::WindowsX64 => ".exe",
157 _ => "",
158 }
159 }
160
161 pub fn runtime_platform_id(&self) -> &'static str {
163 match self {
164 Self::WindowsX64 => "windows-x64",
165 Self::LinuxX64 => "linux-x64",
166 Self::LinuxArm64 => "linux-aarch64",
167 Self::DarwinArm64 => "darwin-aarch64",
168 }
169 }
170
171 pub fn from_runtime_platform_id(id: &str) -> Option<Self> {
174 match id {
175 "windows-x64" => Some(Self::WindowsX64),
176 "linux-x64" => Some(Self::LinuxX64),
177 "linux-aarch64" => Some(Self::LinuxArm64),
178 "darwin-aarch64" => Some(Self::DarwinArm64),
179 _ => None,
180 }
181 }
182
183 pub fn oci_os(&self) -> &'static str {
185 match self {
186 Self::WindowsX64 => "windows",
187 Self::LinuxX64 | Self::LinuxArm64 => "linux",
188 Self::DarwinArm64 => "darwin",
189 }
190 }
191
192 pub fn oci_arch(&self) -> &'static str {
194 match self {
195 Self::WindowsX64 | Self::LinuxX64 => "amd64",
196 Self::LinuxArm64 | Self::DarwinArm64 => "arm64",
197 }
198 }
199
200 pub fn bun_target(&self) -> &'static str {
202 match self {
203 Self::WindowsX64 => "bun-windows-x64",
204 Self::LinuxX64 => "bun-linux-x64",
205 Self::LinuxArm64 => "bun-linux-arm64",
206 Self::DarwinArm64 => "bun-darwin-arm64",
207 }
208 }
209
210 pub fn terraform_key(&self) -> &'static str {
212 match self {
213 BinaryTarget::LinuxX64 => "linux_amd64",
214 BinaryTarget::LinuxArm64 => "linux_arm64",
215 BinaryTarget::DarwinArm64 => "darwin_arm64",
216 BinaryTarget::WindowsX64 => "windows_amd64",
217 }
218 }
219
220 pub fn terraform_os(&self) -> &'static str {
222 match self {
223 BinaryTarget::LinuxX64 | BinaryTarget::LinuxArm64 => "linux",
224 BinaryTarget::DarwinArm64 => "darwin",
225 BinaryTarget::WindowsX64 => "windows",
226 }
227 }
228
229 pub fn terraform_arch(&self) -> &'static str {
231 match self {
232 BinaryTarget::LinuxX64 | BinaryTarget::WindowsX64 => "amd64",
233 BinaryTarget::LinuxArm64 | BinaryTarget::DarwinArm64 => "arm64",
234 }
235 }
236
237 pub fn is_darwin(&self) -> bool {
239 matches!(self, Self::DarwinArm64)
240 }
241
242 pub fn is_windows(&self) -> bool {
244 matches!(self, Self::WindowsX64)
245 }
246
247 pub fn linux_container_target() -> Self {
251 match Self::current_os() {
252 Self::DarwinArm64 | Self::LinuxArm64 => Self::LinuxArm64,
253 Self::LinuxX64 | Self::WindowsX64 => Self::LinuxX64,
254 }
255 }
256
257 pub fn all() -> Vec<Self> {
259 Self::ALL.to_vec()
260 }
261
262 pub fn defaults_for_platform(platform: crate::Platform) -> Vec<Self> {
264 match platform {
265 crate::Platform::Aws => vec![Self::LinuxArm64],
266 crate::Platform::Gcp => vec![Self::LinuxX64],
267 crate::Platform::Azure => vec![Self::LinuxX64],
268 crate::Platform::Kubernetes => Self::LINUX.to_vec(),
269 crate::Platform::Machines => Self::LINUX.to_vec(),
270 crate::Platform::Local => vec![Self::current_os()],
271 crate::Platform::Test => vec![Self::LinuxX64],
272 }
273 }
274
275 pub fn current_os() -> Self {
277 #[cfg(all(target_os = "windows", target_arch = "x86_64"))]
278 return Self::WindowsX64;
279
280 #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
281 return Self::LinuxX64;
282
283 #[cfg(all(target_os = "linux", target_arch = "aarch64"))]
284 return Self::LinuxArm64;
285
286 #[cfg(all(target_os = "macos", target_arch = "aarch64"))]
287 return Self::DarwinArm64;
288
289 #[cfg(not(any(
290 all(target_os = "windows", target_arch = "x86_64"),
291 all(target_os = "linux", target_arch = "x86_64"),
292 all(target_os = "linux", target_arch = "aarch64"),
293 all(target_os = "macos", target_arch = "aarch64")
294 )))]
295 {
296 Self::LinuxX64
297 }
298 }
299}
300
301impl std::fmt::Display for BinaryTarget {
302 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
303 match self {
304 BinaryTarget::WindowsX64 => write!(f, "windows-x64"),
305 BinaryTarget::LinuxX64 => write!(f, "linux-x64"),
306 BinaryTarget::LinuxArm64 => write!(f, "linux-arm64"),
307 BinaryTarget::DarwinArm64 => write!(f, "darwin-arm64"),
308 }
309 }
310}
311
312impl std::str::FromStr for BinaryTarget {
313 type Err = String;
314
315 fn from_str(s: &str) -> Result<Self, Self::Err> {
316 match s {
317 "windows-x64" => Ok(BinaryTarget::WindowsX64),
318 "linux-x64" => Ok(BinaryTarget::LinuxX64),
319 "linux-arm64" => Ok(BinaryTarget::LinuxArm64),
320 "darwin-arm64" => Ok(BinaryTarget::DarwinArm64),
321 _ => Err(format!("Unknown binary target: {}", s)),
322 }
323 }
324}
325
326#[cfg(test)]
327mod tests {
328 use super::BinaryTarget;
329 use crate::Platform;
330
331 #[test]
332 fn local_platform_defaults_to_current_host_target() {
333 assert_eq!(
334 BinaryTarget::defaults_for_platform(Platform::Local),
335 vec![BinaryTarget::current_os()]
336 );
337 }
338
339 #[test]
340 fn runtime_platform_id_round_trips() {
341 for target in BinaryTarget::ALL {
342 assert_eq!(
343 BinaryTarget::from_runtime_platform_id(target.runtime_platform_id()),
344 Some(*target),
345 "round-trip failed for {target}"
346 );
347 }
348 assert_eq!(
350 BinaryTarget::from_runtime_platform_id("linux-aarch64"),
351 Some(BinaryTarget::LinuxArm64)
352 );
353 assert_eq!(BinaryTarget::from_runtime_platform_id("linux-arm64"), None);
354 assert_eq!(BinaryTarget::from_runtime_platform_id("nonsense"), None);
355 }
356
357 #[test]
358 fn cloud_platform_defaults_remain_stable() {
359 assert_eq!(
360 BinaryTarget::defaults_for_platform(Platform::Aws),
361 vec![BinaryTarget::LinuxArm64]
362 );
363 assert_eq!(
364 BinaryTarget::defaults_for_platform(Platform::Gcp),
365 vec![BinaryTarget::LinuxX64]
366 );
367 assert_eq!(
368 BinaryTarget::defaults_for_platform(Platform::Azure),
369 vec![BinaryTarget::LinuxX64]
370 );
371 assert_eq!(
372 BinaryTarget::defaults_for_platform(Platform::Kubernetes),
373 vec![BinaryTarget::LinuxX64, BinaryTarget::LinuxArm64]
374 );
375 }
376}