diff --git a/policy-controller/grpc/src/outbound.rs b/policy-controller/grpc/src/outbound.rs index 6840bce5007d0..262b96827734b 100644 --- a/policy-controller/grpc/src/outbound.rs +++ b/policy-controller/grpc/src/outbound.rs @@ -237,8 +237,12 @@ fn to_service(outbound: OutboundPolicy) -> outbound::OutboundPolicy { outbound::failure_accrual::ConsecutiveFailures { max_failures, backoff: Some(outbound::ExponentialBackoff { - min_backoff: convert_duration("min_backoff")(backoff.min_penalty), - max_backoff: convert_duration("max_backoff")(backoff.max_penalty), + min_backoff: convert_duration("min_backoff")( + backoff.min_penalty, + ), + max_backoff: convert_duration("max_backoff")( + backoff.max_penalty, + ), jitter_ratio: backoff.jitter, }), }, @@ -312,33 +316,39 @@ fn convert_outbound_http_route( let rules = rules .into_iter() - .map(|HttpRouteRule { matches, backends, request_timeout }| { - let backends = backends - .into_iter() - .map(convert_http_backend) - .collect::>(); - let dist = if backends.is_empty() { - outbound::http_route::distribution::Kind::FirstAvailable( - outbound::http_route::distribution::FirstAvailable { - backends: vec![outbound::http_route::RouteBackend { - backend: Some(backend.clone()), - filters: vec![], - request_timeout: None, - }], - }, - ) - } else { - outbound::http_route::distribution::Kind::RandomAvailable( - outbound::http_route::distribution::RandomAvailable { backends }, - ) - }; - outbound::http_route::Rule { - matches: matches.into_iter().map(http_route::convert_match).collect(), - backends: Some(outbound::http_route::Distribution { kind: Some(dist) }), - filters: Default::default(), - request_timeout: request_timeout.and_then(convert_duration("request timeout")) - } - }) + .map( + |HttpRouteRule { + matches, + backends, + request_timeout, + }| { + let backends = backends + .into_iter() + .map(convert_http_backend) + .collect::>(); + let dist = if backends.is_empty() { + outbound::http_route::distribution::Kind::FirstAvailable( + outbound::http_route::distribution::FirstAvailable { + backends: vec![outbound::http_route::RouteBackend { + backend: Some(backend.clone()), + filters: vec![], + request_timeout: None, + }], + }, + ) + } else { + outbound::http_route::distribution::Kind::RandomAvailable( + outbound::http_route::distribution::RandomAvailable { backends }, + ) + }; + outbound::http_route::Rule { + matches: matches.into_iter().map(http_route::convert_match).collect(), + backends: Some(outbound::http_route::Distribution { kind: Some(dist) }), + filters: Default::default(), + request_timeout: request_timeout.and_then(convert_duration("request timeout")), + } + }, + ) .collect(); outbound::HttpRoute { @@ -367,7 +377,9 @@ fn convert_http_backend(backend: Backend) -> outbound::http_route::WeightedRoute )), }), filters: Default::default(), - request_timeout: addr.request_timeout.and_then(convert_duration("backend request timeout")) + request_timeout: addr + .request_timeout + .and_then(convert_duration("backend request timeout")), }), } } @@ -400,7 +412,9 @@ fn convert_http_backend(backend: Backend) -> outbound::http_route::WeightedRoute )), }), filters: Default::default(), - request_timeout: svc.request_timeout.and_then(convert_duration("backend request timeout")) + request_timeout: svc + .request_timeout + .and_then(convert_duration("backend request timeout")), }), }, Backend::Invalid { weight, message } => outbound::http_route::WeightedRouteBackend { @@ -525,14 +539,19 @@ fn default_queue_config() -> outbound::Queue { } } -fn convert_duration(name: &'static str) -> impl Fn(time::Duration) -> Option { +fn convert_duration( + name: &'static str, +) -> impl Fn(time::Duration) -> Option { move |duration| { - duration.try_into().map_err(|error| { - tracing::error!(%error, "Invalid {name} duration"); - prost_types::Duration { - seconds: 315_576_000_000, - nanos: 999_999_999 - } - }).ok() + duration + .try_into() + .map_err(|error| { + tracing::error!(%error, "Invalid {name} duration"); + prost_types::Duration { + seconds: 315_576_000_000, + nanos: 999_999_999, + } + }) + .ok() } -} \ No newline at end of file +} diff --git a/policy-controller/k8s/api/src/duration.rs b/policy-controller/k8s/api/src/duration.rs index 1a9d11f30f96e..969ec9e703903 100644 --- a/policy-controller/k8s/api/src/duration.rs +++ b/policy-controller/k8s/api/src/duration.rs @@ -1,5 +1,5 @@ -use std::{str::FromStr, time::Duration, fmt}; -use serde::{Serialize, Serializer, Deserialize, Deserializer, de}; +use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; +use std::{fmt, str::FromStr, time::Duration}; #[derive(Copy, Clone, PartialEq, Eq)] pub struct K8sDuration { @@ -26,13 +26,13 @@ impl From for K8sDuration { fn from(duration: Duration) -> Self { Self { duration, - is_negative: false + is_negative: false, } } } impl From for Duration { - fn from(K8sDuration {duration, .. }: K8sDuration) -> Self { + fn from(K8sDuration { duration, .. }: K8sDuration) -> Self { duration } } @@ -98,7 +98,8 @@ impl FromStr for K8sDuration { if let Some(unit_start) = s.find(|c: char| c.is_alphabetic()) { let (val, rest) = s.split_at(unit_start); let val = val.parse::()?; - let unit = if let Some(next_numeric_start) = rest.find(|c: char| !c.is_alphabetic()) { + let unit = if let Some(next_numeric_start) = rest.find(|c: char| !c.is_alphabetic()) + { let (unit, rest) = rest.split_at(next_numeric_start); s = rest; unit @@ -108,14 +109,19 @@ impl FromStr for K8sDuration { }; total += duration_from_units(val, unit)?; } else if s == "0" { - return Ok(K8sDuration { duration: Duration::from_secs(0), is_negative }); + return Ok(K8sDuration { + duration: Duration::from_secs(0), + is_negative, + }); } else { return Err(ParseError::NoUnit); } } - Ok(K8sDuration { duration: total, is_negative }) - + Ok(K8sDuration { + duration: total, + is_negative, + }) } } @@ -131,7 +137,7 @@ impl Serialize for K8sDuration { impl<'de> Deserialize<'de> for K8sDuration { fn deserialize(deserializer: D) -> Result where - D: Deserializer<'de> + D: Deserializer<'de>, { struct Visitor; impl<'de> de::Visitor<'de> for Visitor { @@ -141,7 +147,6 @@ impl<'de> Deserialize<'de> for K8sDuration { f.write_str("a string in Go `time.Duration.String()` format") } - fn visit_str(self, value: &str) -> Result where E: de::Error, @@ -204,18 +209,33 @@ mod tests { ("1478s", Duration::from_secs(1478).into()), // // sign // {"-5s", -5 * Second}, - ("-5s", K8sDuration {duration: Duration::from_secs(5), is_negative: true }), + ( + "-5s", + K8sDuration { + duration: Duration::from_secs(5), + is_negative: true, + }, + ), // {"+5s", 5 * Second}, ("+5s", Duration::from_secs(5).into()), // {"-0", 0}, - ("-0", K8sDuration { duration: Duration::from_secs(0), is_negative: true }), + ( + "-0", + K8sDuration { + duration: Duration::from_secs(0), + is_negative: true, + }, + ), // {"+0", 0}, ("+0", Duration::from_secs(0).into()), // // decimal // {"5.0s", 5 * Second}, ("5s", Duration::from_secs(5).into()), // {"5.6s", 5*Second + 600*Millisecond}, - ("5.6s", (Duration::from_secs(5) + Duration::from_millis(600)).into()), + ( + "5.6s", + (Duration::from_secs(5) + Duration::from_millis(600)).into(), + ), // {"5.s", 5 * Second}, ("5.s", Duration::from_secs(5).into()), // {".5s", 500 * Millisecond}, @@ -225,11 +245,20 @@ mod tests { // {"1.00s", 1 * Second}, ("1.00s", Duration::from_secs(1).into()), // {"1.004s", 1*Second + 4*Millisecond}, - ("1.004s", (Duration::from_secs(1) + Duration::from_millis(4)).into()), + ( + "1.004s", + (Duration::from_secs(1) + Duration::from_millis(4)).into(), + ), // {"1.0040s", 1*Second + 4*Millisecond}, - ("1.0040s", (Duration::from_secs(1) + Duration::from_millis(4)).into()), + ( + "1.0040s", + (Duration::from_secs(1) + Duration::from_millis(4)).into(), + ), // {"100.00100s", 100*Second + 1*Millisecond}, - ("100.00100s", (Duration::from_secs(100) + Duration::from_millis(1)).into()), + ( + "100.00100s", + (Duration::from_secs(100) + Duration::from_millis(1)).into(), + ), // // different units // {"10ns", 10 * Nanosecond}, ("10ns", Duration::from_nanos(10).into()), @@ -251,18 +280,34 @@ mod tests { // {"3h30m", 3*Hour + 30*Minute}, ("3h30m", (3 * HOUR + 30 * MINUTE).into()), // {"10.5s4m", 4*Minute + 10*Second + 500*Millisecond}, - ("10.5s4m", (4 * MINUTE + Duration::from_secs(10) + Duration::from_millis(500)).into()), + ( + "10.5s4m", + (4 * MINUTE + Duration::from_secs(10) + Duration::from_millis(500)).into(), + ), // {"-2m3.4s", -(2*Minute + 3*Second + 400*Millisecond)}, - ("-2m3.4s", K8sDuration { duration: 2 * MINUTE + Duration::from_secs(3) + Duration::from_millis(400), is_negative: true }), + ( + "-2m3.4s", + K8sDuration { + duration: 2 * MINUTE + Duration::from_secs(3) + Duration::from_millis(400), + is_negative: true, + }, + ), // {"1h2m3s4ms5us6ns", 1*Hour + 2*Minute + 3*Second + 4*Millisecond + 5*Microsecond + 6*Nanosecond}, ( "1h2m3s4ms5us6ns", - (1 * HOUR + 2 * MINUTE + Duration::from_secs(3) + Duration::from_millis(4) - + Duration::from_micros(5) + Duration::from_nanos(6)).into()), + (1 * HOUR + + 2 * MINUTE + + Duration::from_secs(3) + + Duration::from_millis(4) + + Duration::from_micros(5) + + Duration::from_nanos(6)) + .into(), + ), // {"39h9m14.425s", 39*Hour + 9*Minute + 14*Second + 425*Millisecond}, ( "39h9m14.425s", - (39 * HOUR + 9 * MINUTE + Duration::from_secs(14) + Duration::from_millis(425)).into(), + (39 * HOUR + 9 * MINUTE + Duration::from_secs(14) + Duration::from_millis(425)) + .into(), ), // // large value // {"52763797000ns", 52763797000 * Nanosecond}, @@ -272,7 +317,10 @@ mod tests { ("0.3333333333333333333h", (20 * MINUTE).into()), // // 9007199254740993 = 1<<53+1 cannot be stored precisely in a float64 // {"9007199254740993ns", (1<<53 + 1) * Nanosecond}, - ("9007199254740993ns", Duration::from_nanos((1 << 53) + 1).into()), + ( + "9007199254740993ns", + Duration::from_nanos((1 << 53) + 1).into(), + ), // Rust Durations can handle larger durations than Go's // representation, so skip these tests for their precision limits @@ -292,11 +340,10 @@ mod tests { // // huge string; issue 15011. // {"0.100000000000000000000h", 6 * Minute}, - ("0.100000000000000000000h", (6 * MINUTE).into()) - // // This value tests the first overflow check in leadingFraction. - // {"0.830103483285477580700h", 49*Minute + 48*Second + 372539827*Nanosecond}, - // } - // ``` + ("0.100000000000000000000h", (6 * MINUTE).into()), // // This value tests the first overflow check in leadingFraction. + // {"0.830103483285477580700h", 49*Minute + 48*Second + 372539827*Nanosecond}, + // } + // ``` ]; for (input, expected) in cases { diff --git a/policy-controller/k8s/api/src/lib.rs b/policy-controller/k8s/api/src/lib.rs index 299485178d787..67d72ee0fae1a 100644 --- a/policy-controller/k8s/api/src/lib.rs +++ b/policy-controller/k8s/api/src/lib.rs @@ -1,9 +1,9 @@ #![deny(warnings, rust_2018_idioms)] #![forbid(unsafe_code)] +pub mod duration; pub mod labels; pub mod policy; -pub mod duration; pub use self::labels::Labels; pub use k8s_gateway_api as gateway; diff --git a/policy-controller/k8s/index/src/outbound/index.rs b/policy-controller/k8s/index/src/outbound/index.rs index 901a386e19158..e055d8863f2a0 100644 --- a/policy-controller/k8s/index/src/outbound/index.rs +++ b/policy-controller/k8s/index/src/outbound/index.rs @@ -328,15 +328,33 @@ impl Namespace { .map(http_route::try_match) .collect::>()?; - let backend_request_timeout = rule.timeouts.as_ref().and_then(|timeouts| Some(time::Duration::from(timeouts.backend_request?))); + let backend_request_timeout = rule + .timeouts + .as_ref() + .and_then(|timeouts| Some(time::Duration::from(timeouts.backend_request?))); let backends = rule .backend_refs .into_iter() .flatten() - .filter_map(|b| convert_backend(&self.namespace, b, cluster, service_info, backend_request_timeout)) + .filter_map(|b| { + convert_backend( + &self.namespace, + b, + cluster, + service_info, + backend_request_timeout, + ) + }) .collect(); - let request_timeout = rule.timeouts.as_ref().and_then(|timeouts| Some(time::Duration::from(timeouts.request?))); - Ok(HttpRouteRule { matches, backends, request_timeout }) + let request_timeout = rule + .timeouts + .as_ref() + .and_then(|timeouts| Some(time::Duration::from(timeouts.request?))); + Ok(HttpRouteRule { + matches, + backends, + request_timeout, + }) } } diff --git a/policy-controller/src/admission.rs b/policy-controller/src/admission.rs index a0969ff84b490..eade0aa5c5fc9 100644 --- a/policy-controller/src/admission.rs +++ b/policy-controller/src/admission.rs @@ -467,7 +467,10 @@ impl Validate for Admission { use std::time::Duration; if let Some(t) = timeouts.backend_request { - ensure!(!t.is_negative(), "backendRequest timeout must not be negative"); + ensure!( + !t.is_negative(), + "backendRequest timeout must not be negative" + ); } if let Some(t) = timeouts.request { @@ -488,7 +491,10 @@ impl Validate for Admission { // from `HttpRouteSpec` to `InboundRouteBinding`, except that we don't // actually allocate stuff in order to return an `InboundRouteBinding`. for httproute::HttpRouteRule { - filters, matches, timeouts, .. + filters, + matches, + timeouts, + .. } in spec.rules.into_iter().flatten() { for m in matches.into_iter().flatten() {