@@ -165,6 +165,24 @@ impl TryFrom<(&SubnetMap, &GatewayAgentPeeringsPeeringExpose)> for VpcExpose {
165165 ) ) ;
166166 }
167167
168+ vpc_expose = match & expose. nat {
169+ Some ( nat) => match ( & nat. stateful , & nat. stateless ) {
170+ ( Some ( _) , Some ( _) ) => {
171+ return Err ( FromK8sConversionError :: Invalid (
172+ "Cannot have both stateful and stateless nat configured on the same expose block" . to_string ( ) ,
173+ ) ) ;
174+ }
175+ ( Some ( stateful) , None ) => vpc_expose
176+ . make_stateful_nat ( stateful. idle_timeout )
177+ . map_err ( |e| FromK8sConversionError :: Invalid ( e. to_string ( ) ) ) ,
178+ ( None , Some ( _) ) => vpc_expose
179+ . make_stateless_nat ( )
180+ . map_err ( |e| FromK8sConversionError :: Invalid ( e. to_string ( ) ) ) ,
181+ ( None , None ) => Ok ( vpc_expose) , // Rely on default behavior for NAT
182+ } ,
183+ None => Ok ( vpc_expose) ,
184+ } ?;
185+
168186 if let Some ( ases) = expose. r#as . as_ref ( ) {
169187 for r#as in ases {
170188 vpc_expose = process_as_block ( vpc_expose, r#as) ?;
@@ -177,6 +195,8 @@ impl TryFrom<(&SubnetMap, &GatewayAgentPeeringsPeeringExpose)> for VpcExpose {
177195
178196#[ cfg( test) ]
179197mod test {
198+ use crate :: external:: overlay:: vpcpeering:: VpcExposeNatConfig ;
199+
180200 use super :: * ;
181201
182202 #[ test]
@@ -482,6 +502,49 @@ mod test {
482502 assert_eq ! ( nots, k8s_nots) ;
483503 assert_eq ! ( r#as, k8s_as) ;
484504 assert_eq ! ( not_as, k8s_not_as) ;
505+ match ( expose. nat . as_ref ( ) , k8s_expose. nat . as_ref ( ) ) {
506+ ( Some ( nat) , None ) => {
507+ assert ! (
508+ k8s_expose. r#as. is_some( ) ,
509+ "K8s does not have NAT set, but nat is configured: {expose}"
510+ ) ;
511+ assert ! (
512+ nat. is_stateless( ) ,
513+ "Default NAT configured via 'as' by k8s, but nat is not stateless: {expose}"
514+ ) ;
515+ }
516+ ( None , Some ( _) ) => {
517+ panic ! ( "K8s has NAT configured, but dataplane config does not" )
518+ }
519+ ( Some ( nat) , Some ( k8s_nat) ) => match & nat. config {
520+ VpcExposeNatConfig :: Stateful ( c) => {
521+ if let Some ( k8s_stateful) = k8s_nat. stateful . as_ref ( ) {
522+ if let Some ( k8s_idle_timeout) = k8s_stateful. idle_timeout {
523+ assert_eq ! ( c. idle_timeout, k8s_idle_timeout) ;
524+ } else {
525+ assert_eq ! ( c. idle_timeout, std:: time:: Duration :: new( 2 * 60 , 0 ) ) ;
526+ }
527+ } else {
528+ panic ! ( "Stateful NAT configured but not by K8s" ) ;
529+ }
530+ }
531+ VpcExposeNatConfig :: Stateless ( _) => {
532+ assert ! ( k8s_nat. stateful. is_none( ) , "Stateless NAT configured but K8s configured stateful NAT: {expose:#?}\n k8s: {k8s_nat:#?}" ) ;
533+ if k8s_nat. stateless . is_none ( ) {
534+ assert ! ( k8s_expose. r#as. is_some( ) ) ;
535+ }
536+ }
537+ } ,
538+ ( None , None ) => {
539+ if k8s_expose. r#as . is_some ( ) {
540+ if let Some ( nat) = expose. nat . as_ref ( ) {
541+ assert ! ( nat. is_stateless( ) ) ;
542+ } else {
543+ panic ! ( "K8s has nat configured, but dataplane config does not" )
544+ }
545+ }
546+ }
547+ }
485548 } ) ;
486549 }
487550}
0 commit comments