1use serde::{Deserialize, Serialize};
3
4use super::CNIError;
5
6use super::exec::RawExec;
7use crate::libcni::exec::{Exec, ExecArgs};
8use crate::libcni::result::result100;
9use crate::libcni::result::{APIResult, ResultCNI};
10use crate::libcni::types::NetworkConfig;
11use std::collections::HashMap;
12pub trait CNI {
13 fn add_network_list(
14 &self,
15 net: NetworkConfigList,
16 rt: RuntimeConf,
17 ) -> ResultCNI<Box<dyn APIResult>>;
18
19 fn check_network_list(&self, net: NetworkConfigList, rt: RuntimeConf) -> ResultCNI<()>;
20
21 fn delete_network_list(&self, net: NetworkConfigList, rt: RuntimeConf) -> ResultCNI<()>;
22
23 fn get_network_list_cached_result(
24 &self,
25 net: NetworkConfigList,
26 rt: RuntimeConf,
27 ) -> ResultCNI<Box<dyn APIResult>>;
28
29 fn add_network(
30 &self,
31 name: String,
32 cni_version: String,
33 net: NetworkConfig,
34 prev_result: Option<Box<dyn APIResult>>,
35 rt: RuntimeConf,
36 ) -> ResultCNI<Box<dyn APIResult>>;
37
38 fn check_network(
39 &self,
40 name: String,
41 cni_version: String,
42 prev_result: Option<Box<dyn APIResult>>,
43 net: NetworkConfig,
44 rt: RuntimeConf,
45 ) -> ResultCNI<()>;
46 fn delete_network(
47 &self,
48 name: String,
49 cni_version: String,
50
51 net: NetworkConfig,
52 rt: RuntimeConf,
53 ) -> ResultCNI<()>;
54
55 fn get_network_cached_result(
56 &self,
57 net: NetworkConfig,
58 rt: RuntimeConf,
59 ) -> ResultCNI<Box<dyn APIResult>>;
60
61 fn get_network_cached_config(
62 &self,
63 net: NetworkConfig,
64 rt: RuntimeConf,
65 ) -> ResultCNI<(Vec<u8>, RuntimeConf)>;
66
67 fn validate_network_list(&self, net: NetworkConfigList) -> ResultCNI<Vec<String>>;
68
69 fn validate_network(&self, net: NetworkConfig) -> ResultCNI<Vec<String>>;
70}
71
72#[derive(Default, Clone, Serialize, Deserialize)]
73pub struct NetworkConfigList {
74 pub name: String,
75 pub cni_version: String,
76 pub disable_check: bool,
77 pub plugins: Vec<NetworkConfig>,
78 pub bytes: Vec<u8>,
79}
80
81#[derive(Default, Clone)]
82pub struct RuntimeConf {
83 pub container_id: String,
84 pub net_ns: String,
85 pub if_name: String,
86 pub args: Vec<[String; 2]>,
87 pub capability_args: HashMap<String, String>,
88 pub cache_dir: String,
89}
90#[derive(Default)]
91pub struct CNIConfig {
92 pub path: Vec<String>,
93 pub exec: RawExec,
94 pub cache_dir: String,
95}
96
97impl CNIConfig {
98 fn build_new_config(
109 &self,
110 name: String,
111 cni_version: String,
112 orig: &NetworkConfig,
113 prev_result: Option<Box<dyn APIResult>>,
114 _rt: &RuntimeConf,
115 ) -> Result<NetworkConfig, String> {
116 let mut json_object = json::parse(String::from_utf8_lossy(&orig.bytes).as_ref()).unwrap();
117
118 json_object.insert("name", name).unwrap();
119 json_object.insert("cniVersion", cni_version).unwrap();
120
121 if let Some(prev_result) = prev_result {
122 json_object
123 .insert("prevResult", prev_result.get_json())
124 .unwrap();
125 }
126 let new_bytes = json_object.dump().as_bytes().to_vec();
127 Ok(NetworkConfig {
129 network: serde_json::from_slice(&new_bytes).unwrap(),
130 bytes: new_bytes,
131 })
132 }
133}
134
135impl CNI for CNIConfig {
136 fn add_network_list(
137 &self,
138 net: NetworkConfigList,
139 rt: RuntimeConf,
140 ) -> ResultCNI<Box<dyn APIResult>> {
141 let mut r = None;
142
143 for x in net.plugins {
144 let r1 = self.add_network(
145 net.name.clone(),
146 net.cni_version.clone(),
147 x.clone(),
148 r,
149 rt.clone(),
150 )?;
151 r = Some(r1);
152 }
155 match r {
156 Some(r) => Ok(r),
157 None => Err(Box::new(CNIError::ExecuteError("()".to_string()))),
158 }
159 }
160
161 fn check_network_list(&self, net: NetworkConfigList, rt: RuntimeConf) -> ResultCNI<()> {
162 net.plugins.into_iter().try_for_each(|x| {
163 self.check_network(
164 net.name.clone(),
165 net.cni_version.clone(),
166 None,
167 x,
168 rt.clone(),
169 )
170 })?;
171 Ok(())
172 }
173
174 fn delete_network_list(&self, net: NetworkConfigList, rt: RuntimeConf) -> ResultCNI<()> {
175 net.plugins.into_iter().try_for_each(|x| {
176 self.delete_network(net.name.clone(), net.cni_version.clone(), x, rt.clone())
177 })?;
178 Ok(())
179 }
180
181 fn get_network_list_cached_result(
182 &self,
183 _net: NetworkConfigList,
184 _rt: RuntimeConf,
185 ) -> ResultCNI<Box<dyn APIResult>> {
186 todo!()
187 }
188
189 fn add_network(
190 &self,
191 name: String,
192 cni_version: String,
193 net: NetworkConfig,
194 prev_result: Option<Box<dyn APIResult>>,
195 rt: RuntimeConf,
196 ) -> ResultCNI<Box<dyn APIResult>> {
197 let plugin_path = self
199 .exec
200 .find_in_path(net.network._type.clone(), self.path.clone())
201 .unwrap();
202
203 let environ = ExecArgs {
204 command: "ADD".to_string(),
205 containerd_id: rt.container_id.clone(),
206 netns: rt.net_ns.clone(),
207 plugin_args: rt.args.clone(),
208 plugin_args_str: String::default(),
209 ifname: rt.if_name.clone(),
210 path: self.path[0].clone(),
211 };
212
213 let new_conf = self.build_new_config(name, cni_version, &net, prev_result, &rt);
214 if let Ok(new_conf) = new_conf {
215 let r_result =
216 self.exec
217 .exec_plugins(plugin_path, &new_conf.bytes, environ.to_env())?;
218 let pre_result_json: result100::Result = serde_json::from_slice(&r_result)
219 .map_err(|e| e.to_string())
220 .unwrap_or_else(|e| {
221 println!("Failed to parse JSON: {}", e);
222 result100::Result::default()
223 });
224 println!("cni_result {}", pre_result_json.get_json());
225 return Ok(Box::new(pre_result_json));
226 }
227 Err(Box::new(CNIError::ExecuteError("()".to_string())))
228 }
229
230 fn check_network(
231 &self,
232 name: String,
233 cni_version: String,
234 prev_result: Option<Box<dyn APIResult>>,
235 net: NetworkConfig,
236 rt: RuntimeConf,
237 ) -> ResultCNI<()> {
238 let plugin_path = self
239 .exec
240 .find_in_path(net.network._type.clone(), self.path.clone())
241 .unwrap();
242 let environ = ExecArgs {
243 command: "CHECK".to_string(),
244 containerd_id: rt.container_id.clone(),
245 netns: rt.net_ns.clone(),
246 plugin_args: rt.args.clone(),
247 plugin_args_str: String::default(),
248 ifname: rt.if_name.clone(),
249 path: self.path[0].clone(),
250 };
251 let new_conf = self.build_new_config(name, cni_version, &net, prev_result, &rt);
252 if let Ok(new_conf) = new_conf {
253 self.exec
254 .exec_plugins(plugin_path, &new_conf.bytes, environ.to_env())?;
255 }
256 Ok(())
257 }
258 fn delete_network(
259 &self,
260 name: String,
261 cni_version: String,
262 net: NetworkConfig,
263 rt: RuntimeConf,
264 ) -> ResultCNI<()> {
265 let environ = ExecArgs {
266 command: "DEL".to_string(),
267 containerd_id: rt.container_id,
268 netns: rt.net_ns,
269 plugin_args: rt.args,
270 plugin_args_str: String::default(),
271 ifname: rt.if_name,
272 path: self.path[0].clone(),
273 };
274
275 let plugin_path = self
276 .exec
277 .find_in_path(net.network._type, self.path.clone())
278 .unwrap();
279
280 let mut json_object = json::parse(String::from_utf8_lossy(&net.bytes).as_ref()).unwrap();
282 json_object.insert("name", name).unwrap();
283 json_object.insert("cniVersion", cni_version).unwrap();
284 let new_stdin_data = json_object.dump().as_bytes().to_vec();
285
286 self.exec
287 .exec_plugins(plugin_path, &new_stdin_data, environ.to_env())?;
288
289 Ok(())
290 }
291
292 fn get_network_cached_result(
293 &self,
294 _net: NetworkConfig,
295 _rt: RuntimeConf,
296 ) -> ResultCNI<Box<dyn APIResult>> {
297 todo!()
300 }
301
302 fn get_network_cached_config(
303 &self,
304 _net: NetworkConfig,
305 _rt: RuntimeConf,
306 ) -> ResultCNI<(Vec<u8>, RuntimeConf)> {
307 todo!()
308 }
309
310 fn validate_network_list(&self, _net: NetworkConfigList) -> ResultCNI<Vec<String>> {
311 todo!()
312 }
313
314 fn validate_network(&self, _net: NetworkConfig) -> ResultCNI<Vec<String>> {
315 todo!()
316 }
317}