Skip to content

Commit

Permalink
add TCP and TLS route tests
Browse files Browse the repository at this point in the history
Signed-off-by: Zahari Dichev <[email protected]>
  • Loading branch information
zaharidichev committed Nov 20, 2024
1 parent 742c0ab commit 1668f53
Show file tree
Hide file tree
Showing 4 changed files with 1,555 additions and 0 deletions.
46 changes: 46 additions & 0 deletions policy-test/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,52 @@ pub async fn await_grpc_route_status(
route_status
}

// Waits until an TlsRoute with the given namespace and name has a status set
// on it, then returns the generic route status representation.
pub async fn await_tls_route_status(
client: &kube::Client,
ns: &str,
name: &str,
) -> k8s::gateway::TlsRouteStatus {
let route_status = await_condition(
client,
ns,
name,
|obj: Option<&k8s::gateway::TlsRoute>| -> bool {
obj.and_then(|route| route.status.as_ref()).is_some()
},
)
.await
.expect("must fetch route")
.status
.expect("route must contain a status representation");
tracing::trace!(?route_status, name, ns, "got route status");
route_status
}

// Waits until an TcpRoute with the given namespace and name has a status set
// on it, then returns the generic route status representation.
pub async fn await_tcp_route_status(
client: &kube::Client,
ns: &str,
name: &str,
) -> k8s::gateway::TcpRouteStatus {
let route_status = await_condition(
client,
ns,
name,
|obj: Option<&k8s::gateway::TcpRoute>| -> bool {
obj.and_then(|route| route.status.as_ref()).is_some()
},
)
.await
.expect("must fetch route")
.status
.expect("route must contain a status representation");
tracing::trace!(?route_status, name, ns, "got route status");
route_status
}

// Wait for the endpoints controller to populate the Endpoints resource.
pub fn endpoints_ready(obj: Option<&k8s::Endpoints>) -> bool {
if let Some(ep) = obj {
Expand Down
223 changes: 223 additions & 0 deletions policy-test/src/outbound_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,44 @@ pub fn grpc_routes(config: &grpc::outbound::OutboundPolicy) -> &[grpc::outbound:
}
}

#[track_caller]
pub fn tls_routes(config: &grpc::outbound::OutboundPolicy) -> &[grpc::outbound::TlsRoute] {
let kind = config
.protocol
.as_ref()
.expect("must have proxy protocol")
.kind
.as_ref()
.expect("must have kind");
if let grpc::outbound::proxy_protocol::Kind::Tls(grpc::outbound::proxy_protocol::Tls {
routes,
}) = kind
{
routes
} else {
panic!("proxy protocol must be Tls; actually got:\n{kind:#?}")
}
}

#[track_caller]
pub fn tcp_routes(config: &grpc::outbound::OutboundPolicy) -> &[grpc::outbound::OpaqueRoute] {
let kind = config
.protocol
.as_ref()
.expect("must have proxy protocol")
.kind
.as_ref()
.expect("must have kind");
if let grpc::outbound::proxy_protocol::Kind::Opaque(grpc::outbound::proxy_protocol::Opaque {
routes,
}) = kind
{
routes
} else {
panic!("proxy protocol must be Opaque; actually got:\n{kind:#?}")
}
}

#[track_caller]
pub fn detect_failure_accrual<F>(config: &grpc::outbound::OutboundPolicy, f: F)
where
Expand Down Expand Up @@ -149,6 +187,23 @@ pub fn route_backends_first_available(
}
}

#[track_caller]
pub fn tls_route_backends_first_available(
route: &grpc::outbound::TlsRoute,
) -> &[grpc::outbound::tls_route::RouteBackend] {
let kind = assert_singleton(&route.rules)
.backends
.as_ref()
.expect("Rule must have backends")
.kind
.as_ref()
.expect("Backend must have kind");
match kind {
grpc::outbound::tls_route::distribution::Kind::FirstAvailable(fa) => &fa.backends,
_ => panic!("Distribution must be FirstAvailable"),
}
}

#[track_caller]
pub fn route_backends_random_available(
route: &grpc::outbound::HttpRoute,
Expand All @@ -166,6 +221,40 @@ pub fn route_backends_random_available(
}
}

#[track_caller]
pub fn tls_route_backends_random_available(
route: &grpc::outbound::TlsRoute,
) -> &[grpc::outbound::tls_route::WeightedRouteBackend] {
let kind = assert_singleton(&route.rules)
.backends
.as_ref()
.expect("Rule must have backends")
.kind
.as_ref()
.expect("Backend must have kind");
match kind {
grpc::outbound::tls_route::distribution::Kind::RandomAvailable(dist) => &dist.backends,
_ => panic!("Distribution must be RandomAvailable"),
}
}

#[track_caller]
pub fn tcp_route_backends_random_available(
route: &grpc::outbound::OpaqueRoute,
) -> &[grpc::outbound::opaque_route::WeightedRouteBackend] {
let kind = assert_singleton(&route.rules)
.backends
.as_ref()
.expect("Rule must have backends")
.kind
.as_ref()
.expect("Backend must have kind");
match kind {
grpc::outbound::opaque_route::distribution::Kind::RandomAvailable(dist) => &dist.backends,
_ => panic!("Distribution must be RandomAvailable"),
}
}

