docker_wrapper/command/swarm/
unlock_key.rs1use crate::command::{CommandExecutor, CommandOutput, DockerCommand};
4use crate::error::Result;
5use async_trait::async_trait;
6
7#[derive(Debug, Clone)]
9pub struct SwarmUnlockKeyResult {
10 pub key: Option<String>,
12 pub output: String,
14}
15
16impl SwarmUnlockKeyResult {
17 fn parse(output: &CommandOutput, quiet: bool) -> Self {
19 let stdout = output.stdout.trim();
20
21 let key = if quiet {
22 Some(stdout.to_string())
24 } else {
25 let mut found_key = None;
33 for line in stdout.lines() {
34 let trimmed = line.trim();
35 if trimmed.starts_with("SWMKEY-") {
36 found_key = Some(trimmed.to_string());
37 break;
38 }
39 }
40 found_key
41 };
42
43 Self {
44 key,
45 output: stdout.to_string(),
46 }
47 }
48}
49
50#[derive(Debug, Clone, Default)]
54pub struct SwarmUnlockKeyCommand {
55 quiet: bool,
57 rotate: bool,
59 pub executor: CommandExecutor,
61}
62
63impl SwarmUnlockKeyCommand {
64 #[must_use]
66 pub fn new() -> Self {
67 Self::default()
68 }
69
70 #[must_use]
72 pub fn quiet(mut self) -> Self {
73 self.quiet = true;
74 self
75 }
76
77 #[must_use]
79 pub fn rotate(mut self) -> Self {
80 self.rotate = true;
81 self
82 }
83
84 fn build_args(&self) -> Vec<String> {
86 let mut args = vec!["swarm".to_string(), "unlock-key".to_string()];
87
88 if self.quiet {
89 args.push("--quiet".to_string());
90 }
91
92 if self.rotate {
93 args.push("--rotate".to_string());
94 }
95
96 args
97 }
98}
99
100#[async_trait]
101impl DockerCommand for SwarmUnlockKeyCommand {
102 type Output = SwarmUnlockKeyResult;
103
104 fn get_executor(&self) -> &CommandExecutor {
105 &self.executor
106 }
107
108 fn get_executor_mut(&mut self) -> &mut CommandExecutor {
109 &mut self.executor
110 }
111
112 fn build_command_args(&self) -> Vec<String> {
113 self.build_args()
114 }
115
116 async fn execute(&self) -> Result<Self::Output> {
117 let args = self.build_args();
118 let output = self.execute_command(args).await?;
119 Ok(SwarmUnlockKeyResult::parse(&output, self.quiet))
120 }
121}
122
123#[cfg(test)]
124mod tests {
125 use super::*;
126
127 #[test]
128 fn test_swarm_unlock_key_basic() {
129 let cmd = SwarmUnlockKeyCommand::new();
130 let args = cmd.build_args();
131 assert_eq!(args, vec!["swarm", "unlock-key"]);
132 }
133
134 #[test]
135 fn test_swarm_unlock_key_quiet() {
136 let cmd = SwarmUnlockKeyCommand::new().quiet();
137 let args = cmd.build_args();
138 assert!(args.contains(&"--quiet".to_string()));
139 }
140
141 #[test]
142 fn test_swarm_unlock_key_rotate() {
143 let cmd = SwarmUnlockKeyCommand::new().rotate();
144 let args = cmd.build_args();
145 assert!(args.contains(&"--rotate".to_string()));
146 }
147
148 #[test]
149 fn test_swarm_unlock_key_all_options() {
150 let cmd = SwarmUnlockKeyCommand::new().quiet().rotate();
151 let args = cmd.build_args();
152 assert_eq!(args, vec!["swarm", "unlock-key", "--quiet", "--rotate"]);
153 }
154}