Skip to main content

a3s_box_sdk/sandbox/
builder.rs

1use std::path::PathBuf;
2
3use a3s_box_core::{ExecutionIsolation, ExecutionSnapshotId, PortMapping};
4
5use super::{Sandbox, SandboxCreateOptions, SandboxNetwork, TmpfsMount, VolumeMount};
6use crate::{A3sBoxClient, Result};
7
8/// Fluent builder for a local Sandbox.
9#[derive(Debug, Clone)]
10pub struct SandboxBuilder {
11    client: A3sBoxClient,
12    options: SandboxCreateOptions,
13}
14
15impl SandboxBuilder {
16    pub(crate) fn new(client: A3sBoxClient, image: impl Into<String>) -> Self {
17        Self {
18            client,
19            options: SandboxCreateOptions::new(image),
20        }
21    }
22
23    pub const fn timeout_seconds(mut self, timeout_seconds: u64) -> Self {
24        self.options.timeout_seconds = timeout_seconds;
25        self
26    }
27
28    pub fn env(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
29        self.options.envs.insert(key.into(), value.into());
30        self
31    }
32
33    pub fn metadata(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
34        self.options.metadata.insert(key.into(), value.into());
35        self
36    }
37
38    pub fn name(mut self, name: impl Into<String>) -> Self {
39        self.options.name = Some(name.into());
40        self
41    }
42
43    pub const fn cpus(mut self, cpus: u32) -> Self {
44        self.options.cpus = Some(cpus);
45        self
46    }
47
48    pub const fn memory_mb(mut self, memory_mb: u32) -> Self {
49        self.options.memory_mb = Some(memory_mb);
50        self
51    }
52
53    pub const fn isolation(mut self, isolation: ExecutionIsolation) -> Self {
54        self.options.isolation = isolation;
55        self
56    }
57
58    pub fn filesystem_snapshot(mut self, snapshot_id: ExecutionSnapshotId) -> Self {
59        self.options.rootfs_snapshot_id = Some(snapshot_id);
60        self
61    }
62
63    pub fn workspace(mut self, path: impl Into<PathBuf>) -> Self {
64        self.options.workspace = Some(path.into());
65        self
66    }
67
68    pub fn workdir(mut self, path: impl Into<String>) -> Self {
69        self.options.workdir = Some(path.into());
70        self
71    }
72
73    pub fn user(mut self, user: impl Into<String>) -> Self {
74        self.options.user = Some(user.into());
75        self
76    }
77
78    pub fn hostname(mut self, hostname: impl Into<String>) -> Self {
79        self.options.hostname = Some(hostname.into());
80        self
81    }
82
83    pub fn mount(mut self, mount: VolumeMount) -> Self {
84        self.options.mounts.push(mount);
85        self
86    }
87
88    pub fn mount_bind(self, source: impl Into<PathBuf>, target: impl Into<String>) -> Self {
89        self.mount(VolumeMount::bind(source, target))
90    }
91
92    pub fn mount_named(self, name: impl Into<String>, target: impl Into<String>) -> Self {
93        self.mount(VolumeMount::named(name, target))
94    }
95
96    pub fn tmpfs(mut self, mount: TmpfsMount) -> Self {
97        self.options.tmpfs.push(mount);
98        self
99    }
100
101    pub fn network(mut self, network: SandboxNetwork) -> Self {
102        self.options.network = network;
103        self
104    }
105
106    pub fn publish_port(mut self, port: PortMapping) -> Self {
107        self.options.ports.push(port);
108        self
109    }
110
111    pub fn publish_tcp(mut self, host_port: u16, guest_port: u16) -> Self {
112        self.options.ports.push(PortMapping {
113            host_port,
114            guest_port,
115            protocol: a3s_box_core::PortProtocol::Tcp,
116        });
117        self
118    }
119
120    pub fn dns_server(mut self, server: impl Into<String>) -> Self {
121        self.options.dns_servers.push(server.into());
122        self
123    }
124
125    pub fn host_alias(mut self, host: impl Into<String>, ip: impl Into<String>) -> Self {
126        self.options.host_aliases.insert(host.into(), ip.into());
127        self
128    }
129
130    pub const fn read_only(mut self, read_only: bool) -> Self {
131        self.options.read_only = read_only;
132        self
133    }
134
135    pub const fn persistent(mut self, persistent: bool) -> Self {
136        self.options.persistent = persistent;
137        self
138    }
139
140    pub const fn auto_remove(mut self, auto_remove: bool) -> Self {
141        self.options.auto_remove = auto_remove;
142        self
143    }
144
145    pub async fn start(self) -> Result<Sandbox> {
146        Sandbox::create_with_client(self.client, self.options).await
147    }
148
149    /// Return the typed request value without starting a Sandbox.
150    pub fn options(&self) -> &SandboxCreateOptions {
151        &self.options
152    }
153}
154
155impl A3sBoxClient {
156    /// Start a fluent builder for a local Sandbox.
157    pub fn sandbox(&self, image: impl Into<String>) -> SandboxBuilder {
158        SandboxBuilder::new(self.clone(), image)
159    }
160}