microsandbox_core/config/microsandbox/
builder.rs

1use std::collections::HashMap;
2
3use microsandbox_utils::DEFAULT_SHELL;
4use semver::Version;
5use typed_path::Utf8UnixPathBuf;
6
7use crate::{
8    config::{EnvPair, PathPair, PortPair, ReferenceOrPath},
9    MicrosandboxResult,
10};
11
12use super::{Build, Group, Meta, Microsandbox, Module, NetworkScope, Sandbox, SandboxGroup};
13
14//--------------------------------------------------------------------------------------------------
15// Types
16//--------------------------------------------------------------------------------------------------
17
18/// Builder for Microsandbox configuration
19///
20/// ### Optional fields:
21/// - `meta`: The metadata for the configuration
22/// - `modules`: The modules to import
23/// - `builds`: The builds to run
24/// - `sandboxes`: The sandboxes to run
25/// - `groups`: The groups to run the sandboxes in
26#[derive(Default)]
27pub struct MicrosandboxBuilder {
28    meta: Option<Meta>,
29    modules: HashMap<String, Module>,
30    builds: HashMap<String, Build>,
31    sandboxes: HashMap<String, Sandbox>,
32    groups: HashMap<String, Group>,
33}
34
35/// Builder for Sandbox configuration
36///
37/// ### Required fields:
38/// - `name`: The name of the sandbox
39/// - `image`: The image to use
40///
41/// ### Optional fields:
42/// - `version`: The version of the sandbox
43/// - `meta`: The metadata for the sandbox
44/// - `memory`: The maximum amount of memory allowed for the sandbox
45/// - `cpus`: The maximum number of CPUs allowed for the sandbox
46/// - `volumes`: The volumes to mount
47/// - `ports`: The ports to expose
48/// - `envs`: The environment variables to use
49/// - `env_file`: The environment file to use
50/// - `groups`: The groups to run the sandbox in
51/// - `depends_on`: The sandboxes to depend on
52/// - `workdir`: The working directory to use
53/// - `shell`: The shell to use
54/// - `scripts`: The scripts available in the sandbox
55/// - `imports`: The files to import
56/// - `exports`: The files to export
57/// - `scope`: The network scope for the sandbox
58/// - `proxy`: The proxy to use
59pub struct SandboxBuilder<I> {
60    version: Option<Version>,
61    meta: Option<Meta>,
62    image: I,
63    memory: Option<u32>,
64    cpus: Option<u8>,
65    volumes: Vec<PathPair>,
66    ports: Vec<PortPair>,
67    envs: Vec<EnvPair>,
68    env_file: Option<Utf8UnixPathBuf>,
69    groups: HashMap<String, SandboxGroup>,
70    depends_on: Vec<String>,
71    workdir: Option<Utf8UnixPathBuf>,
72    shell: Option<String>,
73    scripts: HashMap<String, String>,
74    command: Vec<String>,
75    imports: HashMap<String, Utf8UnixPathBuf>,
76    exports: HashMap<String, Utf8UnixPathBuf>,
77    scope: NetworkScope,
78}
79
80//--------------------------------------------------------------------------------------------------
81// Methods
82//--------------------------------------------------------------------------------------------------
83
84impl MicrosandboxBuilder {
85    /// Sets the metadata for the configuration
86    pub fn meta(mut self, meta: Meta) -> Self {
87        self.meta = Some(meta);
88        self
89    }
90
91    /// Sets the modules to import
92    pub fn modules(mut self, modules: impl IntoIterator<Item = (String, Module)>) -> Self {
93        self.modules = modules.into_iter().collect();
94        self
95    }
96
97    /// Sets the builds to run
98    pub fn builds(mut self, builds: impl IntoIterator<Item = (String, Build)>) -> Self {
99        self.builds = builds.into_iter().collect();
100        self
101    }
102
103    /// Sets the sandboxes to run
104    pub fn sandboxes(mut self, sandboxes: impl IntoIterator<Item = (String, Sandbox)>) -> Self {
105        self.sandboxes = sandboxes.into_iter().collect();
106        self
107    }
108
109    /// Sets the groups to run the sandboxes in
110    pub fn groups(mut self, groups: impl IntoIterator<Item = (String, Group)>) -> Self {
111        self.groups = groups.into_iter().collect();
112        self
113    }
114
115    /// Builds the Microsandbox configuration with validation
116    pub fn build(self) -> MicrosandboxResult<Microsandbox> {
117        let microsandbox = self.build_unchecked();
118        microsandbox.validate()?;
119        Ok(microsandbox)
120    }
121
122    /// Builds the Microsandbox configuration without validation
123    pub fn build_unchecked(self) -> Microsandbox {
124        Microsandbox {
125            meta: self.meta,
126            modules: self.modules,
127            builds: self.builds,
128            sandboxes: self.sandboxes,
129            groups: self.groups,
130        }
131    }
132}
133
134impl<I> SandboxBuilder<I> {
135    /// Sets the version of the sandbox
136    pub fn version(mut self, version: impl Into<Version>) -> SandboxBuilder<I> {
137        self.version = Some(version.into());
138        self
139    }
140
141    /// Sets the metadata for the sandbox
142    pub fn meta(mut self, meta: Meta) -> SandboxBuilder<I> {
143        self.meta = Some(meta);
144        self
145    }
146
147    /// Sets the image for the sandbox
148    pub fn image(self, image: impl Into<ReferenceOrPath>) -> SandboxBuilder<ReferenceOrPath> {
149        SandboxBuilder {
150            version: self.version,
151            meta: self.meta,
152            image: image.into(),
153            memory: self.memory,
154            cpus: self.cpus,
155            volumes: self.volumes,
156            ports: self.ports,
157            envs: self.envs,
158            env_file: self.env_file,
159            groups: self.groups,
160            depends_on: self.depends_on,
161            workdir: self.workdir,
162            shell: self.shell,
163            scripts: self.scripts,
164            command: self.command,
165            imports: self.imports,
166            exports: self.exports,
167            scope: self.scope,
168        }
169    }
170
171    /// Sets the maximum amount of memory allowed for the sandbox
172    pub fn memory(mut self, memory: u32) -> SandboxBuilder<I> {
173        self.memory = Some(memory);
174        self
175    }
176
177    /// Sets the maximum number of CPUs allowed for the sandbox
178    pub fn cpus(mut self, cpus: u8) -> SandboxBuilder<I> {
179        self.cpus = Some(cpus);
180        self
181    }
182
183    /// Sets the volumes to mount for the sandbox
184    pub fn volumes(mut self, volumes: impl IntoIterator<Item = PathPair>) -> SandboxBuilder<I> {
185        self.volumes = volumes.into_iter().collect();
186        self
187    }
188
189    /// Sets the ports to expose for the sandbox
190    pub fn ports(mut self, ports: impl IntoIterator<Item = PortPair>) -> SandboxBuilder<I> {
191        self.ports = ports.into_iter().collect();
192        self
193    }
194
195    /// Sets the environment variables for the sandbox
196    pub fn envs(mut self, envs: impl IntoIterator<Item = EnvPair>) -> SandboxBuilder<I> {
197        self.envs = envs.into_iter().collect();
198        self
199    }
200
201    /// Sets the environment file for the sandbox
202    pub fn env_file(mut self, env_file: impl Into<Utf8UnixPathBuf>) -> SandboxBuilder<I> {
203        self.env_file = Some(env_file.into());
204        self
205    }
206
207    /// Sets the groups for the sandbox
208    pub fn groups(
209        mut self,
210        groups: impl IntoIterator<Item = (String, SandboxGroup)>,
211    ) -> SandboxBuilder<I> {
212        self.groups = groups.into_iter().collect();
213        self
214    }
215
216    /// Sets the sandboxes that the sandbox depends on
217    pub fn depends_on(mut self, depends_on: impl IntoIterator<Item = String>) -> SandboxBuilder<I> {
218        self.depends_on = depends_on.into_iter().collect();
219        self
220    }
221
222    /// Sets the working directory for the sandbox
223    pub fn workdir(mut self, workdir: impl Into<Utf8UnixPathBuf>) -> SandboxBuilder<I> {
224        self.workdir = Some(workdir.into());
225        self
226    }
227
228    /// Sets the shell for the sandbox
229    pub fn shell(mut self, shell: impl AsRef<str>) -> SandboxBuilder<I> {
230        self.shell = Some(shell.as_ref().to_string());
231        self
232    }
233
234    /// Sets the scripts for the sandbox
235    pub fn scripts(
236        mut self,
237        scripts: impl IntoIterator<Item = (String, String)>,
238    ) -> SandboxBuilder<I> {
239        self.scripts = scripts.into_iter().collect();
240        self
241    }
242
243    /// Sets the command for the sandbox
244    pub fn command(mut self, command: impl IntoIterator<Item = String>) -> SandboxBuilder<I> {
245        self.command = command.into_iter().collect();
246        self
247    }
248
249    /// Sets the files to import for the sandbox
250    pub fn imports(
251        mut self,
252        imports: impl IntoIterator<Item = (String, Utf8UnixPathBuf)>,
253    ) -> SandboxBuilder<I> {
254        self.imports = imports.into_iter().collect();
255        self
256    }
257
258    /// Sets the files to export for the sandbox
259    pub fn exports(
260        mut self,
261        exports: impl IntoIterator<Item = (String, Utf8UnixPathBuf)>,
262    ) -> SandboxBuilder<I> {
263        self.exports = exports.into_iter().collect();
264        self
265    }
266
267    /// Sets the network scope for the sandbox
268    pub fn scope(mut self, scope: NetworkScope) -> SandboxBuilder<I> {
269        self.scope = scope;
270        self
271    }
272}
273
274impl SandboxBuilder<ReferenceOrPath> {
275    /// Builds the sandbox
276    pub fn build(self) -> Sandbox {
277        Sandbox {
278            version: self.version,
279            meta: self.meta,
280            image: self.image,
281            memory: self.memory,
282            cpus: self.cpus,
283            volumes: self.volumes,
284            ports: self.ports,
285            envs: self.envs,
286            groups: self.groups,
287            depends_on: self.depends_on,
288            workdir: self.workdir,
289            shell: self.shell,
290            scripts: self.scripts,
291            command: self.command,
292            imports: self.imports,
293            exports: self.exports,
294            scope: self.scope,
295        }
296    }
297}
298
299//--------------------------------------------------------------------------------------------------
300// Trait Implementations
301//--------------------------------------------------------------------------------------------------
302
303impl Default for SandboxBuilder<()> {
304    fn default() -> Self {
305        Self {
306            version: None,
307            meta: None,
308            image: (),
309            memory: None,
310            cpus: None,
311            volumes: Vec::new(),
312            ports: Vec::new(),
313            envs: Vec::new(),
314            env_file: None,
315            groups: HashMap::new(),
316            depends_on: Vec::new(),
317            workdir: None,
318            shell: Some(DEFAULT_SHELL.to_string()),
319            scripts: HashMap::new(),
320            command: Vec::new(),
321            imports: HashMap::new(),
322            exports: HashMap::new(),
323            scope: NetworkScope::default(),
324        }
325    }
326}