#![warn(missing_docs)]
#![warn(rustdoc::missing_crate_level_docs)]
pub mod context;
pub mod environment;
pub mod inheritance;
pub mod mounts;
pub mod providers;
pub mod resources;
pub mod runtime;
pub mod secrets;
pub mod storage;
pub use context::{ContextMetadata, ExecutionContext};
pub use environment::{
EnvFileRef, EnvValue, EnvironmentConfig, GeneratedValue, SecretRef,
};
pub use mounts::{Mount, MountType};
pub use resources::{
CpuConfig, ExecutionLimits, FilesystemConfig, MemoryConfig, NetworkConfig,
RateLimit, ResourceConfig,
};
pub use runtime::{DockerOverrides, NativeOverrides, RuntimeOverrides, WasmOverrides};
pub use secrets::{
ExternalSecretProvider, SecretDefinition, SecretFileFormat, SecretInjectionTarget,
SecretProviderConfig, SecretsConfig,
};
pub use inheritance::{
merge_environments, merge_mounts, merge_resources, merge_secrets, resolve_context,
ContextResolver,
};
pub use storage::{BackupInfo, ContextIndex, ContextIndexEntry, ContextStorage};
pub use providers::{
EnvironmentProvider, FileProvider, KeychainProvider, SecretManager, SecretProvider,
SecretValue,
};
pub mod error {
use thiserror::Error;
#[derive(Debug, Error)]
pub enum ContextError {
#[error("Context not found: {0}")]
NotFound(String),
#[error("Context already exists: {0}")]
AlreadyExists(String),
#[error("Invalid context configuration: {0}")]
InvalidConfig(String),
#[error("Circular inheritance detected: {0}")]
CircularInheritance(String),
#[error("Parent context not found: {0}")]
ParentNotFound(String),
#[error("Secret not found: {0}")]
SecretNotFound(String),
#[error("Required secret not set: {0}")]
RequiredSecretNotSet(String),
#[error("Mount source not found: {0}")]
MountSourceNotFound(String),
#[error("Invalid mount configuration: {0}")]
InvalidMount(String),
#[error("IO error: {0}")]
Io(#[from] std::io::Error),
#[error("Serialization error: {0}")]
Serialization(String),
#[error("Secret provider error: {0}")]
SecretProvider(String),
}
impl From<serde_json::Error> for ContextError {
fn from(e: serde_json::Error) -> Self {
Self::Serialization(e.to_string())
}
}
impl From<toml::de::Error> for ContextError {
fn from(e: toml::de::Error) -> Self {
Self::Serialization(e.to_string())
}
}
impl From<toml::ser::Error> for ContextError {
fn from(e: toml::ser::Error) -> Self {
Self::Serialization(e.to_string())
}
}
}
pub use error::ContextError;
pub type Result<T> = std::result::Result<T, ContextError>;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_full_context_creation() {
let context = ExecutionContext::new("test-context", "Test Context")
.with_description("A comprehensive test context")
.with_mount(
Mount::directory("data", "/host/data", "/app/data")
.as_read_write()
.with_description("Data directory"),
)
.with_mount(
Mount::tmpfs("temp", "/tmp", 100)
.as_optional(),
)
.with_environment(
EnvironmentConfig::new()
.with_var("LOG_LEVEL", "debug")
.with_var("APP_ENV", "test")
.with_passthrough_prefix("AWS_")
.with_passthrough_var("PATH"),
)
.with_secrets(
SecretsConfig::new()
.with_required_env_secret("api-key", "API_KEY", "API key for auth"),
)
.with_resources(
ResourceConfig::new()
.with_cpu_limit("2")
.with_memory_limit("1g")
.with_network_enabled()
.with_timeout(300),
)
.with_runtime_overrides(
RuntimeOverrides::new()
.with_docker(
DockerOverrides::new()
.with_user("1000:1000")
.with_no_new_privileges(),
),
)
.with_tag("test")
.with_tag("comprehensive");
assert_eq!(context.id, "test-context");
assert_eq!(context.name, "Test Context");
assert_eq!(context.mounts.len(), 2);
assert_eq!(context.environment.variables.len(), 2);
assert!(!context.secrets.is_empty());
assert!(context.resources.cpu.is_some());
assert!(context.resources.memory.is_some());
assert!(context.resources.network.enabled);
assert!(context.runtime_overrides.is_some());
assert_eq!(context.metadata.tags.len(), 2);
}
#[test]
fn test_context_inheritance_setup() {
let base = ExecutionContext::new("base", "Base Context")
.with_environment(
EnvironmentConfig::new()
.with_var("BASE_VAR", "base_value"),
);
let child = ExecutionContext::inheriting("child", "Child Context", "base")
.with_environment(
EnvironmentConfig::new()
.with_var("CHILD_VAR", "child_value"),
);
assert!(!base.has_parent());
assert!(child.has_parent());
assert_eq!(child.inherits_from, Some("base".to_string()));
}
#[test]
fn test_full_serialization_roundtrip() {
let context = ExecutionContext::new("roundtrip-test", "Roundtrip Test")
.with_mount(Mount::directory("data", "/host", "/container"))
.with_environment(
EnvironmentConfig::new()
.with_var("KEY", "value"),
)
.with_secrets(
SecretsConfig::new()
.with_required_env_secret("secret", "SECRET_VAR", "A secret"),
)
.with_resources(
ResourceConfig::new()
.with_memory_limit("512m"),
);
let json = serde_json::to_string_pretty(&context).unwrap();
let from_json: ExecutionContext = serde_json::from_str(&json).unwrap();
assert_eq!(context.id, from_json.id);
assert_eq!(context.mounts.len(), from_json.mounts.len());
let toml_str = toml::to_string_pretty(&context).unwrap();
let from_toml: ExecutionContext = toml::from_str(&toml_str).unwrap();
assert_eq!(context.id, from_toml.id);
assert_eq!(context.mounts.len(), from_toml.mounts.len());
}
}