]>
Commit | Line | Data |
---|---|---|
bf78f708 DM |
1 | //! API Type Definitions |
2 | ||
e7cb4dc5 WB |
3 | use anyhow::bail; |
4 | use serde::{Deserialize, Serialize}; | |
4ebf0eab | 5 | |
6ef1b649 | 6 | use proxmox_schema::*; |
f28d9088 | 7 | |
6227654a DM |
8 | use pbs_api_types::StorageStatus; |
9 | ||
39c5db7f DM |
10 | mod acme; |
11 | pub use acme::*; | |
12 | ||
255f378a DM |
13 | // File names: may not contain slashes, may not start with "." |
14 | pub const FILENAME_FORMAT: ApiStringFormat = ApiStringFormat::VerifyFn(|name| { | |
15 | if name.starts_with('.') { | |
16 | bail!("file names may not start with '.'"); | |
17 | } | |
18 | if name.contains('/') { | |
19 | bail!("file names may not contain slashes"); | |
20 | } | |
21 | Ok(()) | |
22 | }); | |
23 | ||
fc189b19 | 24 | |
ff620a3d DM |
25 | // Regression tests |
26 | ||
dcb8db66 | 27 | #[test] |
ff329f97 | 28 | fn test_cert_fingerprint_schema() -> Result<(), anyhow::Error> { |
dcb8db66 | 29 | |
67a5cf47 | 30 | let schema = pbs_api_types::CERT_FINGERPRINT_SHA256_SCHEMA; |
dcb8db66 DM |
31 | |
32 | let invalid_fingerprints = [ | |
33 | "86:88:7c:be:26:77:a5:62:67:d9:06:f5:e4::61:3e:20:dc:cd:43:92:07:7f:fb:65:54:6c:ff:d2:96:36:f8", | |
34 | "88:7C:BE:26:77:a5:62:67:D9:06:f5:e4:14:61:3e:20:dc:cd:43:92:07:7f:fb:65:54:6c:ff:d2:96:36:f8", | |
35 | "86:88:7c:be:26:77:a5:62:67:d9:06:f5:e4::14:61:3e:20:dc:cd:43:92:07:7f:fb:65:54:6c:ff:d2:96:36:f8:ff", | |
36 | "XX:88:7c:be:26:77:a5:62:67:d9:06:f5:e4::14:61:3e:20:dc:cd:43:92:07:7f:fb:65:54:6c:ff:d2:96:36:f8", | |
37 | "86:88:Y4:be:26:77:a5:62:67:d9:06:f5:e4:14:61:3e:20:dc:cd:43:92:07:7f:fb:65:54:6c:ff:d2:96:36:f8", | |
38 | "86:88:0:be:26:77:a5:62:67:d9:06:f5:e4:14:61:3e:20:dc:cd:43:92:07:7f:fb:65:54:6c:ff:d2:96:36:f8", | |
39 | ]; | |
40 | ||
41 | for fingerprint in invalid_fingerprints.iter() { | |
3984a5fd | 42 | if parse_simple_value(fingerprint, &schema).is_ok() { |
add5861e | 43 | bail!("test fingerprint '{}' failed - got Ok() while exception an error.", fingerprint); |
dcb8db66 DM |
44 | } |
45 | } | |
46 | ||
47 | let valid_fingerprints = [ | |
48 | "86:88:7c:be:26:77:a5:62:67:d9:06:f5:e4:14:61:3e:20:dc:cd:43:92:07:7f:fb:65:54:6c:ff:d2:96:36:f8", | |
49 | "86:88:7C:BE:26:77:a5:62:67:D9:06:f5:e4:14:61:3e:20:dc:cd:43:92:07:7f:fb:65:54:6c:ff:d2:96:36:f8", | |
50 | ]; | |
51 | ||
52 | for fingerprint in valid_fingerprints.iter() { | |
53 | let v = match parse_simple_value(fingerprint, &schema) { | |
54 | Ok(v) => v, | |
55 | Err(err) => { | |
56 | bail!("unable to parse fingerprint '{}' - {}", fingerprint, err); | |
57 | } | |
58 | }; | |
59 | ||
60 | if v != serde_json::json!(fingerprint) { | |
61 | bail!("unable to parse fingerprint '{}' - got wrong value {:?}", fingerprint, v); | |
62 | } | |
63 | } | |
64 | ||
65 | Ok(()) | |
66 | } | |
67 | ||
ff620a3d | 68 | #[test] |
ff329f97 | 69 | fn test_proxmox_user_id_schema() -> Result<(), anyhow::Error> { |
67a5cf47 DM |
70 | |
71 | use pbs_api_types::Userid; | |
72 | ||
ff620a3d DM |
73 | let invalid_user_ids = [ |
74 | "x", // too short | |
75 | "xx", // too short | |
76 | "xxx", // no realm | |
77 | "xxx@", // no realm | |
78 | "xx x@test", // contains space | |
79 | "xx\nx@test", // contains control character | |
80 | "x:xx@test", // contains collon | |
81 | "xx/x@test", // contains slash | |
82 | "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx@test", // too long | |
83 | ]; | |
84 | ||
85 | for name in invalid_user_ids.iter() { | |
3984a5fd | 86 | if parse_simple_value(name, &Userid::API_SCHEMA).is_ok() { |
add5861e | 87 | bail!("test userid '{}' failed - got Ok() while exception an error.", name); |
ff620a3d DM |
88 | } |
89 | } | |
90 | ||
91 | let valid_user_ids = [ | |
92 | "xxx@y", | |
93 | "name@y", | |
94 | "xxx@test-it.com", | |
95 | "xxx@_T_E_S_T-it.com", | |
96 | "x_x-x.x@test-it.com", | |
97 | ]; | |
98 | ||
99 | for name in valid_user_ids.iter() { | |
e7cb4dc5 | 100 | let v = match parse_simple_value(name, &Userid::API_SCHEMA) { |
ff620a3d DM |
101 | Ok(v) => v, |
102 | Err(err) => { | |
103 | bail!("unable to parse userid '{}' - {}", name, err); | |
104 | } | |
105 | }; | |
106 | ||
107 | if v != serde_json::json!(name) { | |
108 | bail!("unable to parse userid '{}' - got wrong value {:?}", name, v); | |
109 | } | |
110 | } | |
111 | ||
112 | Ok(()) | |
113 | } | |
a2f862ee | 114 | |
75054859 DC |
115 | #[api] |
116 | #[derive(Serialize, Deserialize, Default)] | |
117 | #[serde(rename_all = "kebab-case")] | |
118 | /// Node memory usage counters | |
119 | pub struct NodeMemoryCounters { | |
120 | /// Total memory | |
121 | pub total: u64, | |
122 | /// Used memory | |
123 | pub used: u64, | |
124 | /// Free memory | |
125 | pub free: u64, | |
126 | } | |
127 | ||
398636b6 DC |
128 | #[api] |
129 | #[derive(Serialize, Deserialize, Default)] | |
130 | #[serde(rename_all = "kebab-case")] | |
131 | /// Node swap usage counters | |
132 | pub struct NodeSwapCounters { | |
133 | /// Total swap | |
134 | pub total: u64, | |
135 | /// Used swap | |
136 | pub used: u64, | |
137 | /// Free swap | |
138 | pub free: u64, | |
139 | } | |
140 | ||
75054859 DC |
141 | #[api] |
142 | #[derive(Serialize,Deserialize,Default)] | |
143 | #[serde(rename_all = "kebab-case")] | |
144 | /// Contains general node information such as the fingerprint` | |
145 | pub struct NodeInformation { | |
146 | /// The SSL Fingerprint | |
147 | pub fingerprint: String, | |
148 | } | |
149 | ||
398636b6 DC |
150 | #[api] |
151 | #[derive(Serialize, Deserialize, Default)] | |
152 | #[serde(rename_all = "kebab-case")] | |
153 | /// Information about the CPU | |
154 | pub struct NodeCpuInformation { | |
155 | /// The CPU model | |
156 | pub model: String, | |
157 | /// The number of CPU sockets | |
158 | pub sockets: usize, | |
159 | /// The number of CPU cores (incl. threads) | |
160 | pub cpus: usize, | |
161 | } | |
162 | ||
75054859 DC |
163 | #[api( |
164 | properties: { | |
165 | memory: { | |
166 | type: NodeMemoryCounters, | |
167 | }, | |
168 | root: { | |
169 | type: StorageStatus, | |
170 | }, | |
398636b6 DC |
171 | swap: { |
172 | type: NodeSwapCounters, | |
173 | }, | |
174 | loadavg: { | |
175 | type: Array, | |
176 | items: { | |
177 | type: Number, | |
178 | description: "the load", | |
179 | } | |
180 | }, | |
181 | cpuinfo: { | |
182 | type: NodeCpuInformation, | |
183 | }, | |
75054859 DC |
184 | info: { |
185 | type: NodeInformation, | |
186 | } | |
187 | }, | |
188 | )] | |
189 | #[derive(Serialize, Deserialize, Default)] | |
190 | #[serde(rename_all = "kebab-case")] | |
191 | /// The Node status | |
192 | pub struct NodeStatus { | |
193 | pub memory: NodeMemoryCounters, | |
194 | pub root: StorageStatus, | |
398636b6 DC |
195 | pub swap: NodeSwapCounters, |
196 | /// The current uptime of the server. | |
197 | pub uptime: u64, | |
198 | /// Load for 1, 5 and 15 minutes. | |
199 | pub loadavg: [f64; 3], | |
200 | /// The current kernel version. | |
201 | pub kversion: String, | |
75054859 DC |
202 | /// Total CPU usage since last query. |
203 | pub cpu: f64, | |
398636b6 DC |
204 | /// Total IO wait since last query. |
205 | pub wait: f64, | |
206 | pub cpuinfo: NodeCpuInformation, | |
75054859 DC |
207 | pub info: NodeInformation, |
208 | } | |
467bd01c DM |
209 | |
210 | pub const HTTP_PROXY_SCHEMA: Schema = StringSchema::new( | |
211 | "HTTP proxy configuration [http://]<host>[:port]") | |
212 | .format(&ApiStringFormat::VerifyFn(|s| { | |
1d781c5b | 213 | proxmox_http::ProxyConfig::parse_proxy_url(s)?; |
467bd01c DM |
214 | Ok(()) |
215 | })) | |
216 | .min_length(1) | |
217 | .max_length(128) | |
218 | .type_text("[http://]<host>[:port]") | |
219 | .schema(); |