#[track_caller]
pub fn route_name(route: &grpc::outbound::HttpRoute) -> &str {
match route.metadata.as_ref().unwrap().kind.as_ref().unwrap() {
Expand All @@ -174,6 +263,22 @@ pub fn route_name(route: &grpc::outbound::HttpRoute) -> &str {
}
}

#[track_caller]
pub fn tls_route_name(route: &grpc::outbound::TlsRoute) -> &str {
match route.metadata.as_ref().unwrap().kind.as_ref().unwrap() {
grpc::meta::metadata::Kind::Resource(grpc::meta::Resource { ref name, .. }) => name,
_ => panic!("route must be a resource kind"),
}
}

#[track_caller]
pub fn tcp_route_name(route: &grpc::outbound::OpaqueRoute) -> &str {
match route.metadata.as_ref().unwrap().kind.as_ref().unwrap() {
grpc::meta::metadata::Kind::Resource(grpc::meta::Resource { ref name, .. }) => name,
_ => panic!("route must be a resource kind"),
}
}

#[track_caller]
pub fn assert_backend_has_failure_filter(
backend: &grpc::outbound::http_route::WeightedRouteBackend,
Expand Down Expand Up @@ -208,6 +313,22 @@ pub fn assert_route_is_default(route: &grpc::outbound::HttpRoute, parent: &Resou
);
}

#[track_caller]
pub fn assert_tls_route_is_default(route: &grpc::outbound::TlsRoute, parent: &Resource, port: u16) {
let kind = route.metadata.as_ref().unwrap().kind.as_ref().unwrap();
match kind {
grpc::meta::metadata::Kind::Default(_) => {}
grpc::meta::metadata::Kind::Resource(r) => {
panic!("route expected to be default but got resource {r:?}")
}
}

let backends = tls_route_backends_first_available(route);
let backend = assert_singleton(backends);
assert_tls_backend_matches_parent(backend, parent, port);
assert_singleton(&route.rules);
}

#[track_caller]
pub fn assert_backend_matches_parent(
backend: &grpc::outbound::http_route::RouteBackend,
Expand Down Expand Up @@ -254,6 +375,98 @@ pub fn assert_backend_matches_parent(
assert_resource_meta(&backend.metadata, parent, port)
}

#[track_caller]
pub fn assert_tls_backend_matches_parent(
backend: &grpc::outbound::tls_route::RouteBackend,
parent: &Resource,
port: u16,
) {
let backend = backend.backend.as_ref().unwrap();

match parent {
Resource::Service(svc) => {
let dst = match backend.kind.as_ref().unwrap() {
grpc::outbound::backend::Kind::Balancer(balance) => {
let kind = balance.discovery.as_ref().unwrap().kind.as_ref().unwrap();
match kind {
grpc::outbound::backend::endpoint_discovery::Kind::Dst(dst) => &dst.path,
}
}
grpc::outbound::backend::Kind::Forward(_) => {
panic!("service default route backend must be Balancer")
}
};
assert_eq!(
*dst,
format!(
"{}.{}.svc.{}:{}",
svc.name_unchecked(),
svc.namespace().unwrap(),
"cluster.local",
port
)
);
}

Resource::EgressNetwork(_) => {
match backend.kind.as_ref().unwrap() {
grpc::outbound::backend::Kind::Forward(_) => {}
grpc::outbound::backend::Kind::Balancer(_) => {
panic!("egress net default route backend must be Forward")
}
};
}
}

assert_resource_meta(&backend.metadata, parent, port)
}

#[track_caller]
pub fn assert_tcp_backend_matches_parent(
backend: &grpc::outbound::opaque_route::RouteBackend,
parent: &Resource,
port: u16,
) {
let backend = backend.backend.as_ref().unwrap();

match parent {
Resource::Service(svc) => {
let dst = match backend.kind.as_ref().unwrap() {
grpc::outbound::backend::Kind::Balancer(balance) => {
let kind = balance.discovery.as_ref().unwrap().kind.as_ref().unwrap();
match kind {
grpc::outbound::backend::endpoint_discovery::Kind::Dst(dst) => &dst.path,
}
}
grpc::outbound::backend::Kind::Forward(_) => {
panic!("service default route backend must be Balancer")
}
};
assert_eq!(
*dst,
format!(
"{}.{}.svc.{}:{}",
svc.name_unchecked(),
svc.namespace().unwrap(),
"cluster.local",
port
)
);
}

Resource::EgressNetwork(_) => {
match backend.kind.as_ref().unwrap() {
grpc::outbound::backend::Kind::Forward(_) => {}
grpc::outbound::backend::Kind::Balancer(_) => {
panic!("egress net default route backend must be Forward")
}
};
}
}

assert_resource_meta(&backend.metadata, parent, port)
}

#[track_caller]
pub fn assert_singleton<T>(ts: &[T]) -> &T {
assert_eq!(ts.len(), 1);
Expand All @@ -276,6 +489,16 @@ pub fn assert_route_name_eq(route: &grpc::outbound::HttpRoute, name: &str) {
assert_name_eq(route.metadata.as_ref().unwrap(), name)
}

#[track_caller]
pub fn assert_tls_route_name_eq(route: &grpc::outbound::TlsRoute, name: &str) {
assert_name_eq(route.metadata.as_ref().unwrap(), name)
}

#[track_caller]
pub fn assert_tcp_route_name_eq(route: &grpc::outbound::OpaqueRoute, name: &str) {
assert_name_eq(route.metadata.as_ref().unwrap(), name)
}

#[track_caller]
pub fn assert_name_eq(meta: &grpc::meta::Metadata, name: &str) {
let kind = meta.kind.as_ref().unwrap();
Expand Down
Loading

0 comments on commit 1668f53

Please sign in to comment.