docker_wrapper/command/network/
connect.rs1use crate::command::{CommandExecutor, CommandOutput, DockerCommand};
4use crate::error::Result;
5use async_trait::async_trait;
6
7#[derive(Debug, Clone)]
9pub struct NetworkConnectCommand {
10 network: String,
12 container: String,
14 ipv4: Option<String>,
16 ipv6: Option<String>,
18 alias: Vec<String>,
20 link: Vec<String>,
22 link_local_ip: Vec<String>,
24 driver_opt: Vec<(String, String)>,
26 pub executor: CommandExecutor,
28}
29
30impl NetworkConnectCommand {
31 #[must_use]
33 pub fn new(network: impl Into<String>, container: impl Into<String>) -> Self {
34 Self {
35 network: network.into(),
36 container: container.into(),
37 ipv4: None,
38 ipv6: None,
39 alias: Vec::new(),
40 link: Vec::new(),
41 link_local_ip: Vec::new(),
42 driver_opt: Vec::new(),
43 executor: CommandExecutor::new(),
44 }
45 }
46
47 #[must_use]
49 pub fn ipv4(mut self, ip: impl Into<String>) -> Self {
50 self.ipv4 = Some(ip.into());
51 self
52 }
53
54 #[must_use]
56 pub fn ipv6(mut self, ip: impl Into<String>) -> Self {
57 self.ipv6 = Some(ip.into());
58 self
59 }
60
61 #[must_use]
63 pub fn alias(mut self, alias: impl Into<String>) -> Self {
64 self.alias.push(alias.into());
65 self
66 }
67
68 #[must_use]
70 pub fn link(mut self, container: impl Into<String>) -> Self {
71 self.link.push(container.into());
72 self
73 }
74
75 #[must_use]
77 pub fn link_local_ip(mut self, ip: impl Into<String>) -> Self {
78 self.link_local_ip.push(ip.into());
79 self
80 }
81
82 #[must_use]
84 pub fn driver_opt(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
85 self.driver_opt.push((key.into(), value.into()));
86 self
87 }
88
89 pub async fn run(&self) -> Result<NetworkConnectResult> {
95 self.execute().await.map(NetworkConnectResult::from)
96 }
97}
98
99#[async_trait]
100impl DockerCommand for NetworkConnectCommand {
101 type Output = CommandOutput;
102
103 fn build_command_args(&self) -> Vec<String> {
104 let mut args = vec!["network".to_string(), "connect".to_string()];
105
106 if let Some(ref ip) = self.ipv4 {
107 args.push("--ip".to_string());
108 args.push(ip.clone());
109 }
110
111 if let Some(ref ip) = self.ipv6 {
112 args.push("--ip6".to_string());
113 args.push(ip.clone());
114 }
115
116 for alias in &self.alias {
117 args.push("--alias".to_string());
118 args.push(alias.clone());
119 }
120
121 for link in &self.link {
122 args.push("--link".to_string());
123 args.push(link.clone());
124 }
125
126 for ip in &self.link_local_ip {
127 args.push("--link-local-ip".to_string());
128 args.push(ip.clone());
129 }
130
131 for (key, value) in &self.driver_opt {
132 args.push("--driver-opt".to_string());
133 args.push(format!("{key}={value}"));
134 }
135
136 args.push(self.network.clone());
137 args.push(self.container.clone());
138 args.extend(self.executor.raw_args.clone());
139 args
140 }
141
142 fn get_executor(&self) -> &CommandExecutor {
143 &self.executor
144 }
145
146 fn get_executor_mut(&mut self) -> &mut CommandExecutor {
147 &mut self.executor
148 }
149
150 async fn execute(&self) -> Result<Self::Output> {
151 let args = self.build_command_args();
152 let command_name = args[0].clone();
153 let command_args = args[1..].to_vec();
154 self.executor
155 .execute_command(&command_name, command_args)
156 .await
157 }
158}
159
160#[derive(Debug, Clone)]
162pub struct NetworkConnectResult {
163 pub raw_output: CommandOutput,
165}
166
167impl From<CommandOutput> for NetworkConnectResult {
168 fn from(output: CommandOutput) -> Self {
169 Self { raw_output: output }
170 }
171}
172
173impl NetworkConnectResult {
174 #[must_use]
176 pub fn is_success(&self) -> bool {
177 self.raw_output.success
178 }
179}
180
181#[cfg(test)]
182mod tests {
183 use super::*;
184
185 #[test]
186 fn test_network_connect_basic() {
187 let cmd = NetworkConnectCommand::new("my-network", "my-container");
188 let args = cmd.build_command_args();
189 assert_eq!(
190 args,
191 vec!["network", "connect", "my-network", "my-container"]
192 );
193 }
194
195 #[test]
196 fn test_network_connect_with_ip() {
197 let cmd = NetworkConnectCommand::new("my-network", "my-container").ipv4("172.20.0.10");
198 let args = cmd.build_command_args();
199 assert_eq!(
200 args,
201 vec![
202 "network",
203 "connect",
204 "--ip",
205 "172.20.0.10",
206 "my-network",
207 "my-container"
208 ]
209 );
210 }
211
212 #[test]
213 fn test_network_connect_with_alias() {
214 let cmd = NetworkConnectCommand::new("my-network", "my-container")
215 .alias("db")
216 .alias("database");
217 let args = cmd.build_command_args();
218 assert!(args.contains(&"--alias".to_string()));
219 assert!(args.contains(&"db".to_string()));
220 assert!(args.contains(&"database".to_string()));
221 }
222}