mirror of
https://github.com/fabro-sh/fabro.git
synced 2026-10-06 02:48:25 +00:00
Add SandboxProvider::Exe for exe.dev VM sandboxes
New `arc-exe` crate that runs agent tool operations inside ephemeral exe.dev VMs via SSH. Uses two SSH connections: a management plane (`ssh exe.dev`) for VM lifecycle and a data plane (`ssh vmname.exe.xyz`) for command execution and file I/O. Includes SshRunner trait with MockSshRunner for unit tests and OpensshRunner for real SSH, with raw_mode for the exe.dev management plane's custom command handler. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
a67c1be788
commit
5df7e178ac
11 changed files with 1415 additions and 10 deletions
49
Cargo.lock
generated
49
Cargo.lock
generated
|
|
@ -236,6 +236,22 @@ dependencies = [
|
|||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "arc-exe"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"arc-agent",
|
||||
"async-trait",
|
||||
"base64",
|
||||
"openssh",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tempfile",
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "arc-git-storage"
|
||||
version = "0.1.0"
|
||||
|
|
@ -339,6 +355,7 @@ version = "0.1.0"
|
|||
dependencies = [
|
||||
"anyhow",
|
||||
"arc-agent",
|
||||
"arc-exe",
|
||||
"arc-git-storage",
|
||||
"arc-llm",
|
||||
"arc-util",
|
||||
|
|
@ -806,7 +823,7 @@ version = "3.1.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "faf9468729b8cbcea668e36183cb69d317348c2e08e994829fb56ebfdfbaac34"
|
||||
dependencies = [
|
||||
"windows-sys 0.48.0",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -1273,7 +1290,7 @@ dependencies = [
|
|||
"libc",
|
||||
"option-ext",
|
||||
"redox_users",
|
||||
"windows-sys 0.59.0",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -1360,7 +1377,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.59.0",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -2672,7 +2689,7 @@ version = "0.50.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5"
|
||||
dependencies = [
|
||||
"windows-sys 0.59.0",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -2809,6 +2826,20 @@ dependencies = [
|
|||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "openssh"
|
||||
version = "0.11.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d534c4bfecb0ed71dea4db444a5922a294d15cf40e700548f27295e1feb0ef18"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"once_cell",
|
||||
"shell-escape",
|
||||
"tempfile",
|
||||
"thiserror 2.0.18",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "openssl"
|
||||
version = "0.10.75"
|
||||
|
|
@ -3217,7 +3248,7 @@ dependencies = [
|
|||
"once_cell",
|
||||
"socket2",
|
||||
"tracing",
|
||||
"windows-sys 0.59.0",
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -3606,7 +3637,7 @@ dependencies = [
|
|||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
"windows-sys 0.59.0",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -3674,7 +3705,7 @@ dependencies = [
|
|||
"security-framework",
|
||||
"security-framework-sys",
|
||||
"webpki-root-certs",
|
||||
"windows-sys 0.59.0",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -4484,7 +4515,7 @@ dependencies = [
|
|||
"getrandom 0.4.1",
|
||||
"once_cell",
|
||||
"rustix",
|
||||
"windows-sys 0.59.0",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -5363,7 +5394,7 @@ version = "0.1.11"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
|
||||
dependencies = [
|
||||
"windows-sys 0.48.0",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ toml = "0.8"
|
|||
jsonwebtoken = { version = "10", features = ["aws_lc_rs"] }
|
||||
tokio-tungstenite = { version = "0.26", features = ["rustls-tls-webpki-roots"] }
|
||||
futures-util = "0.3"
|
||||
openssh = "0.11"
|
||||
daytona-sdk = { git = "https://github.com/brynary/daytona-sdk-rust", package = "daytona-sdk" }
|
||||
daytona-api-client = { git = "https://github.com/brynary/daytona-sdk-rust", package = "daytona-api-client" }
|
||||
|
||||
|
|
|
|||
|
|
@ -933,6 +933,7 @@ mod runs {
|
|||
}),
|
||||
network: Some(arc_workflows::daytona_sandbox::DaytonaNetwork::Block),
|
||||
}),
|
||||
exe: None,
|
||||
}),
|
||||
vars: Some(std::collections::HashMap::from([
|
||||
("repo_url".into(), "https://github.com/org/api-server".into()),
|
||||
|
|
@ -1051,6 +1052,7 @@ mod workflows {
|
|||
}),
|
||||
network: None,
|
||||
}),
|
||||
exe: None,
|
||||
}),
|
||||
vars: Some(std::collections::HashMap::from([
|
||||
("repo_url".into(), "https://github.com/org/service".into()),
|
||||
|
|
@ -1114,6 +1116,7 @@ mod workflows {
|
|||
}),
|
||||
network: None,
|
||||
}),
|
||||
exe: None,
|
||||
}),
|
||||
vars: Some(std::collections::HashMap::from([
|
||||
("spec_path".into(), "specs/feature.md".into()),
|
||||
|
|
@ -1188,6 +1191,7 @@ mod workflows {
|
|||
}),
|
||||
network: None,
|
||||
}),
|
||||
exe: None,
|
||||
}),
|
||||
vars: Some(std::collections::HashMap::from([
|
||||
("source_env".into(), "production".into()),
|
||||
|
|
@ -1253,6 +1257,7 @@ mod workflows {
|
|||
}),
|
||||
network: None,
|
||||
}),
|
||||
exe: None,
|
||||
}),
|
||||
vars: Some(std::collections::HashMap::from([
|
||||
("analytics_window".into(), "30d".into()),
|
||||
|
|
@ -2590,6 +2595,7 @@ mod settings {
|
|||
snapshot: None,
|
||||
network: Some(arc_workflows::daytona_sandbox::DaytonaNetwork::Block),
|
||||
}),
|
||||
exe: None,
|
||||
}),
|
||||
vars: None,
|
||||
},
|
||||
|
|
|
|||
24
crates/arc-exe/Cargo.toml
Normal file
24
crates/arc-exe/Cargo.toml
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
[package]
|
||||
name = "arc-exe"
|
||||
edition.workspace = true
|
||||
version.workspace = true
|
||||
license.workspace = true
|
||||
description = "exe.dev VM sandbox for Arc agent tool operations"
|
||||
|
||||
[lib]
|
||||
doctest = false
|
||||
|
||||
[dependencies]
|
||||
arc-agent = { path = "../arc-agent" }
|
||||
async-trait.workspace = true
|
||||
tokio.workspace = true
|
||||
tokio-util.workspace = true
|
||||
openssh.workspace = true
|
||||
serde_json.workspace = true
|
||||
base64.workspace = true
|
||||
tracing.workspace = true
|
||||
serde.workspace = true
|
||||
|
||||
[dev-dependencies]
|
||||
tokio = { workspace = true, features = ["test-util", "macros"] }
|
||||
tempfile = "3"
|
||||
1124
crates/arc-exe/src/lib.rs
Normal file
1124
crates/arc-exe/src/lib.rs
Normal file
File diff suppressed because it is too large
Load diff
123
crates/arc-exe/src/openssh_runner.rs
Normal file
123
crates/arc-exe/src/openssh_runner.rs
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
use async_trait::async_trait;
|
||||
use openssh::{KnownHosts, Session};
|
||||
|
||||
use crate::{SshOutput, SshRunner};
|
||||
|
||||
/// Real SSH implementation using the `openssh` crate (multiplexed connections).
|
||||
pub struct OpensshRunner {
|
||||
session: Session,
|
||||
/// When true, commands are sent via `raw_command` (no shell wrapping).
|
||||
/// Used for the exe.dev management plane which has a custom SSH command handler.
|
||||
raw_mode: bool,
|
||||
}
|
||||
|
||||
impl OpensshRunner {
|
||||
/// Connect to a host via SSH, using the user's SSH agent for authentication.
|
||||
/// Commands are executed through a shell (`sh -c`).
|
||||
pub async fn connect(host: &str) -> Result<Self, String> {
|
||||
let session = Session::connect(host, KnownHosts::Accept)
|
||||
.await
|
||||
.map_err(|e| format!("SSH connection to {host} failed: {e}"))?;
|
||||
Ok(Self {
|
||||
session,
|
||||
raw_mode: false,
|
||||
})
|
||||
}
|
||||
|
||||
/// Connect to a host via SSH in raw mode (no shell wrapping).
|
||||
/// Commands are sent directly as the SSH command string.
|
||||
/// Used for the exe.dev management plane which has a custom command handler.
|
||||
pub async fn connect_raw(host: &str) -> Result<Self, String> {
|
||||
let session = Session::connect(host, KnownHosts::Accept)
|
||||
.await
|
||||
.map_err(|e| format!("SSH connection to {host} failed: {e}"))?;
|
||||
Ok(Self {
|
||||
session,
|
||||
raw_mode: true,
|
||||
})
|
||||
}
|
||||
|
||||
fn build_command(&self, command: &str) -> openssh::OwningCommand<&Session> {
|
||||
if self.raw_mode {
|
||||
self.session.raw_command(command)
|
||||
} else {
|
||||
self.session.shell(command)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl SshRunner for OpensshRunner {
|
||||
async fn run_command(&self, command: &str) -> Result<SshOutput, String> {
|
||||
let output = self
|
||||
.build_command(command)
|
||||
.output()
|
||||
.await
|
||||
.map_err(|e| format!("SSH command failed: {e}"))?;
|
||||
|
||||
let exit_code = output.status.code().unwrap_or(-1);
|
||||
Ok(SshOutput {
|
||||
stdout: output.stdout,
|
||||
stderr: output.stderr,
|
||||
exit_code,
|
||||
})
|
||||
}
|
||||
|
||||
async fn run_command_with_timeout(
|
||||
&self,
|
||||
command: &str,
|
||||
timeout: std::time::Duration,
|
||||
) -> Result<SshOutput, String> {
|
||||
let mut child = self.build_command(command);
|
||||
let fut = child.output();
|
||||
|
||||
match tokio::time::timeout(timeout, fut).await {
|
||||
Ok(Ok(output)) => {
|
||||
let exit_code = output.status.code().unwrap_or(-1);
|
||||
Ok(SshOutput {
|
||||
stdout: output.stdout,
|
||||
stderr: output.stderr,
|
||||
exit_code,
|
||||
})
|
||||
}
|
||||
Ok(Err(e)) => Err(format!("SSH command failed: {e}")),
|
||||
Err(_) => Err("Command timed out".to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
async fn upload_file(&self, path: &str, content: &[u8]) -> Result<(), String> {
|
||||
use base64::Engine;
|
||||
let encoded = base64::engine::general_purpose::STANDARD.encode(content);
|
||||
let cmd = format!(
|
||||
"echo '{}' | base64 -d > '{}'",
|
||||
encoded,
|
||||
path.replace('\'', "'\\''"),
|
||||
);
|
||||
let output = self
|
||||
.build_command(&cmd)
|
||||
.output()
|
||||
.await
|
||||
.map_err(|e| format!("SSH upload failed: {e}"))?;
|
||||
|
||||
if !output.status.success() {
|
||||
let stderr = String::from_utf8_lossy(&output.stderr);
|
||||
return Err(format!("Upload to {path} failed: {stderr}"));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn download_file(&self, path: &str) -> Result<Vec<u8>, String> {
|
||||
let cmd = format!("cat '{}'", path.replace('\'', "'\\''"));
|
||||
let output = self
|
||||
.build_command(&cmd)
|
||||
.output()
|
||||
.await
|
||||
.map_err(|e| format!("SSH download failed: {e}"))?;
|
||||
|
||||
if !output.status.success() {
|
||||
let stderr = String::from_utf8_lossy(&output.stderr);
|
||||
return Err(format!("Download of {path} failed: {stderr}"));
|
||||
}
|
||||
Ok(output.stdout)
|
||||
}
|
||||
}
|
||||
49
crates/arc-exe/tests/integration.rs
Normal file
49
crates/arc-exe/tests/integration.rs
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
use arc_agent::sandbox::Sandbox;
|
||||
use arc_exe::{ExeSandbox, OpensshRunner};
|
||||
|
||||
/// Full lifecycle test against a real exe.dev account.
|
||||
/// Requires SSH agent with exe.dev credentials.
|
||||
///
|
||||
/// Run with: cargo test -p arc-exe -- --ignored
|
||||
#[tokio::test]
|
||||
#[ignore]
|
||||
async fn exe_sandbox_full_lifecycle() {
|
||||
let mgmt_ssh = OpensshRunner::connect_raw("exe.dev")
|
||||
.await
|
||||
.expect("SSH to exe.dev failed — is your SSH agent running?");
|
||||
|
||||
let sandbox = ExeSandbox::new(Box::new(mgmt_ssh));
|
||||
|
||||
// Initialize (creates VM)
|
||||
sandbox.initialize().await.unwrap();
|
||||
assert!(!sandbox.sandbox_info().is_empty());
|
||||
assert_eq!(sandbox.platform(), "linux");
|
||||
|
||||
// exec_command
|
||||
let result = sandbox
|
||||
.exec_command("echo hello", 10_000, None, None, None)
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(result.stdout.trim(), "hello");
|
||||
assert_eq!(result.exit_code, 0);
|
||||
|
||||
// write_file + read_file
|
||||
sandbox
|
||||
.write_file("test.txt", "line1\nline2\nline3")
|
||||
.await
|
||||
.unwrap();
|
||||
let content = sandbox.read_file("test.txt", None, None).await.unwrap();
|
||||
assert!(content.contains("1 | line1"));
|
||||
assert!(content.contains("2 | line2"));
|
||||
|
||||
// file_exists
|
||||
assert!(sandbox.file_exists("test.txt").await.unwrap());
|
||||
assert!(!sandbox.file_exists("nonexistent.txt").await.unwrap());
|
||||
|
||||
// delete_file
|
||||
sandbox.delete_file("test.txt").await.unwrap();
|
||||
assert!(!sandbox.file_exists("test.txt").await.unwrap());
|
||||
|
||||
// Cleanup (destroys VM)
|
||||
sandbox.cleanup().await.unwrap();
|
||||
}
|
||||
|
|
@ -17,6 +17,7 @@ clap.workspace = true
|
|||
anyhow.workspace = true
|
||||
dotenvy.workspace = true
|
||||
arc-agent = { path = "../arc-agent" }
|
||||
arc-exe = { path = "../arc-exe" }
|
||||
arc-util = { path = "../arc-util" }
|
||||
arc-git-storage = { path = "../arc-git-storage" }
|
||||
arc-llm = { path = "../arc-llm" }
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@ pub enum SandboxProvider {
|
|||
Docker,
|
||||
/// Run tools inside a Daytona cloud sandbox
|
||||
Daytona,
|
||||
/// Run tools inside an exe.dev VM
|
||||
Exe,
|
||||
}
|
||||
|
||||
impl fmt::Display for SandboxProvider {
|
||||
|
|
@ -36,6 +38,7 @@ impl fmt::Display for SandboxProvider {
|
|||
Self::Local => write!(f, "local"),
|
||||
Self::Docker => write!(f, "docker"),
|
||||
Self::Daytona => write!(f, "daytona"),
|
||||
Self::Exe => write!(f, "exe"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -48,6 +51,7 @@ impl FromStr for SandboxProvider {
|
|||
"local" => Ok(Self::Local),
|
||||
"docker" => Ok(Self::Docker),
|
||||
"daytona" => Ok(Self::Daytona),
|
||||
"exe" => Ok(Self::Exe),
|
||||
other => Err(format!("unknown sandbox provider: {other}")),
|
||||
}
|
||||
}
|
||||
|
|
@ -255,6 +259,14 @@ mod tests {
|
|||
"LOCAL".parse::<SandboxProvider>().unwrap(),
|
||||
SandboxProvider::Local
|
||||
);
|
||||
assert_eq!(
|
||||
"exe".parse::<SandboxProvider>().unwrap(),
|
||||
SandboxProvider::Exe
|
||||
);
|
||||
assert_eq!(
|
||||
"EXE".parse::<SandboxProvider>().unwrap(),
|
||||
SandboxProvider::Exe
|
||||
);
|
||||
assert!("invalid".parse::<SandboxProvider>().is_err());
|
||||
}
|
||||
|
||||
|
|
@ -263,6 +275,7 @@ mod tests {
|
|||
assert_eq!(SandboxProvider::Local.to_string(), "local");
|
||||
assert_eq!(SandboxProvider::Docker.to_string(), "docker");
|
||||
assert_eq!(SandboxProvider::Daytona.to_string(), "daytona");
|
||||
assert_eq!(SandboxProvider::Exe.to_string(), "exe");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
|
|
@ -267,7 +267,7 @@ pub async fn run_command(
|
|||
SandboxProvider::Local | SandboxProvider::Docker => {
|
||||
crate::git::ensure_clean(&original_cwd).is_ok()
|
||||
}
|
||||
SandboxProvider::Daytona => false,
|
||||
SandboxProvider::Daytona | SandboxProvider::Exe => false,
|
||||
};
|
||||
|
||||
if args.preflight {
|
||||
|
|
@ -457,6 +457,17 @@ pub async fn run_command(
|
|||
daytona_sandbox_ref = Some(Arc::clone(&daytona_arc));
|
||||
daytona_arc
|
||||
}
|
||||
SandboxProvider::Exe => {
|
||||
let mgmt_ssh = arc_exe::OpensshRunner::connect_raw("exe.dev")
|
||||
.await
|
||||
.map_err(|e| anyhow::anyhow!("Failed to connect to exe.dev: {e}"))?;
|
||||
let mut env = arc_exe::ExeSandbox::new(Box::new(mgmt_ssh));
|
||||
let emitter_cb = Arc::clone(&emitter);
|
||||
env.set_event_callback(Arc::new(move |event| {
|
||||
emitter_cb.emit(&crate::event::WorkflowRunEvent::Sandbox { event });
|
||||
}));
|
||||
Arc::new(env)
|
||||
}
|
||||
SandboxProvider::Local => {
|
||||
let mut env = LocalSandbox::new(cwd);
|
||||
let emitter_cb = Arc::clone(&emitter);
|
||||
|
|
@ -667,6 +678,7 @@ pub async fn run_command(
|
|||
SandboxProvider::Daytona => daytona_base_sha
|
||||
.as_ref()
|
||||
.map(|_| GitCheckpointMode::Remote(original_cwd.clone())),
|
||||
SandboxProvider::Exe => None,
|
||||
},
|
||||
base_sha: worktree_base_sha.or(daytona_base_sha),
|
||||
run_branch: worktree_branch.or(daytona_branch),
|
||||
|
|
@ -1202,6 +1214,13 @@ async fn run_preflight(
|
|||
}
|
||||
Err(e) => Err(format!("Daytona client creation failed: {e}")),
|
||||
},
|
||||
SandboxProvider::Exe => match arc_exe::OpensshRunner::connect_raw("exe.dev").await {
|
||||
Ok(mgmt_ssh) => {
|
||||
let env = arc_exe::ExeSandbox::new(Box::new(mgmt_ssh));
|
||||
Ok(Arc::new(env) as Arc<dyn Sandbox>)
|
||||
}
|
||||
Err(e) => Err(format!("exe.dev SSH connection failed: {e}")),
|
||||
},
|
||||
SandboxProvider::Local => {
|
||||
Ok(Arc::new(LocalSandbox::new(original_cwd.clone())) as Arc<dyn Sandbox>)
|
||||
}
|
||||
|
|
@ -1653,6 +1672,7 @@ mod tests {
|
|||
provider: None,
|
||||
preserve: Some(false),
|
||||
daytona: None,
|
||||
exe: None,
|
||||
}),
|
||||
vars: None,
|
||||
hooks: Vec::new(),
|
||||
|
|
@ -1674,6 +1694,7 @@ mod tests {
|
|||
provider: None,
|
||||
preserve: Some(true),
|
||||
daytona: None,
|
||||
exe: None,
|
||||
}),
|
||||
vars: None,
|
||||
hooks: Vec::new(),
|
||||
|
|
@ -1683,6 +1704,7 @@ mod tests {
|
|||
provider: None,
|
||||
preserve: Some(false),
|
||||
daytona: None,
|
||||
exe: None,
|
||||
}),
|
||||
..RunDefaults::default()
|
||||
};
|
||||
|
|
@ -1696,6 +1718,7 @@ mod tests {
|
|||
provider: None,
|
||||
preserve: Some(true),
|
||||
daytona: None,
|
||||
exe: None,
|
||||
}),
|
||||
..RunDefaults::default()
|
||||
};
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ pub struct SandboxConfig {
|
|||
pub provider: Option<String>,
|
||||
pub preserve: Option<bool>,
|
||||
pub daytona: Option<DaytonaConfig>,
|
||||
pub exe: Option<arc_exe::ExeConfig>,
|
||||
}
|
||||
|
||||
/// Defaults for workflow runs, loaded from the server config.
|
||||
|
|
@ -754,6 +755,7 @@ preserve = true
|
|||
provider: None,
|
||||
preserve: Some(false),
|
||||
daytona: None,
|
||||
exe: None,
|
||||
}),
|
||||
..RunDefaults::default()
|
||||
};
|
||||
|
|
@ -779,6 +781,7 @@ provider = "docker"
|
|||
provider: None,
|
||||
preserve: Some(true),
|
||||
daytona: None,
|
||||
exe: None,
|
||||
}),
|
||||
..RunDefaults::default()
|
||||
};
|
||||
|
|
@ -807,6 +810,7 @@ provider = "daytona"
|
|||
auto_stop_interval: Some(30),
|
||||
..DaytonaConfig::default()
|
||||
}),
|
||||
exe: None,
|
||||
}),
|
||||
..RunDefaults::default()
|
||||
};
|
||||
|
|
@ -842,6 +846,7 @@ auto_stop_interval = 60
|
|||
labels: Some(HashMap::from([("env".into(), "prod".into())])),
|
||||
..DaytonaConfig::default()
|
||||
}),
|
||||
exe: None,
|
||||
}),
|
||||
..RunDefaults::default()
|
||||
};
|
||||
|
|
@ -876,6 +881,7 @@ env = "from_task"
|
|||
])),
|
||||
..DaytonaConfig::default()
|
||||
}),
|
||||
exe: None,
|
||||
}),
|
||||
..RunDefaults::default()
|
||||
};
|
||||
|
|
@ -914,6 +920,7 @@ cpu = 2
|
|||
}),
|
||||
..DaytonaConfig::default()
|
||||
}),
|
||||
exe: None,
|
||||
}),
|
||||
..RunDefaults::default()
|
||||
};
|
||||
|
|
@ -951,6 +958,7 @@ auto_stop_interval = 60
|
|||
}),
|
||||
..DaytonaConfig::default()
|
||||
}),
|
||||
exe: None,
|
||||
}),
|
||||
..RunDefaults::default()
|
||||
};
|
||||
|
|
@ -1183,6 +1191,7 @@ network = "block"
|
|||
network: Some(crate::daytona_sandbox::DaytonaNetwork::AllowAll),
|
||||
..DaytonaConfig::default()
|
||||
}),
|
||||
exe: None,
|
||||
}),
|
||||
..RunDefaults::default()
|
||||
};
|
||||
|
|
@ -1216,6 +1225,7 @@ auto_stop_interval = 60
|
|||
])),
|
||||
..DaytonaConfig::default()
|
||||
}),
|
||||
exe: None,
|
||||
}),
|
||||
..RunDefaults::default()
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue