Skip to content

Commit fe9eb86

Browse files
committed
feat(vpcpeering): Introduce validation for VpcTable
In previous commits, we introduced validation for VpcExpose and VpcManifest objects; now we do the same for a VpcTable. Here, we simply need to ensure, after building the table, that for any two given Vpcs, we have at most a single Peering object between the two: having more than one is not currently supported. Signed-off-by: Quentin Monnet <[email protected]>
1 parent a9feeb1 commit fe9eb86

File tree

4 files changed

+58
-0
lines changed

4 files changed

+58
-0
lines changed

mgmt/src/models/external/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ pub enum ConfigError {
2222
DuplicateVpcVni(u32),
2323
#[error("A VPC peering with id '{0}' already exists")]
2424
DuplicateVpcPeeringId(String),
25+
#[error("Peerings '{0}' and '{1}' refer to the same two VPCs")]
26+
DuplicateVpcPeerings(String, String),
2527
#[error("A VPC peering object refers to non-existent VPC '{0}'")]
2628
NoSuchVpc(String),
2729
#[error("'{0}' is not a valid VNI")]

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ impl Overlay {
5757
/* collect peerings of every VPC */
5858
self.vpc_table
5959
.collect_peerings(&self.peering_table, &id_map);
60+
self.vpc_table.validate()?;
6061

6162
debug!(
6263
"Overlay configuration is VALID and looks as:\n{}\n{}",

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

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,41 @@ pub mod test {
263263
);
264264
}
265265

266+
#[test]
267+
fn test_overlay_duplicate_peering() {
268+
/* build VPCs */
269+
let vpc1 = Vpc::new("VPC-1", "AAAAA", 3000).expect("Should succeed");
270+
let vpc2 = Vpc::new("VPC-2", "BBBBB", 4000).expect("Should succeed");
271+
272+
/* build VPC table */
273+
let mut vpc_table = VpcTable::new();
274+
vpc_table.add(vpc1).expect("Should succeed");
275+
vpc_table.add(vpc2).expect("Should succeed");
276+
277+
/* build peerings */
278+
let peering1 = build_vpc_peering();
279+
let mut peering2 = build_vpc_peering();
280+
peering2.name = "Peering-2".to_owned();
281+
282+
let name1 = peering1.name.clone();
283+
let name2 = peering2.name.clone();
284+
285+
assert_eq!(peering1.validate(), Ok(()));
286+
assert_eq!(peering2.validate(), Ok(()));
287+
288+
/* build peering table */
289+
let mut peering_table = VpcPeeringTable::new();
290+
peering_table.add(peering1).expect("Should succeed");
291+
peering_table.add(peering2).expect("Should succeed");
292+
293+
/* build overlay object and validate it */
294+
let mut overlay = Overlay::new(vpc_table, peering_table);
295+
assert_eq!(
296+
overlay.validate(),
297+
Err(ConfigError::DuplicateVpcPeerings(name2, name1))
298+
);
299+
}
300+
266301
#[test]
267302
fn test_overlay() {
268303
/* build VPCs */

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

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,4 +162,24 @@ impl VpcTable {
162162
self.values_mut()
163163
.for_each(|vpc| vpc.collect_peerings(peering_table, idmap));
164164
}
165+
/// Validate the [`VpcTable`]
166+
pub fn validate(&self) -> ConfigResult {
167+
for vpc in self.values() {
168+
// For each VPC, loop over all peerings
169+
for (index, peering) in vpc.peerings.iter().enumerate() {
170+
// For each peering, compare with all remaining peerings for the same (local) VPC
171+
for other_peering in vpc.peerings.iter().skip(index + 1) {
172+
// If several peerings, for the given local VPC, refer to the same remote VPC as
173+
// well, this is a configuration error
174+
if peering.remote_id == other_peering.remote_id {
175+
return Err(ConfigError::DuplicateVpcPeerings(
176+
peering.name.clone(),
177+
other_peering.name.clone(),
178+
));
179+
}
180+
}
181+
}
182+
}
183+
Ok(())
184+
}
165185
}

0 commit comments

Comments
 (0)