Skip to content

Commit 3898e9c

Browse files
qmonnetFredi-raspall
authored andcommitted
feat(vpcpeering): Implement validation for VpcManifest
We already have validation for VpcExpose, VpcPeering, and expose or peering addition to lists and tables; we're only missing some basic checks for the VpcManifest objects. There's not much to do this time, because most of the work consists in validating the VpcExpose objects and preventing prefix overlap between them, which we have implemented in previous commits. Make sure the name is not empty, make sure the lists of VpcExpose objects are not empty, and use the resulting validation function for each VpcManifest when validating a VpcPeering object. Add relevant enum variants to ApiError. Fix some tests that would use manifests with empty VpcExpose lists. Signed-off-by: Quentin Monnet <qmo@qmon.net>
1 parent 259607b commit 3898e9c

File tree

2 files changed

+79
-20
lines changed

2 files changed

+79
-20
lines changed

mgmt/src/models/external/overlay/tests.rs

Lines changed: 56 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -142,23 +142,71 @@ pub mod test {
142142
fn test_peering_iter() {
143143
let mut peering_table = VpcPeeringTable::new();
144144

145-
let m1 = VpcManifest::new("VPC-1");
146-
let m2 = VpcManifest::new("VPC-2");
145+
let mut m1 = VpcManifest::new("VPC-1");
146+
m1.add_expose(
147+
VpcExpose::empty()
148+
.ip(Prefix::from(("1.1.1.0", 24)))
149+
.as_range(Prefix::from(("1.1.2.0", 24))),
150+
)
151+
.expect("Failed to add expose");
152+
let mut m2 = VpcManifest::new("VPC-2");
153+
m2.add_expose(
154+
VpcExpose::empty()
155+
.ip(Prefix::from(("1.2.1.0", 24)))
156+
.as_range(Prefix::from(("1.2.2.0", 24))),
157+
)
158+
.expect("Failed to add expose");
147159
let peering = VpcPeering::new("Peering-1", m1, m2);
148160
peering_table.add(peering).unwrap();
149161

150-
let m1 = VpcManifest::new("VPC-1");
151-
let m2 = VpcManifest::new("VPC-3");
162+
let mut m1 = VpcManifest::new("VPC-1");
163+
m1.add_expose(
164+
VpcExpose::empty()
165+
.ip(Prefix::from(("2.1.1.0", 24)))
166+
.as_range(Prefix::from(("2.2.2.0", 24))),
167+
)
168+
.expect("Failed to add expose");
169+
let mut m2 = VpcManifest::new("VPC-3");
170+
m2.add_expose(
171+
VpcExpose::empty()
172+
.ip(Prefix::from(("2.2.1.0", 24)))
173+
.as_range(Prefix::from(("2.2.2.0", 24))),
174+
)
175+
.expect("Failed to add expose");
152176
let peering = VpcPeering::new("Peering-2", m1, m2);
153177
peering_table.add(peering).unwrap();
154178

155-
let m1 = VpcManifest::new("VPC-2");
156-
let m2 = VpcManifest::new("VPC-4");
179+
let mut m1 = VpcManifest::new("VPC-2");
180+
m1.add_expose(
181+
VpcExpose::empty()
182+
.ip(Prefix::from(("3.1.1.0", 24)))
183+
.as_range(Prefix::from(("3.1.2.0", 24))),
184+
)
185+
.expect("Failed to add expose");
186+
let mut m2 = VpcManifest::new("VPC-4");
187+
m2.add_expose(
188+
VpcExpose::empty()
189+
.ip(Prefix::from(("3.2.1.0", 24)))
190+
.as_range(Prefix::from(("3.2.2.0", 24))),
191+
)
192+
.expect("Failed to add expose");
157193
let peering = VpcPeering::new("Peering-3", m1, m2);
158194
peering_table.add(peering).unwrap();
159195

160-
let m1 = VpcManifest::new("VPC-1");
161-
let m2 = VpcManifest::new("VPC-4");
196+
let mut m1 = VpcManifest::new("VPC-1");
197+
m1.add_expose(
198+
VpcExpose::empty()
199+
.ip(Prefix::from(("4.1.1.0", 24)))
200+
.as_range(Prefix::from(("4.1.2.0", 24))),
201+
)
202+
.expect("Failed to add expose");
203+
let mut m2 = VpcManifest::new("VPC-4");
204+
m2.add_expose(
205+
VpcExpose::empty()
206+
.ip(Prefix::from(("4.2.1.0", 24)))
207+
.as_range(Prefix::from(("4.2.2.0", 24))),
208+
)
209+
.expect("Failed to add expose");
162210
let peering = VpcPeering::new("Peering-4", m1, m2);
163211
peering_table.add(peering).unwrap();
164212

mgmt/src/models/external/overlay/vpcpeering.rs

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,11 @@ impl VpcExpose {
3636
self.not_as.insert(prefix);
3737
self
3838
}
39-
fn fixup(mut self) -> Result<Self, ApiError> {
39+
fn fixup(mut self) -> Result<Self, ConfigError> {
4040
// Add a root prefix to the list of private prefixes if the list is empty
4141
if self.ips.is_empty() {
4242
if self.nots.is_empty() {
43-
return Err(ApiError::EmptyExpose);
43+
return Err(ConfigError::EmptyExpose);
4444
}
4545
let mut added_v4 = false;
4646
let mut added_v6 = false;
@@ -198,7 +198,7 @@ impl VpcManifest {
198198
..Default::default()
199199
}
200200
}
201-
fn validate_expose_addition(&self, expose: &VpcExpose) -> ApiResult {
201+
fn validate_expose_addition(&self, expose: &VpcExpose) -> ConfigResult {
202202
// Check that prefixes in the expose don't overlap with prefixes in other exposes
203203
for other_expose in &self.exposes {
204204
validate_overlapping(
@@ -216,11 +216,11 @@ impl VpcManifest {
216216
}
217217
Ok(())
218218
}
219-
pub fn add_expose(&mut self, new_expose: VpcExpose) -> ApiResult {
219+
pub fn add_expose(&mut self, new_expose: VpcExpose) -> ConfigResult {
220220
let mut expose = new_expose;
221221
match expose.validate() {
222222
Ok(_) => {}
223-
Err(ApiError::EmptyExpose) => {
223+
Err(ConfigError::EmptyExpose) => {
224224
// Fix up empty expose and give another try at validation
225225
expose = expose.clone();
226226
expose = expose.fixup()?;
@@ -232,6 +232,15 @@ impl VpcManifest {
232232
self.exposes.push(expose);
233233
Ok(())
234234
}
235+
pub fn validate(&self) -> ConfigResult {
236+
if self.name.is_empty() {
237+
return Err(ConfigError::MissingIdentifier("Manifest name"));
238+
}
239+
if self.exposes.is_empty() {
240+
return Err(ConfigError::IncompleteConfig("Empty manifest".to_string()));
241+
}
242+
Ok(())
243+
}
235244
}
236245

237246
#[derive(Clone, Debug)]
@@ -252,6 +261,8 @@ impl VpcPeering {
252261
if self.name.is_empty() {
253262
return Err(ConfigError::MissingIdentifier("Peering name"));
254263
}
264+
self.left.validate()?;
265+
self.right.validate()?;
255266
Ok(())
256267
}
257268
/// Given a peering fetch the manifests, orderly depending on the provided vpc name
@@ -280,13 +291,13 @@ impl VpcPeeringTable {
280291
self.0.is_empty()
281292
}
282293

283-
fn validate_peering_addition(&self, new_peering: &VpcPeering) -> ApiResult {
294+
fn validate_peering_addition(&self, new_peering: &VpcPeering) -> ConfigResult {
284295
// Check that exposes in the new peering do not collide with any of the exposes in the
285296
// existing peerings in the table, for the same VPCs
286297
for vpc in [&new_peering.left.name, &new_peering.right.name] {
287-
let (new_local, _) = new_peering.get_peers(vpc);
298+
let (new_local, _) = new_peering.get_peering_manifests(vpc);
288299
for peering in self.peerings_vpc(vpc) {
289-
let (local, _) = peering.get_peers(vpc);
300+
let (local, _) = peering.get_peering_manifests(vpc);
290301
for new_expose in &new_local.exposes {
291302
for expose in &local.exposes {
292303
validate_overlapping(
@@ -314,7 +325,7 @@ impl VpcPeeringTable {
314325

315326
// First look for an existing entry, to avoid inserting a duplicate peering
316327
if self.0.contains_key(&peering.name) {
317-
return Err(ApiError::DuplicateVpcPeeringId(peering.name.clone()));
328+
return Err(ConfigError::DuplicateVpcPeeringId(peering.name.clone()));
318329
}
319330

320331
if let Some(peering) = self.0.insert(peering.name.to_owned(), peering) {
@@ -341,7 +352,7 @@ fn validate_overlapping(
341352
excludes_left: &BTreeSet<Prefix>,
342353
prefixes_right: &BTreeSet<Prefix>,
343354
excludes_right: &BTreeSet<Prefix>,
344-
) -> Result<(), ApiError> {
355+
) -> Result<(), ConfigError> {
345356
// Find colliding prefixes
346357
let mut colliding = Vec::new();
347358
for prefix_left in prefixes_left.iter() {
@@ -448,7 +459,7 @@ fn validate_overlapping(
448459
// Some addresses at the intersection of both prefixes are not covered by the union of
449460
// all exclusion prefixes, in other words, they are available from both prefixes. This
450461
// is an error.
451-
return Err(ApiError::OverlappingPrefixes(prefix_left, prefix_right));
462+
return Err(ConfigError::OverlappingPrefixes(prefix_left, prefix_right));
452463
}
453464
}
454465
Ok(())
@@ -753,7 +764,7 @@ mod tests {
753764
let peering2 = VpcPeering::new("test_peering2", manifest1.clone(), manifest2.clone());
754765
assert_eq!(
755766
table.add(peering2),
756-
Err(ApiError::OverlappingPrefixes(
767+
Err(ConfigError::OverlappingPrefixes(
757768
prefix_v4("10.0.0.0/16"),
758769
prefix_v4("10.0.0.0/16")
759770
))

0 commit comments

Comments
 (0)