1use std::collections::HashMap;
11
12use serde::{Deserialize, Serialize};
13
14#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
16#[serde(rename_all = "camelCase", default)]
17pub struct ImageSpec {
18 #[serde(skip_serializing_if = "Option::is_none")]
20 pub base: Option<BaseImage>,
21 #[serde(skip_serializing_if = "Vec::is_empty")]
23 pub build_steps: Vec<ImageBuildStep>,
24 #[serde(skip_serializing_if = "HashMap::is_empty")]
26 pub env: HashMap<String, String>,
27 #[serde(skip_serializing_if = "ImageArchitecture::is_unspecified")]
29 pub architecture: ImageArchitecture,
30 #[serde(skip_serializing_if = "String::is_empty")]
32 pub python_version: String,
33}
34
35#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
37pub enum BaseImage {
38 #[default]
40 #[serde(rename = "BASE_IMAGE_UNSPECIFIED")]
41 Unspecified,
42 #[serde(rename = "BASE_IMAGE_DEBIAN")]
44 Debian,
45 #[serde(rename = "BASE_IMAGE_DEVBOX")]
49 Devbox,
50}
51
52#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
54pub enum ImageArchitecture {
55 #[default]
57 #[serde(rename = "IMAGE_ARCHITECTURE_UNSPECIFIED")]
58 Unspecified,
59 #[serde(rename = "IMAGE_ARCHITECTURE_AMD64")]
61 Amd64,
62 #[serde(rename = "IMAGE_ARCHITECTURE_ARM64")]
64 Arm64,
65}
66
67impl ImageArchitecture {
68 #[allow(clippy::trivially_copy_pass_by_ref)]
70 fn is_unspecified(&self) -> bool {
71 matches!(self, ImageArchitecture::Unspecified)
72 }
73}
74
75#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
77#[serde(rename_all = "camelCase")]
78pub enum ImageBuildStep {
79 AptInstall(PackageInstall),
81 PipInstall(PackageInstall),
83 RunCommand(RunCommand),
85 AddLocalFile(AddLocalFile),
87 AddLocalDir(AddLocalDir),
89}
90
91#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
93#[serde(default)]
94pub struct PackageInstall {
95 #[serde(skip_serializing_if = "Vec::is_empty")]
97 pub packages: Vec<String>,
98}
99
100#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
102#[serde(default)]
103pub struct RunCommand {
104 #[serde(skip_serializing_if = "String::is_empty")]
106 pub command: String,
107}
108
109#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
111#[serde(rename_all = "camelCase", default)]
112pub struct AddLocalFile {
113 #[serde(skip_serializing_if = "String::is_empty")]
115 pub content_sha256: String,
116 #[serde(skip_serializing_if = "String::is_empty")]
118 pub remote_path: String,
119 #[serde(skip_serializing_if = "is_zero")]
121 pub mode: u32,
122}
123
124#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
126#[serde(rename_all = "camelCase", default)]
127pub struct AddLocalDir {
128 #[serde(skip_serializing_if = "String::is_empty")]
130 pub remote_path: String,
131 #[serde(skip_serializing_if = "Vec::is_empty")]
133 pub files: Vec<AddLocalDirFile>,
134}
135
136#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
138#[serde(rename_all = "camelCase", default)]
139pub struct AddLocalDirFile {
140 #[serde(skip_serializing_if = "String::is_empty")]
142 pub relative_path: String,
143 #[serde(skip_serializing_if = "String::is_empty")]
145 pub content_sha256: String,
146 #[serde(skip_serializing_if = "is_zero")]
148 pub mode: u32,
149}
150
151#[allow(clippy::trivially_copy_pass_by_ref)]
153fn is_zero(n: &u32) -> bool {
154 *n == 0
155}