@@ -47,7 +47,7 @@ use uuid::Uuid;
47
47
/// -- we're trying to cacth.
48
48
/// CAST(
49
49
/// IF(
50
- /// inet_contains_or_equals(ipv4_block, <ipv4_block>),
50
+ /// ( <ipv4_block> && ipv4_block ),
51
51
/// 'ipv4',
52
52
/// 'ipv6'
53
53
/// )
@@ -60,8 +60,8 @@ use uuid::Uuid;
60
60
/// time_deleted IS NULL AND
61
61
/// id != <id> AND
62
62
/// (
63
- /// inet_contains_or_equals (ipv4_block, <ipv4_block>) OR
64
- /// inet_contains_or_equals (ipv6_block, <ipv6_block>)
63
+ /// (ipv4_block && <ipv4_block>) OR
64
+ /// (ipv6_block && <ipv6_block>)
65
65
/// )
66
66
/// )
67
67
/// INSERT INTO
@@ -104,9 +104,9 @@ impl QueryFragment<Pg> for InsertVpcSubnetQuery {
104
104
& ' a self ,
105
105
mut out : AstPass < ' _ , ' a , Pg > ,
106
106
) -> diesel:: QueryResult < ( ) > {
107
- out. push_sql ( "WITH overlap AS MATERIALIZED (SELECT CAST(IF(inet_contains_or_equals (" ) ;
107
+ out. push_sql ( "WITH overlap AS MATERIALIZED (SELECT CAST(IF((" ) ;
108
108
out. push_identifier ( dsl:: ipv4_block:: NAME ) ?;
109
- out. push_sql ( ", " ) ;
109
+ out. push_sql ( " && " ) ;
110
110
out. push_bind_param :: < sql_types:: Inet , _ > ( & self . ipv4_block ) ?;
111
111
out. push_sql ( "), " ) ;
112
112
out. push_bind_param :: < sql_types:: Text , _ > (
@@ -128,13 +128,13 @@ impl QueryFragment<Pg> for InsertVpcSubnetQuery {
128
128
out. push_identifier ( dsl:: id:: NAME ) ?;
129
129
out. push_sql ( " != " ) ;
130
130
out. push_bind_param :: < sql_types:: Uuid , Uuid > ( & self . subnet . identity . id ) ?;
131
- out. push_sql ( " AND (inet_contains_or_equals (" ) ;
131
+ out. push_sql ( " AND ((" ) ;
132
132
out. push_identifier ( dsl:: ipv4_block:: NAME ) ?;
133
- out. push_sql ( ", " ) ;
133
+ out. push_sql ( " && " ) ;
134
134
out. push_bind_param :: < sql_types:: Inet , IpNetwork > ( & self . ipv4_block ) ?;
135
- out. push_sql ( ") OR inet_contains_or_equals (" ) ;
135
+ out. push_sql ( ") OR (" ) ;
136
136
out. push_identifier ( dsl:: ipv6_block:: NAME ) ?;
137
- out. push_sql ( ", " ) ;
137
+ out. push_sql ( " && " ) ;
138
138
out. push_bind_param :: < sql_types:: Inet , IpNetwork > ( & self . ipv6_block ) ?;
139
139
140
140
out. push_sql ( "))) INSERT INTO " ) ;
@@ -331,8 +331,14 @@ mod test {
331
331
} ;
332
332
let ipv4_block = "172.30.0.0/22" . parse ( ) . unwrap ( ) ;
333
333
let other_ipv4_block = "172.31.0.0/22" . parse ( ) . unwrap ( ) ;
334
+ let overlapping_ipv4_block_longer = "172.30.0.0/21" . parse ( ) . unwrap ( ) ;
335
+ let overlapping_ipv4_block_shorter = "172.30.0.0/23" . parse ( ) . unwrap ( ) ;
334
336
let ipv6_block = "fd12:3456:7890::/64" . parse ( ) . unwrap ( ) ;
335
337
let other_ipv6_block = "fd00::/64" . parse ( ) . unwrap ( ) ;
338
+ let overlapping_ipv6_block_longer =
339
+ "fd12:3456:7890::/60" . parse ( ) . unwrap ( ) ;
340
+ let overlapping_ipv6_block_shorter =
341
+ "fd12:3456:7890::/68" . parse ( ) . unwrap ( ) ;
336
342
let name = "a-name" . to_string ( ) . try_into ( ) . unwrap ( ) ;
337
343
let other_name = "b-name" . to_string ( ) . try_into ( ) . unwrap ( ) ;
338
344
let description = "some description" . to_string ( ) ;
@@ -404,6 +410,81 @@ mod test {
404
410
"Should be able to insert a VPC Subnet with the same ranges in a different VPC" ,
405
411
) ;
406
412
413
+ // We shouldn't be able to insert a subnet if the IPv4 or IPv6 blocks overlap.
414
+ // Explicitly test for different CIDR masks with the same network address
415
+ let new_row = VpcSubnet :: new (
416
+ other_other_subnet_id,
417
+ vpc_id,
418
+ make_id ( & other_name, & description) ,
419
+ overlapping_ipv4_block_longer,
420
+ other_ipv6_block,
421
+ ) ;
422
+ let err = db_datastore. vpc_create_subnet_raw ( new_row) . await . expect_err (
423
+ "Should not be able to insert VPC Subnet with \
424
+ overlapping IPv4 range {overlapping_ipv4_block_longer}",
425
+ ) ;
426
+ assert_eq ! (
427
+ err,
428
+ InsertVpcSubnetError :: OverlappingIpRange (
429
+ overlapping_ipv4_block_longer. into( )
430
+ ) ,
431
+ "InsertError variant should indicate an IP block overlaps"
432
+ ) ;
433
+ let new_row = VpcSubnet :: new (
434
+ other_other_subnet_id,
435
+ vpc_id,
436
+ make_id ( & other_name, & description) ,
437
+ overlapping_ipv4_block_shorter,
438
+ other_ipv6_block,
439
+ ) ;
440
+ let err = db_datastore. vpc_create_subnet_raw ( new_row) . await . expect_err (
441
+ "Should not be able to insert VPC Subnet with \
442
+ overlapping IPv4 range {overlapping_ipv4_block_shorter}",
443
+ ) ;
444
+ assert_eq ! (
445
+ err,
446
+ InsertVpcSubnetError :: OverlappingIpRange (
447
+ overlapping_ipv4_block_shorter. into( )
448
+ ) ,
449
+ "InsertError variant should indicate an IP block overlaps"
450
+ ) ;
451
+ let new_row = VpcSubnet :: new (
452
+ other_other_subnet_id,
453
+ vpc_id,
454
+ make_id ( & other_name, & description) ,
455
+ other_ipv4_block,
456
+ overlapping_ipv6_block_longer,
457
+ ) ;
458
+ let err = db_datastore. vpc_create_subnet_raw ( new_row) . await . expect_err (
459
+ "Should not be able to insert VPC Subnet with \
460
+ overlapping IPv6 range {overlapping_ipv6_block_longer}",
461
+ ) ;
462
+ assert_eq ! (
463
+ err,
464
+ InsertVpcSubnetError :: OverlappingIpRange (
465
+ overlapping_ipv6_block_longer. into( )
466
+ ) ,
467
+ "InsertError variant should indicate an IP block overlaps"
468
+ ) ;
469
+ let new_row = VpcSubnet :: new (
470
+ other_other_subnet_id,
471
+ vpc_id,
472
+ make_id ( & other_name, & description) ,
473
+ other_ipv4_block,
474
+ overlapping_ipv6_block_shorter,
475
+ ) ;
476
+ let err = db_datastore. vpc_create_subnet_raw ( new_row) . await . expect_err (
477
+ "Should not be able to insert VPC Subnet with \
478
+ overlapping IPv6 range {overlapping_ipv6_block_shorter}",
479
+ ) ;
480
+ assert_eq ! (
481
+ err,
482
+ InsertVpcSubnetError :: OverlappingIpRange (
483
+ overlapping_ipv6_block_shorter. into( )
484
+ ) ,
485
+ "InsertError variant should indicate an IP block overlaps"
486
+ ) ;
487
+
407
488
// We shouldn't be able to insert a subnet if we change only the
408
489
// IPv4 or IPv6 block. They must _both_ be non-overlapping.
409
490
let new_row = VpcSubnet :: new (
@@ -413,10 +494,10 @@ mod test {
413
494
other_ipv4_block,
414
495
ipv6_block,
415
496
) ;
416
- let err = db_datastore
417
- . vpc_create_subnet_raw ( new_row )
418
- . await
419
- . expect_err ( "Should not be able to insert VPC Subnet with overlapping IPv6 range" ) ;
497
+ let err = db_datastore. vpc_create_subnet_raw ( new_row ) . await . expect_err (
498
+ "Should not be able to insert VPC Subnet with \
499
+ overlapping IPv6 range" ,
500
+ ) ;
420
501
assert_eq ! (
421
502
err,
422
503
InsertVpcSubnetError :: OverlappingIpRange ( ipv6_block. into( ) ) ,
0 commit comments