#![allow(clippy::expect_used)]
use veracode_platform::sandbox::{CreateSandboxRequest, SandboxApi, SandboxError};
use veracode_platform::{VeracodeClient, VeracodeConfig, VeracodeError};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let config = VeracodeConfig::new(
&std::env::var("VERACODE_API_ID").expect("VERACODE_API_ID environment variable required"),
&std::env::var("VERACODE_API_KEY").expect("VERACODE_API_KEY environment variable required"),
);
let search_name = std::env::var("APP_NAME").unwrap_or_else(|_| {
println!("💡 Tip: Set APP_NAME environment variable to search for specific applications");
"Test Application".to_string()
});
let client = VeracodeClient::new(config)?;
let sandbox_api = SandboxApi::new(&client);
let application_guid = search_applications(&client, &search_name).await?;
println!("🏗️ Creating sandbox examples...\n");
println!("📦 Creating a simple sandbox...");
let simple_sandbox = match sandbox_api
.create_simple_sandbox(&application_guid, "my-dev-sandbox")
.await
{
Ok(sandbox) => {
println!(
"✅ Created simple sandbox: {} ({})",
sandbox.name, sandbox.guid
);
sandbox
}
Err(SandboxError::AlreadyExists(_)) => {
println!("⚠️ Sandbox 'my-dev-sandbox' already exists, retrieving it...");
sandbox_api
.get_sandbox_by_name(&application_guid, "my-dev-sandbox")
.await?
.expect("Sandbox should exist")
}
Err(e) => return Err(e.into()),
};
println!("\n📦 Creating an auto-recreate sandbox...");
let auto_recreate_sandbox = match sandbox_api
.create_auto_recreate_sandbox(
&application_guid,
"auto-recreate-sandbox",
Some("This sandbox will auto-recreate after promotion".to_string()),
)
.await
{
Ok(sandbox) => {
println!(
"✅ Created auto-recreate sandbox: {} ({})",
sandbox.name, sandbox.guid
);
sandbox
}
Err(SandboxError::AlreadyExists(_)) => {
println!("⚠️ Sandbox 'auto-recreate-sandbox' already exists, retrieving it...");
sandbox_api
.get_sandbox_by_name(&application_guid, "auto-recreate-sandbox")
.await?
.expect("Sandbox should exist")
}
Err(e) => return Err(e.into()),
};
println!("\n📦 Creating a sandbox with custom configuration...");
let custom_request = CreateSandboxRequest {
name: "feature-xyz-sandbox".to_string(),
description: Some("Sandbox for developing feature XYZ".to_string()),
auto_recreate: Some(true),
custom_fields: None, team_identifiers: None, };
let custom_sandbox = match sandbox_api
.create_sandbox(&application_guid, custom_request)
.await
{
Ok(sandbox) => {
println!(
"✅ Created custom sandbox: {} ({})",
sandbox.name, sandbox.guid
);
sandbox
}
Err(SandboxError::AlreadyExists(_)) => {
println!("⚠️ Sandbox 'feature-xyz-sandbox' already exists, retrieving it...");
sandbox_api
.get_sandbox_by_name(&application_guid, "feature-xyz-sandbox")
.await?
.expect("Sandbox should exist")
}
Err(e) => return Err(e.into()),
};
println!("\n📋 Listing all sandboxes...");
let all_sandboxes = sandbox_api.list_sandboxes(&application_guid, None).await?;
println!("Found {} sandboxes:", all_sandboxes.len());
for sandbox in &all_sandboxes {
println!(
" - {} ({}) - Created: {}",
sandbox.name,
sandbox.guid,
sandbox.created.format("%Y-%m-%d %H:%M:%S")
);
}
println!("\n🔍 Checking if sandbox exists...");
let exists = sandbox_api
.sandbox_exists(&application_guid, &simple_sandbox.guid)
.await?;
println!("Simple sandbox exists: {exists}");
println!("\n🔍 Finding sandbox by name...");
match sandbox_api
.get_sandbox_by_name(&application_guid, "my-dev-sandbox")
.await?
{
Some(found_sandbox) => {
println!(
"Found sandbox: {} ({})",
found_sandbox.name, found_sandbox.guid
);
}
None => {
println!("Sandbox not found");
}
}
println!("\n✏️ Updating sandbox name...");
let updated_sandbox = sandbox_api
.update_sandbox_name(
&application_guid,
&simple_sandbox.guid,
"my-renamed-dev-sandbox",
)
.await?;
println!(
"✅ Updated sandbox name: {} -> {}",
simple_sandbox.name, updated_sandbox.name
);
println!("\n⏳ Waiting 5 seconds before cleanup...");
tokio::time::sleep(tokio::time::Duration::from_secs(5)).await;
println!("\n🗑️ Deleting sandboxes...");
match sandbox_api
.delete_sandbox(&application_guid, &simple_sandbox.guid)
.await
{
Ok(_) => println!("✅ Deleted simple sandbox"),
Err(SandboxError::NotFound) => println!("⚠️ Simple sandbox not found (already deleted?)"),
Err(e) => println!("❌ Failed to delete simple sandbox: {e}"),
}
match sandbox_api
.delete_sandbox(&application_guid, &auto_recreate_sandbox.guid)
.await
{
Ok(_) => println!("✅ Deleted auto-recreate sandbox"),
Err(SandboxError::NotFound) => {
println!("⚠️ Auto-recreate sandbox not found (already deleted?)")
}
Err(e) => println!("❌ Failed to delete auto-recreate sandbox: {e}"),
}
match sandbox_api
.delete_sandbox(&application_guid, &custom_sandbox.guid)
.await
{
Ok(_) => println!("✅ Deleted custom sandbox"),
Err(SandboxError::NotFound) => println!("⚠️ Custom sandbox not found (already deleted?)"),
Err(e) => println!("❌ Failed to delete custom sandbox: {e}"),
}
println!("\n🔍 Verifying sandboxes were deleted...");
let remaining_sandboxes = sandbox_api.list_sandboxes(&application_guid, None).await?;
println!("Remaining sandboxes: {}", remaining_sandboxes.len());
println!("\n✅ Sandbox lifecycle example completed!");
Ok(())
}
async fn search_applications(
client: &VeracodeClient,
search_name: &str,
) -> Result<String, VeracodeError> {
println!("🔍 Searching for applications containing '{search_name}'...");
let matching_apps = client.search_applications_by_name(search_name).await?;
let app_found = match matching_apps.first() {
Some(app) => app,
None => {
println!("❌ No applications found matching '{search_name}'");
return Err(VeracodeError::NotFound("No applications found".to_string()));
}
};
Ok(app_found.guid.clone())
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn test_sandbox_creation_validation() {
let config = VeracodeConfig::new("test-api-id", "test-api-key");
let client = VeracodeClient::new(config).expect("should create client");
let sandbox_api = SandboxApi::new(&client);
let invalid_request = CreateSandboxRequest {
name: "".to_string(), description: None,
auto_recreate: None,
custom_fields: None,
team_identifiers: None,
};
let result = sandbox_api
.create_sandbox("dummy-guid", invalid_request)
.await;
assert!(result.is_err());
if let Err(SandboxError::InvalidInput(_)) = result {
} else {
panic!("Expected InvalidInput error");
}
}
}