forked from containers/netavark
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathplugin.rs
130 lines (112 loc) · 3.74 KB
/
plugin.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
use std::{collections::HashMap, env, error::Error, io};
use serde::Serialize;
use crate::{error, network::types};
pub const API_VERSION: &str = "1.0.0";
// create new boxed error with string error message, also accepts format!() style arguments
#[macro_export]
macro_rules! new_error {
($msg:ident) => {
Box::new(std::io::Error::new(std::io::ErrorKind::Other, $msg))
};
($($arg:tt)*) => {{
Box::new(std::io::Error::new(std::io::ErrorKind::Other, format!($($arg)*)))
}};
}
/// Contains info about this plugin
#[derive(Serialize)]
pub struct Info {
/// The version of this plugin.
version: String,
// The api version for the netavark plugin API.
api_version: String,
/// Optional fields you want to be displayed for the info command
#[serde(flatten)]
extra_info: Option<HashMap<String, String>>,
}
impl Info {
pub fn new(
version: String,
api_version: String,
extra_info: Option<HashMap<String, String>>,
) -> Self {
Self {
version,
api_version,
extra_info,
}
}
}
/// Define the plugin functions
pub trait Plugin {
// create a network config
fn create(&self, network: types::Network) -> Result<types::Network, Box<dyn Error>>;
/// set up the network configuration
fn setup(
&self,
netns: String,
opts: types::NetworkPluginExec,
) -> Result<types::StatusBlock, Box<dyn Error>>;
/// tear down the network configuration
fn teardown(&self, netns: String, opts: types::NetworkPluginExec)
-> Result<(), Box<dyn Error>>;
}
pub struct PluginExec<P: Plugin> {
plugin: P,
info: Info,
}
impl<P: Plugin> PluginExec<P> {
pub fn new(plugin: P, info: Info) -> Self {
PluginExec { plugin, info }
}
pub fn exec(&self) {
match self.inner_exec() {
Ok(_) => {}
Err(err) => {
let e = error::JsonError {
error: err.to_string(),
};
serde_json::to_writer(io::stdout(), &e)
.unwrap_or_else(|e| println!("failed to write json error: {e}: {err}"));
std::process::exit(1);
}
};
}
fn inner_exec(&self) -> Result<(), Box<dyn Error>> {
let mut args = env::args();
args.next()
.ok_or_else(|| new_error!("zero arguments given"))?;
// match subcommand
match args.next().as_deref() {
Some("create") => {
let mut network = serde_json::from_reader(io::stdin())?;
network = self.plugin.create(network)?;
serde_json::to_writer(io::stdout(), &network)?;
}
Some("setup") => {
let netns = args
.next()
.ok_or_else(|| new_error!("netns path argument is missing"))?;
let opts = serde_json::from_reader(io::stdin())?;
let status_block = self.plugin.setup(netns, opts)?;
serde_json::to_writer(io::stdout(), &status_block)?;
}
Some("teardown") => {
let netns = args
.next()
.ok_or_else(|| new_error!("netns path argument is missing"))?;
let opts = serde_json::from_reader(io::stdin())?;
self.plugin.teardown(netns, opts)?;
}
Some("info") => self.print_info()?,
Some(unknown) => {
return Err(new_error!("unknown subcommand: {}", unknown));
}
None => self.print_info()?,
};
Ok(())
}
fn print_info(&self) -> Result<(), Box<dyn Error>> {
serde_json::to_writer(io::stdout(), &self.info)?;
Ok(())
}
}