docker_wrapper/command/context/
create.rs1use crate::command::{CommandExecutor, CommandOutput, DockerCommand};
4use crate::error::Result;
5use async_trait::async_trait;
6
7#[derive(Debug, Clone)]
27pub struct ContextCreateCommand {
28 name: String,
30 description: Option<String>,
32 docker_host: Option<String>,
34 default_stack_orchestrator: Option<String>,
36 docker_api_endpoint: Option<String>,
38 kubernetes_config_file: Option<String>,
40 kubernetes_context: Option<String>,
42 kubernetes_namespace: Option<String>,
44 kubernetes_api_endpoint: Option<String>,
46 from: Option<String>,
48 pub executor: CommandExecutor,
50}
51
52impl ContextCreateCommand {
53 #[must_use]
55 pub fn new(name: impl Into<String>) -> Self {
56 Self {
57 name: name.into(),
58 description: None,
59 docker_host: None,
60 default_stack_orchestrator: None,
61 docker_api_endpoint: None,
62 kubernetes_config_file: None,
63 kubernetes_context: None,
64 kubernetes_namespace: None,
65 kubernetes_api_endpoint: None,
66 from: None,
67 executor: CommandExecutor::new(),
68 }
69 }
70
71 #[must_use]
73 pub fn description(mut self, desc: impl Into<String>) -> Self {
74 self.description = Some(desc.into());
75 self
76 }
77
78 #[must_use]
80 pub fn docker_host(mut self, host: impl Into<String>) -> Self {
81 self.docker_host = Some(host.into());
82 self
83 }
84
85 #[must_use]
87 pub fn default_stack_orchestrator(mut self, orchestrator: impl Into<String>) -> Self {
88 self.default_stack_orchestrator = Some(orchestrator.into());
89 self
90 }
91
92 #[must_use]
94 pub fn docker_api_endpoint(mut self, endpoint: impl Into<String>) -> Self {
95 self.docker_api_endpoint = Some(endpoint.into());
96 self
97 }
98
99 #[must_use]
101 pub fn kubernetes_config_file(mut self, file: impl Into<String>) -> Self {
102 self.kubernetes_config_file = Some(file.into());
103 self
104 }
105
106 #[must_use]
108 pub fn kubernetes_context(mut self, context: impl Into<String>) -> Self {
109 self.kubernetes_context = Some(context.into());
110 self
111 }
112
113 #[must_use]
115 pub fn kubernetes_namespace(mut self, namespace: impl Into<String>) -> Self {
116 self.kubernetes_namespace = Some(namespace.into());
117 self
118 }
119
120 #[must_use]
122 pub fn kubernetes_api_endpoint(mut self, endpoint: impl Into<String>) -> Self {
123 self.kubernetes_api_endpoint = Some(endpoint.into());
124 self
125 }
126
127 #[must_use]
129 pub fn from(mut self, context: impl Into<String>) -> Self {
130 self.from = Some(context.into());
131 self
132 }
133}
134
135#[async_trait]
136impl DockerCommand for ContextCreateCommand {
137 type Output = CommandOutput;
138
139 fn get_executor(&self) -> &CommandExecutor {
140 &self.executor
141 }
142
143 fn get_executor_mut(&mut self) -> &mut CommandExecutor {
144 &mut self.executor
145 }
146
147 fn build_command_args(&self) -> Vec<String> {
148 let mut args = vec!["context".to_string(), "create".to_string()];
149
150 if let Some(desc) = &self.description {
151 args.push("--description".to_string());
152 args.push(desc.clone());
153 }
154
155 if let Some(host) = &self.docker_host {
156 args.push("--docker".to_string());
157 args.push(format!("host={host}"));
158 }
159
160 if let Some(orchestrator) = &self.default_stack_orchestrator {
161 args.push("--default-stack-orchestrator".to_string());
162 args.push(orchestrator.clone());
163 }
164
165 if let Some(endpoint) = &self.docker_api_endpoint {
166 args.push("--docker".to_string());
167 args.push(format!("api-endpoint={endpoint}"));
168 }
169
170 if let Some(file) = &self.kubernetes_config_file {
171 args.push("--kubernetes".to_string());
172 args.push(format!("config-file={file}"));
173 }
174
175 if let Some(context) = &self.kubernetes_context {
176 args.push("--kubernetes".to_string());
177 args.push(format!("context={context}"));
178 }
179
180 if let Some(namespace) = &self.kubernetes_namespace {
181 args.push("--kubernetes".to_string());
182 args.push(format!("namespace={namespace}"));
183 }
184
185 if let Some(endpoint) = &self.kubernetes_api_endpoint {
186 args.push("--kubernetes".to_string());
187 args.push(format!("api-endpoint={endpoint}"));
188 }
189
190 if let Some(from) = &self.from {
191 args.push("--from".to_string());
192 args.push(from.clone());
193 }
194
195 args.push(self.name.clone());
196
197 args.extend(self.executor.raw_args.clone());
198 args
199 }
200
201 async fn execute(&self) -> Result<Self::Output> {
202 let args = self.build_command_args();
203 self.execute_command(args).await
204 }
205}
206
207#[cfg(test)]
208mod tests {
209 use super::*;
210
211 #[test]
212 fn test_context_create_basic() {
213 let cmd = ContextCreateCommand::new("test-context");
214 let args = cmd.build_command_args();
215 assert_eq!(args[0], "context");
216 assert_eq!(args[1], "create");
217 assert!(args.contains(&"test-context".to_string()));
218 }
219
220 #[test]
221 fn test_context_create_with_description() {
222 let cmd =
223 ContextCreateCommand::new("test-context").description("Test context for development");
224 let args = cmd.build_command_args();
225 assert!(args.contains(&"--description".to_string()));
226 assert!(args.contains(&"Test context for development".to_string()));
227 }
228
229 #[test]
230 fn test_context_create_with_docker_host() {
231 let cmd = ContextCreateCommand::new("remote").docker_host("ssh://user@remote-host");
232 let args = cmd.build_command_args();
233 assert!(args.contains(&"--docker".to_string()));
234 assert!(args.contains(&"host=ssh://user@remote-host".to_string()));
235 }
236
237 #[test]
238 fn test_context_create_from_existing() {
239 let cmd = ContextCreateCommand::new("new-context").from("default");
240 let args = cmd.build_command_args();
241 assert!(args.contains(&"--from".to_string()));
242 assert!(args.contains(&"default".to_string()));
243 }
244}