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 #[serde(skip_serializing_if = "ImageFilesystem::is_unspecified")]
35 pub filesystem: ImageFilesystem,
36}
37
38#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
40pub enum BaseImage {
41 #[serde(rename = "BASE_IMAGE_DEBIAN")]
43 Debian,
44 #[serde(rename = "BASE_IMAGE_DEVBOX")]
48 Devbox,
49}
50
51#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
53pub enum ImageArchitecture {
54 #[default]
56 #[serde(rename = "IMAGE_ARCHITECTURE_UNSPECIFIED")]
57 Unspecified,
58 #[serde(rename = "IMAGE_ARCHITECTURE_AMD64")]
60 Amd64,
61 #[serde(rename = "IMAGE_ARCHITECTURE_ARM64")]
63 Arm64,
64}
65
66impl ImageArchitecture {
67 #[allow(clippy::trivially_copy_pass_by_ref)]
69 fn is_unspecified(&self) -> bool {
70 matches!(self, ImageArchitecture::Unspecified)
71 }
72}
73
74#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
76pub enum ImageFilesystem {
77 #[default]
79 #[serde(rename = "IMAGE_FILESYSTEM_UNSPECIFIED")]
80 Unspecified,
81 #[serde(rename = "IMAGE_FILESYSTEM_EXT4")]
83 Ext4,
84 #[serde(rename = "IMAGE_FILESYSTEM_BTRFS")]
86 Btrfs,
87}
88
89impl ImageFilesystem {
90 #[allow(clippy::trivially_copy_pass_by_ref)]
91 fn is_unspecified(&self) -> bool {
92 matches!(self, ImageFilesystem::Unspecified)
93 }
94}
95
96#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
98#[serde(rename_all = "camelCase")]
99pub enum ImageBuildStep {
100 AptInstall(PackageInstall),
102 PipInstall(PackageInstall),
104 RunCommand(RunCommand),
106 AddLocalFile(AddLocalFile),
108 AddLocalDir(AddLocalDir),
110}
111
112#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
114#[serde(default)]
115pub struct PackageInstall {
116 #[serde(skip_serializing_if = "Vec::is_empty")]
118 pub packages: Vec<String>,
119}
120
121#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
123#[serde(default)]
124pub struct RunCommand {
125 #[serde(skip_serializing_if = "String::is_empty")]
127 pub command: String,
128}
129
130#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
132#[serde(rename_all = "camelCase", default)]
133pub struct AddLocalFile {
134 #[serde(skip_serializing_if = "String::is_empty")]
136 pub content_sha256: String,
137 #[serde(skip_serializing_if = "String::is_empty")]
139 pub remote_path: String,
140 #[serde(skip_serializing_if = "is_zero")]
142 pub mode: u32,
143}
144
145#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
147#[serde(rename_all = "camelCase", default)]
148pub struct AddLocalDir {
149 #[serde(skip_serializing_if = "String::is_empty")]
151 pub remote_path: String,
152 #[serde(skip_serializing_if = "Vec::is_empty")]
154 pub files: Vec<AddLocalDirFile>,
155}
156
157#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
159#[serde(rename_all = "camelCase", default)]
160pub struct AddLocalDirFile {
161 #[serde(skip_serializing_if = "String::is_empty")]
163 pub relative_path: String,
164 #[serde(skip_serializing_if = "String::is_empty")]
166 pub content_sha256: String,
167 #[serde(skip_serializing_if = "is_zero")]
169 pub mode: u32,
170}
171
172#[allow(clippy::trivially_copy_pass_by_ref)]
174fn is_zero(n: &u32) -> bool {
175 *n == 0
176}