use serde::{Deserialize, Serialize};
use zeroize::Zeroizing;
use crate::domain::EnvVar;
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[cfg_attr(feature = "ts", derive(ts_rs::TS))]
pub struct SandboxModificationPatch {
#[serde(skip_serializing_if = "Option::is_none")]
pub cpus: Option<u8>,
#[serde(skip_serializing_if = "Option::is_none")]
pub max_cpus: Option<u8>,
#[serde(skip_serializing_if = "Option::is_none")]
pub memory_mib: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub max_memory_mib: Option<u32>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub env: Vec<EnvVar>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub env_remove: Vec<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub labels: Vec<(String, String)>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub labels_remove: Vec<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub workdir: Option<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub secrets: Vec<SecretModificationPatch>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub secrets_remove: Vec<String>,
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "ts", derive(ts_rs::TS))]
#[serde(rename_all = "snake_case")]
pub enum ModificationPolicy {
#[default]
NoRestart,
NextStart,
Restart,
}
#[derive(Clone, Default, Serialize, Deserialize)]
#[cfg_attr(feature = "ts", derive(ts_rs::TS))]
pub struct SecretModificationPatch {
pub name: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub source: Option<SecretSource>,
#[serde(default, skip_serializing_if = "String::is_empty")]
#[cfg_attr(feature = "ts", ts(type = "string"))]
pub value: Zeroizing<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub placeholder: Option<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub allowed_hosts: Vec<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "ts", derive(ts_rs::TS))]
#[serde(tag = "kind", rename_all = "snake_case")]
pub enum SecretSource {
Env {
var: String,
},
Store {
reference: String,
},
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "ts", derive(ts_rs::TS))]
pub struct SandboxModificationPlan {
pub sandbox: String,
pub status: String,
pub applied: bool,
pub policy: ModificationPolicy,
pub changes: Vec<PlannedChange>,
pub conflicts: Vec<ModificationConflict>,
pub warnings: Vec<ModificationWarning>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub resize_status: Vec<ResourceResizeStatus>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "ts", derive(ts_rs::TS))]
#[serde(tag = "kind", rename_all = "snake_case")]
pub enum PlannedChange {
Config(ConfigPlannedChange),
Secret(SecretPlannedChange),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "ts", derive(ts_rs::TS))]
pub struct ConfigPlannedChange {
pub field: String,
pub change: ChangeKind,
#[serde(skip_serializing_if = "Option::is_none")]
pub before: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub after: Option<String>,
pub disposition: ModificationDisposition,
#[serde(skip_serializing_if = "Option::is_none")]
pub reason: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "ts", derive(ts_rs::TS))]
pub struct SecretPlannedChange {
pub field: String,
pub name: String,
pub change: SecretChangeKind,
#[serde(skip_serializing_if = "Option::is_none")]
pub before_ref: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub after_ref: Option<String>,
pub disposition: ModificationDisposition,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub allow_hosts: Vec<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub reason: Option<String>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "ts", derive(ts_rs::TS))]
#[serde(rename_all = "lowercase")]
pub enum ChangeKind {
Added,
Updated,
Removed,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "ts", derive(ts_rs::TS))]
pub enum SecretChangeKind {
#[serde(rename = "added")]
Added,
#[serde(rename = "rotated")]
Rotated,
#[serde(rename = "removed")]
Removed,
#[serde(rename = "renamed")]
Renamed,
#[serde(rename = "hosts updated")]
HostsUpdated,
#[serde(rename = "placeholder updated")]
PlaceholderUpdated,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "ts", derive(ts_rs::TS))]
pub enum ModificationDisposition {
#[serde(rename = "live")]
Live,
#[serde(rename = "next start")]
NextStart,
#[serde(rename = "requires restart")]
RequiresRestart,
#[serde(rename = "unsupported")]
Unsupported,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "ts", derive(ts_rs::TS))]
pub struct ModificationConflict {
pub field: String,
pub message: String,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "ts", derive(ts_rs::TS))]
pub struct ModificationWarning {
pub field: String,
pub message: String,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "ts", derive(ts_rs::TS))]
#[serde(rename_all = "snake_case")]
pub enum ResourceKind {
Cpus,
Memory,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "ts", derive(ts_rs::TS))]
#[serde(rename_all = "kebab-case")]
pub enum ResourceConvergenceState {
Accepted,
Converging,
Applied,
GuestRefused,
Failed,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "ts", derive(ts_rs::TS))]
pub struct ResourceResizeStatus {
pub resource: ResourceKind,
pub requested: String,
pub actual: String,
pub enforced: String,
pub state: ResourceConvergenceState,
}
impl std::fmt::Debug for SecretModificationPatch {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("SecretModificationPatch")
.field("name", &self.name)
.field("source", &self.source)
.field("value", &"[REDACTED]")
.field("placeholder", &self.placeholder)
.field("allowed_hosts", &self.allowed_hosts)
.finish()
}
}