Skip to content

Commit 127334f

Browse files
committed
fix(config): Convert NAT configuration from K8s
The k8s conversion code was not properly setting the NAT config even when configured in k8s making it impossible to set stateful NAT. This adds the conversion and some unit tests. Signed-off-by: Manish Vachharajani <manish@githedgehog.com>
1 parent e086aab commit 127334f

File tree

2 files changed

+64
-1
lines changed

2 files changed

+64
-1
lines changed

config/src/converters/k8s/config/expose.rs

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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)]
179197
mod 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:#?}\nk8s: {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
}

k8s-intf/src/bolero/expose.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ impl ValueGenerator for LegalValueExposeGenerator<'_> {
126126
Some(GatewayAgentPeeringsPeeringExpose {
127127
r#as: Some(final_as).filter(|f| !f.is_empty()),
128128
ips: Some(final_ips).filter(|f| !f.is_empty()),
129-
nat: if has_as {
129+
nat: if has_as && d.produce::<bool>()? {
130130
Some(
131131
d.produce::<LegalValue<GatewayAgentPeeringsPeeringExposeNat>>()?
132132
.take(),

0 commit comments

Comments
 (0)