use crate::command::{CommandExecutor, DockerCommand};
use crate::error::Result;
use async_trait::async_trait;
#[derive(Debug, Clone)]
pub struct SwarmUpdateResult {
pub success: bool,
pub output: String,
}
#[derive(Debug, Clone, Default)]
pub struct SwarmUpdateCommand {
autolock: Option<bool>,
cert_expiry: Option<String>,
dispatcher_heartbeat: Option<String>,
external_ca: Option<String>,
max_snapshots: Option<u32>,
snapshot_interval: Option<u32>,
task_history_limit: Option<i32>,
pub executor: CommandExecutor,
}
impl SwarmUpdateCommand {
#[must_use]
pub fn new() -> Self {
Self::default()
}
#[must_use]
pub fn autolock(mut self, enabled: bool) -> Self {
self.autolock = Some(enabled);
self
}
#[must_use]
pub fn cert_expiry(mut self, expiry: impl Into<String>) -> Self {
self.cert_expiry = Some(expiry.into());
self
}
#[must_use]
pub fn dispatcher_heartbeat(mut self, heartbeat: impl Into<String>) -> Self {
self.dispatcher_heartbeat = Some(heartbeat.into());
self
}
#[must_use]
pub fn external_ca(mut self, spec: impl Into<String>) -> Self {
self.external_ca = Some(spec.into());
self
}
#[must_use]
pub fn max_snapshots(mut self, count: u32) -> Self {
self.max_snapshots = Some(count);
self
}
#[must_use]
pub fn snapshot_interval(mut self, interval: u32) -> Self {
self.snapshot_interval = Some(interval);
self
}
#[must_use]
pub fn task_history_limit(mut self, limit: i32) -> Self {
self.task_history_limit = Some(limit);
self
}
fn build_args(&self) -> Vec<String> {
let mut args = vec!["swarm".to_string(), "update".to_string()];
if let Some(enabled) = self.autolock {
args.push("--autolock".to_string());
args.push(enabled.to_string());
}
if let Some(ref expiry) = self.cert_expiry {
args.push("--cert-expiry".to_string());
args.push(expiry.clone());
}
if let Some(ref heartbeat) = self.dispatcher_heartbeat {
args.push("--dispatcher-heartbeat".to_string());
args.push(heartbeat.clone());
}
if let Some(ref spec) = self.external_ca {
args.push("--external-ca".to_string());
args.push(spec.clone());
}
if let Some(count) = self.max_snapshots {
args.push("--max-snapshots".to_string());
args.push(count.to_string());
}
if let Some(interval) = self.snapshot_interval {
args.push("--snapshot-interval".to_string());
args.push(interval.to_string());
}
if let Some(limit) = self.task_history_limit {
args.push("--task-history-limit".to_string());
args.push(limit.to_string());
}
args
}
}
#[async_trait]
impl DockerCommand for SwarmUpdateCommand {
type Output = SwarmUpdateResult;
fn get_executor(&self) -> &CommandExecutor {
&self.executor
}
fn get_executor_mut(&mut self) -> &mut CommandExecutor {
&mut self.executor
}
fn build_command_args(&self) -> Vec<String> {
self.build_args()
}
async fn execute(&self) -> Result<Self::Output> {
let args = self.build_args();
let output = self.execute_command(args).await?;
Ok(SwarmUpdateResult {
success: true,
output: output.stdout,
})
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_swarm_update_basic() {
let cmd = SwarmUpdateCommand::new();
let args = cmd.build_args();
assert_eq!(args, vec!["swarm", "update"]);
}
#[test]
fn test_swarm_update_autolock_enable() {
let cmd = SwarmUpdateCommand::new().autolock(true);
let args = cmd.build_args();
assert!(args.contains(&"--autolock".to_string()));
assert!(args.contains(&"true".to_string()));
}
#[test]
fn test_swarm_update_autolock_disable() {
let cmd = SwarmUpdateCommand::new().autolock(false);
let args = cmd.build_args();
assert!(args.contains(&"--autolock".to_string()));
assert!(args.contains(&"false".to_string()));
}
#[test]
fn test_swarm_update_cert_expiry() {
let cmd = SwarmUpdateCommand::new().cert_expiry("90d");
let args = cmd.build_args();
assert!(args.contains(&"--cert-expiry".to_string()));
assert!(args.contains(&"90d".to_string()));
}
#[test]
fn test_swarm_update_all_options() {
let cmd = SwarmUpdateCommand::new()
.autolock(true)
.cert_expiry("90d")
.dispatcher_heartbeat("5s")
.external_ca("protocol=cfssl,url=https://ca.example.com")
.max_snapshots(5)
.snapshot_interval(10000)
.task_history_limit(10);
let args = cmd.build_args();
assert!(args.contains(&"--autolock".to_string()));
assert!(args.contains(&"--cert-expiry".to_string()));
assert!(args.contains(&"--dispatcher-heartbeat".to_string()));
assert!(args.contains(&"--external-ca".to_string()));
assert!(args.contains(&"--max-snapshots".to_string()));
assert!(args.contains(&"--snapshot-interval".to_string()));
assert!(args.contains(&"--task-history-limit".to_string()));
}
}