use crate::{
error::EnvError, operator::OperatorInput, operator::OperatorOutput, secret::SecretSource,
};
use async_trait::async_trait;
use serde::{Deserialize, Serialize};
#[async_trait]
pub trait Environment: Send + Sync {
async fn run(
&self,
input: OperatorInput,
spec: &EnvironmentSpec,
) -> Result<OperatorOutput, EnvError>;
}
#[non_exhaustive]
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct EnvironmentSpec {
#[serde(default)]
pub isolation: Vec<IsolationBoundary>,
#[serde(default)]
pub credentials: Vec<CredentialRef>,
pub resources: Option<ResourceLimits>,
pub network: Option<NetworkPolicy>,
}
#[non_exhaustive]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum IsolationBoundary {
Process,
Container {
image: Option<String>,
},
Gvisor,
MicroVm,
Wasm {
runtime: Option<String>,
},
NetworkPolicy {
rules: Vec<NetworkRule>,
},
Custom {
boundary_type: String,
config: serde_json::Value,
},
}
#[non_exhaustive]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CredentialRef {
pub name: String,
pub source: SecretSource,
pub injection: CredentialInjection,
}
#[non_exhaustive]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum CredentialInjection {
EnvVar {
var_name: String,
},
File {
path: String,
},
Sidecar,
}
#[non_exhaustive]
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct ResourceLimits {
pub cpu: Option<String>,
pub memory: Option<String>,
pub disk: Option<String>,
pub gpu: Option<String>,
}
#[non_exhaustive]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NetworkPolicy {
pub default: NetworkAction,
pub rules: Vec<NetworkRule>,
}
#[non_exhaustive]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NetworkRule {
pub destination: String,
pub port: Option<u16>,
pub action: NetworkAction,
}
#[non_exhaustive]
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "snake_case")]
pub enum NetworkAction {
Allow,
Deny,
}
impl CredentialRef {
pub fn new(
name: impl Into<String>,
source: SecretSource,
injection: CredentialInjection,
) -> Self {
Self {
name: name.into(),
source,
injection,
}
}
}
impl NetworkPolicy {
pub fn new(default: NetworkAction, rules: Vec<NetworkRule>) -> Self {
Self { default, rules }
}
}
impl NetworkRule {
pub fn new(destination: impl Into<String>, action: NetworkAction) -> Self {
Self {
destination: destination.into(),
port: None,
action,
}
}
}