diff --git a/policy-test/src/lib.rs b/policy-test/src/lib.rs index 0b2b21ae72189..cdf2aba7d405c 100644 --- a/policy-test/src/lib.rs +++ b/policy-test/src/lib.rs @@ -8,9 +8,10 @@ pub mod grpc; pub mod outbound_api; pub mod web; +use kube::runtime::wait::Condition; use linkerd_policy_controller_k8s_api::{ self as k8s, - policy::{httproute::ParentReference, EgressNetwork}, + policy::{httproute::ParentReference, EgressNetwork, TrafficPolicy}, ResourceExt, }; use maplit::{btreemap, convert_args}; @@ -349,6 +350,26 @@ pub fn endpoints_ready(obj: Option<&k8s::Endpoints>) -> bool { false } +pub fn egress_network_traffic_policy_is( + policy: TrafficPolicy, +) -> impl Condition + 'static { + move |egress_net: Option<&EgressNetwork>| { + if let Some(egress_net) = &egress_net { + let status = egress_net.status.clone(); + assert_status_accepted(status.map(|s| s.conditions).unwrap_or_default()); + + return egress_net.spec.traffic_policy == policy; + } + false + } +} + +pub fn assert_status_accepted(conditions: Vec) { + conditions + .iter() + .any(|c| c.type_ == "Accepted" && c.status == "True"); +} + #[tracing::instrument(skip_all, fields(%pod, %container))] pub async fn logs(client: &kube::Client, ns: &str, pod: &str, container: &str) { let params = kube::api::LogParams { diff --git a/policy-test/tests/e2e_egress_network.rs b/policy-test/tests/e2e_egress_network.rs new file mode 100644 index 0000000000000..486bb03a7c39b --- /dev/null +++ b/policy-test/tests/e2e_egress_network.rs @@ -0,0 +1,724 @@ +use k8s::policy::TrafficPolicy; +use linkerd_policy_controller_k8s_api as k8s; +use linkerd_policy_test::{ + assert_status_accepted, await_condition, await_egress_net_status, await_gateway_route_status, + await_tcp_route_status, await_tls_route_status, create, create_ready_pod, curl, + egress_network_traffic_policy_is, endpoints_ready, update, web, with_temp_ns, LinkerdInject, +}; + +#[tokio::test(flavor = "current_thread")] +async fn default_traffic_policy_http() { + with_temp_ns(|client, ns| async move { + let mut egress = create( + &client, + k8s::policy::EgressNetwork { + metadata: k8s::ObjectMeta { + namespace: Some(ns.clone()), + name: Some("egress".to_string()), + ..Default::default() + }, + spec: k8s::policy::EgressNetworkSpec { + traffic_policy: k8s::policy::TrafficPolicy::Allow, + networks: None, + }, + status: None, + }, + ) + .await; + let status = await_egress_net_status(&client, &ns, "egress").await; + assert_status_accepted(status.conditions); + + let curl = curl::Runner::init(&client, &ns).await; + let allowed = curl + .run( + "curl-allowed", + "http://httpbin.org/get", + LinkerdInject::Enabled, + ) + .await; + + let allowed_status = allowed.http_status_code().await; + assert_eq!(allowed_status, 200, "traffic should be allowed"); + + // now modify the default traffic policy + egress.spec.traffic_policy = k8s::policy::TrafficPolicy::Deny; + update(&client, egress).await; + await_condition( + &client, + &ns, + "egress", + egress_network_traffic_policy_is(TrafficPolicy::Deny), + ) + .await; + + let not_allowed = curl + .run( + "curl-not-allowed", + "http://httpbin.org/get", + LinkerdInject::Enabled, + ) + .await; + + let not_allowed_status = not_allowed.http_status_code().await; + assert_eq!(not_allowed_status, 403, "traffic should be blocked"); + }) + .await; +} + +#[tokio::test(flavor = "current_thread")] +async fn default_traffic_policy_opaque() { + with_temp_ns(|client, ns| async move { + let mut egress = create( + &client, + k8s::policy::EgressNetwork { + metadata: k8s::ObjectMeta { + namespace: Some(ns.clone()), + name: Some("egress".to_string()), + ..Default::default() + }, + spec: k8s::policy::EgressNetworkSpec { + traffic_policy: k8s::policy::TrafficPolicy::Allow, + networks: None, + }, + status: None, + }, + ) + .await; + let status = await_egress_net_status(&client, &ns, "egress").await; + assert_status_accepted(status.conditions); + + let curl = curl::Runner::init(&client, &ns).await; + let allowed = curl + .run( + "curl-allowed", + "https://httpbin.org/get", + LinkerdInject::Enabled, + ) + .await; + + let allowed_status = allowed.http_status_code().await; + assert_eq!(allowed_status, 200, "traffic should be allowed"); + + // now modify the default traffic policy + egress.spec.traffic_policy = k8s::policy::TrafficPolicy::Deny; + update(&client, egress).await; + await_condition( + &client, + &ns, + "egress", + egress_network_traffic_policy_is(TrafficPolicy::Deny), + ) + .await; + + let not_allowed = curl + .run( + "curl-not-allowed", + "https://httpbin.org/get", + LinkerdInject::Enabled, + ) + .await; + + let not_allowed_exit_code = not_allowed.exit_code().await; + assert_ne!(not_allowed_exit_code, 0, "traffic should be blocked"); + }) + .await; +} + +#[tokio::test(flavor = "current_thread")] +async fn explicit_allow_http_route() { + with_temp_ns(|client, ns| async move { + create( + &client, + k8s::policy::EgressNetwork { + metadata: k8s::ObjectMeta { + namespace: Some(ns.clone()), + name: Some("egress".to_string()), + ..Default::default() + }, + spec: k8s::policy::EgressNetworkSpec { + traffic_policy: k8s::policy::TrafficPolicy::Deny, + networks: None, + }, + status: None, + }, + ) + .await; + let status = await_egress_net_status(&client, &ns, "egress").await; + assert_status_accepted(status.conditions); + + let curl = curl::Runner::init(&client, &ns).await; + let not_allowed_get = curl + .run( + "curl-not-allowed-get", + "http://httpbin.org/get", + LinkerdInject::Enabled, + ) + .await; + + let not_allowed_get_status = not_allowed_get.http_status_code().await; + assert_eq!(not_allowed_get_status, 403, "traffic should be blocked"); + + // Now create an http route that will allow explicit hostname and explicit path + create( + &client, + k8s::gateway::HttpRoute { + metadata: k8s::ObjectMeta { + namespace: Some(ns.clone()), + name: Some("http-route".to_string()), + ..Default::default() + }, + spec: k8s::gateway::HttpRouteSpec { + inner: k8s::gateway::CommonRouteSpec { + parent_refs: Some(vec![k8s::policy::httproute::ParentReference { + namespace: None, + name: "egress".to_string(), + port: Some(80), + group: Some("policy.linkerd.io".to_string()), + kind: Some("EgressNetwork".to_string()), + section_name: None, + }]), + }, + hostnames: None, + rules: Some(vec![k8s::gateway::HttpRouteRule { + matches: Some(vec![k8s::policy::httproute::HttpRouteMatch { + path: Some(k8s::policy::httproute::HttpPathMatch::Exact { + value: "/get".to_string(), + }), + ..Default::default() + }]), + backend_refs: None, + filters: None, + }]), + }, + status: None, + }, + ) + .await; + await_gateway_route_status(&client, &ns, "http-route").await; + + // traffic should be allowed for /get request + let allowed_get = curl + .run( + "curl-allowed-get", + "http://httpbin.org/get", + LinkerdInject::Enabled, + ) + .await; + + let allowed_get_status = allowed_get.http_status_code().await; + assert_eq!(allowed_get_status, 200, "traffic should be allowed"); + + // traffic should not be allowed for /ip request + let not_allowed_ip = curl + .run( + "curl-not-allowed-ip", + "http://httpbin.org/ip", + LinkerdInject::Enabled, + ) + .await; + + let not_allowed_ip_status = not_allowed_ip.http_status_code().await; + assert_eq!(not_allowed_ip_status, 403, "traffic should not be allowed"); + }) + .await; +} + +#[tokio::test(flavor = "current_thread")] +async fn explicit_allow_tls_route() { + with_temp_ns(|client, ns| async move { + create( + &client, + k8s::policy::EgressNetwork { + metadata: k8s::ObjectMeta { + namespace: Some(ns.clone()), + name: Some("egress".to_string()), + ..Default::default() + }, + spec: k8s::policy::EgressNetworkSpec { + traffic_policy: k8s::policy::TrafficPolicy::Deny, + networks: None, + }, + status: None, + }, + ) + .await; + let status = await_egress_net_status(&client, &ns, "egress").await; + assert_status_accepted(status.conditions); + + let curl = curl::Runner::init(&client, &ns).await; + let not_allowed_httpbin = curl + .run( + "not-allowed-httpbin", + "https://httpbin.org/get", + LinkerdInject::Enabled, + ) + .await; + + let not_allowed_httpbin_exit_code = not_allowed_httpbin.exit_code().await; + assert_ne!( + not_allowed_httpbin_exit_code, 0, + "traffic should be blocked" + ); + + // Now create a tls route that will allow explicit hostname and explicit path + create( + &client, + k8s_gateway_api::TlsRoute { + metadata: k8s::ObjectMeta { + namespace: Some(ns.clone()), + name: Some("tls-route".to_string()), + ..Default::default() + }, + spec: k8s_gateway_api::TlsRouteSpec { + inner: k8s_gateway_api::CommonRouteSpec { + parent_refs: Some(vec![k8s_gateway_api::ParentReference { + namespace: None, + name: "egress".to_string(), + port: Some(443), + group: Some("policy.linkerd.io".to_string()), + kind: Some("EgressNetwork".to_string()), + section_name: None, + }]), + }, + hostnames: Some(vec!["httpbin.org".to_string()]), + rules: vec![k8s_gateway_api::TlsRouteRule { + backend_refs: vec![k8s_gateway_api::BackendRef { + weight: None, + inner: k8s_gateway_api::BackendObjectReference { + namespace: None, + name: "egress".to_string(), + port: Some(443), + group: Some("policy.linkerd.io".to_string()), + kind: Some("EgressNetwork".to_string()), + }, + }], + }], + }, + status: None, + }, + ) + .await; + await_tls_route_status(&client, &ns, "tls-route").await; + + // traffic should be allowed for httpbin + let allowed_httpbin = curl + .run( + "allowed-httpbin", + "https://httpbin.org/get", + LinkerdInject::Enabled, + ) + .await; + + let allowed_httpbin_status = allowed_httpbin.http_status_code().await; + assert_eq!(allowed_httpbin_status, 200, "traffic should be allowed"); + + // traffic should not be allowed for google.com + let not_allowed_google = curl + .run( + "curl-not-allowed-google", + "https://google.com/", + LinkerdInject::Enabled, + ) + .await; + + let not_allowed_google_exit_code = not_allowed_google.exit_code().await; + assert_ne!( + not_allowed_google_exit_code, 0, + "traffic should not be allowed" + ); + }) + .await; +} + +#[tokio::test(flavor = "current_thread")] +async fn explicit_allow_tcp_route() { + with_temp_ns(|client, ns| async move { + create( + &client, + k8s::policy::EgressNetwork { + metadata: k8s::ObjectMeta { + namespace: Some(ns.clone()), + name: Some("egress".to_string()), + ..Default::default() + }, + spec: k8s::policy::EgressNetworkSpec { + traffic_policy: k8s::policy::TrafficPolicy::Deny, + networks: None, + }, + status: None, + }, + ) + .await; + let status = await_egress_net_status(&client, &ns, "egress").await; + assert_status_accepted(status.conditions); + + let curl = curl::Runner::init(&client, &ns).await; + let not_allowed_httpbin = curl + .run( + "not-allowed-httpbin", + "https://httpbin.org/get", + LinkerdInject::Enabled, + ) + .await; + + let not_allowed_httpbin_exit_code = not_allowed_httpbin.exit_code().await; + assert_ne!( + not_allowed_httpbin_exit_code, 0, + "traffic should be blocked" + ); + + // Now create a tcp route that will allow explicit hostname and explicit path + create( + &client, + k8s_gateway_api::TcpRoute { + metadata: k8s::ObjectMeta { + namespace: Some(ns.clone()), + name: Some("tcp-route".to_string()), + ..Default::default() + }, + spec: k8s_gateway_api::TcpRouteSpec { + inner: k8s_gateway_api::CommonRouteSpec { + parent_refs: Some(vec![k8s_gateway_api::ParentReference { + namespace: None, + name: "egress".to_string(), + port: Some(443), + group: Some("policy.linkerd.io".to_string()), + kind: Some("EgressNetwork".to_string()), + section_name: None, + }]), + }, + rules: vec![k8s_gateway_api::TcpRouteRule { + backend_refs: vec![k8s_gateway_api::BackendRef { + weight: None, + inner: k8s_gateway_api::BackendObjectReference { + namespace: None, + name: "egress".to_string(), + port: Some(443), + group: Some("policy.linkerd.io".to_string()), + kind: Some("EgressNetwork".to_string()), + }, + }], + }], + }, + status: None, + }, + ) + .await; + await_tcp_route_status(&client, &ns, "tcp-route").await; + + // traffic should be allowed for httpbin on 443 + let allowed_httpbin = curl + .run( + "allowed-httpbin", + "https://httpbin.org/get", + LinkerdInject::Enabled, + ) + .await; + + let allowed_httpbin_status = allowed_httpbin.http_status_code().await; + assert_eq!(allowed_httpbin_status, 200, "traffic should be allowed"); + + // traffic should not be allowed for httpbin on 80 + let not_allowed_google = curl + .run( + "curl-not-allowed-google", + "http://google.com:80/", + LinkerdInject::Enabled, + ) + .await; + + let not_allowed_google_status = not_allowed_google.http_status_code().await; + assert_eq!( + not_allowed_google_status, 403, + "traffic should not be allowed" + ); + }) + .await; +} + +#[tokio::test(flavor = "current_thread")] +async fn routing_back_to_cluster_http_route() { + with_temp_ns(|client, ns| async move { + create( + &client, + k8s::policy::EgressNetwork { + metadata: k8s::ObjectMeta { + namespace: Some(ns.clone()), + name: Some("egress".to_string()), + ..Default::default() + }, + spec: k8s::policy::EgressNetworkSpec { + traffic_policy: k8s::policy::TrafficPolicy::Allow, + networks: None, + }, + status: None, + }, + ) + .await; + let status = await_egress_net_status(&client, &ns, "egress").await; + assert_status_accepted(status.conditions); + + // Create the web pod and wait for it to be ready. + tokio::join!( + create(&client, web::service(&ns)), + create_ready_pod(&client, web::pod(&ns)) + ); + + await_condition(&client, &ns, "web", endpoints_ready).await; + + // Now create an http route that will route requests + // back to the cluster if the request path is /get + // and will let the rest go through + create( + &client, + k8s::gateway::HttpRoute { + metadata: k8s::ObjectMeta { + namespace: Some(ns.clone()), + name: Some("http-route".to_string()), + ..Default::default() + }, + spec: k8s::gateway::HttpRouteSpec { + inner: k8s_gateway_api::CommonRouteSpec { + parent_refs: Some(vec![k8s_gateway_api::ParentReference { + namespace: None, + name: "egress".to_string(), + port: Some(80), + group: Some("policy.linkerd.io".to_string()), + kind: Some("EgressNetwork".to_string()), + section_name: None, + }]), + }, + hostnames: Some(vec!["httpbin.org".to_string()]), + rules: Some(vec![k8s::gateway::HttpRouteRule { + matches: Some(vec![k8s_gateway_api::HttpRouteMatch { + path: Some(k8s_gateway_api::HttpPathMatch::Exact { + value: "/get".to_string(), + }), + ..Default::default() + }]), + backend_refs: Some(vec![k8s_gateway_api::HttpBackendRef { + backend_ref: Some(k8s_gateway_api::BackendRef { + weight: None, + inner: k8s_gateway_api::BackendObjectReference { + namespace: Some(ns.clone()), + name: "web".to_string(), + port: Some(80), + group: None, + kind: None, + }, + }), + filters: None, + }]), + filters: None, + }]), + }, + status: None, + }, + ) + .await; + await_gateway_route_status(&client, &ns, "http-route").await; + + let curl = curl::Runner::init(&client, &ns).await; + let (in_cluster, out_of_cluster) = tokio::join!( + curl.run( + "curl-in-cluster", + "http://httpbin.org/get", + LinkerdInject::Enabled + ), + curl.run( + "curl-out-of-cluster", + "http://httpbin.org/ip", + LinkerdInject::Enabled + ), + ); + + let (in_cluster_status, out_of_cluster_status) = tokio::join!( + in_cluster.http_status_code(), + out_of_cluster.http_status_code(), + ); + + assert_eq!(in_cluster_status, 204); // in-cluster service returns 204 + assert_eq!(out_of_cluster_status, 200); // external service returns 200 + }) + .await; +} + +#[tokio::test(flavor = "current_thread")] +async fn routing_back_to_cluster_tls_route() { + with_temp_ns(|client, ns| async move { + create( + &client, + k8s::policy::EgressNetwork { + metadata: k8s::ObjectMeta { + namespace: Some(ns.clone()), + name: Some("egress".to_string()), + ..Default::default() + }, + spec: k8s::policy::EgressNetworkSpec { + traffic_policy: k8s::policy::TrafficPolicy::Allow, + networks: None, + }, + status: None, + }, + ) + .await; + let status = await_egress_net_status(&client, &ns, "egress").await; + assert_status_accepted(status.conditions); + + // Create the web pod and wait for it to be ready. + tokio::join!( + create(&client, web::service(&ns)), + create_ready_pod(&client, web::pod(&ns)) + ); + + await_condition(&client, &ns, "web", endpoints_ready).await; + + // Now create an tls route that will route requests + // to an in-cluster service based on SNI + create( + &client, + k8s_gateway_api::TlsRoute { + metadata: k8s::ObjectMeta { + namespace: Some(ns.clone()), + name: Some("tls-route".to_string()), + ..Default::default() + }, + spec: k8s_gateway_api::TlsRouteSpec { + inner: k8s_gateway_api::CommonRouteSpec { + parent_refs: Some(vec![k8s::policy::httproute::ParentReference { + namespace: None, + name: "egress".to_string(), + port: Some(443), + group: Some("policy.linkerd.io".to_string()), + kind: Some("EgressNetwork".to_string()), + section_name: None, + }]), + }, + hostnames: Some(vec!["httpbin.org".to_string()]), + rules: vec![k8s_gateway_api::TlsRouteRule { + backend_refs: vec![k8s::gateway::BackendRef { + weight: None, + inner: k8s_gateway_api::BackendObjectReference { + namespace: Some(ns.clone()), + name: "web".to_string(), + port: Some(80), + group: None, + kind: None, + }, + }], + }], + }, + status: None, + }, + ) + .await; + await_tls_route_status(&client, &ns, "tls-route").await; + + let curl = curl::Runner::init(&client, &ns).await; + let (in_cluster, out_of_cluster) = tokio::join!( + curl.run( + "curl-in-cluster", + "https://httpbin.org/get", + LinkerdInject::Enabled + ), + curl.run( + "curl-out-of-cluster", + "https://google.com/not-there", + LinkerdInject::Enabled + ), + ); + + let (in_cluster_exit_code, out_of_cluster_status) = + tokio::join!(in_cluster.exit_code(), out_of_cluster.http_status_code(),); + + assert_ne!(in_cluster_exit_code, 0); // in-cluster service fails because it does not expect TLS + assert_eq!(out_of_cluster_status, 404); // external service returns 404 as this path does not exist + }) + .await; +} + +#[tokio::test(flavor = "current_thread")] +async fn routing_back_to_cluster_tcp_route() { + with_temp_ns(|client, ns| async move { + create( + &client, + k8s::policy::EgressNetwork { + metadata: k8s::ObjectMeta { + namespace: Some(ns.clone()), + name: Some("egress".to_string()), + ..Default::default() + }, + spec: k8s::policy::EgressNetworkSpec { + traffic_policy: k8s::policy::TrafficPolicy::Allow, + networks: None, + }, + status: None, + }, + ) + .await; + let status = await_egress_net_status(&client, &ns, "egress").await; + assert_status_accepted(status.conditions); + + // Create the web pod and wait for it to be ready. + tokio::join!( + create(&client, web::service(&ns)), + create_ready_pod(&client, web::pod(&ns)) + ); + + await_condition(&client, &ns, "web", endpoints_ready).await; + + // Now create an tls route that will route requests + // to an in-cluster service based on SNI + create( + &client, + k8s_gateway_api::TcpRoute { + metadata: k8s::ObjectMeta { + namespace: Some(ns.clone()), + name: Some("tcp-route".to_string()), + ..Default::default() + }, + spec: k8s_gateway_api::TcpRouteSpec { + inner: k8s_gateway_api::CommonRouteSpec { + parent_refs: Some(vec![k8s_gateway_api::ParentReference { + namespace: None, + name: "egress".to_string(), + port: Some(80), + group: Some("policy.linkerd.io".to_string()), + kind: Some("EgressNetwork".to_string()), + section_name: None, + }]), + }, + rules: vec![k8s_gateway_api::TcpRouteRule { + backend_refs: vec![k8s::gateway::BackendRef { + weight: None, + inner: k8s_gateway_api::BackendObjectReference { + namespace: Some(ns.clone()), + name: "web".to_string(), + port: Some(80), + group: None, + kind: None, + }, + }], + }], + }, + status: None, + }, + ) + .await; + await_tcp_route_status(&client, &ns, "tcp-route").await; + + let curl = curl::Runner::init(&client, &ns).await; + let in_cluster = curl + .run( + "curl-in-cluster", + "http://httpbin.org/get", + LinkerdInject::Enabled, + ) + .await; + + let in_cluster_status = in_cluster.http_status_code().await; + + assert_eq!(in_cluster_status, 204); // in-cluster service returns 204 + }) + .await; +} diff --git a/policy-test/tests/outbound_api_egress_network.rs b/policy-test/tests/outbound_api_egress_network.rs index 99f46827453aa..b8e75a5a14407 100644 --- a/policy-test/tests/outbound_api_egress_network.rs +++ b/policy-test/tests/outbound_api_egress_network.rs @@ -1,14 +1,16 @@ use futures::prelude::*; use linkerd2_proxy_api::meta; use linkerd_policy_test::{ - await_egress_net_status, create_egress_network, delete, grpc, with_temp_ns, + assert_status_accepted, await_egress_net_status, create_egress_network, delete, grpc, + with_temp_ns, }; #[tokio::test(flavor = "current_thread")] async fn egress_switches_to_fallback() { with_temp_ns(|client, ns| async move { let egress_net = create_egress_network(&client, &ns, "egress-net").await; - await_egress_net_status(&client, &ns, "egress-net").await; + let status = await_egress_net_status(&client, &ns, "egress-net").await; + assert_status_accepted(status.conditions); let mut policy_api = grpc::OutboundPolicyClient::port_forwarded(&client).await; let mut rsp = policy_api.watch_ip(&ns, "1.1.1.1", 80).await.unwrap(); @@ -58,7 +60,8 @@ async fn fallback_switches_to_egress() { assert_eq!(meta, expected_meta); let _egress_net = create_egress_network(&client, &ns, "egress-net").await; - await_egress_net_status(&client, &ns, "egress-net").await; + let status = await_egress_net_status(&client, &ns, "egress-net").await; + assert_status_accepted(status.conditions); // stream should fall apart now assert!(rsp.next().await.is_none()); diff --git a/policy-test/tests/outbound_api_gateway.rs b/policy-test/tests/outbound_api_gateway.rs index e466a83088bb2..1e96c40f92b9c 100644 --- a/policy-test/tests/outbound_api_gateway.rs +++ b/policy-test/tests/outbound_api_gateway.rs @@ -2,11 +2,11 @@ use futures::prelude::*; use kube::ResourceExt; use linkerd_policy_controller_k8s_api as k8s; use linkerd_policy_test::{ - assert_default_accrual_backoff, assert_resource_meta, await_egress_net_status, - await_gateway_route_status, create, create_annotated_egress_network, create_annotated_service, - create_cluster_scoped, create_egress_network, create_opaque_egress_network, - create_opaque_service, create_service, delete_cluster_scoped, grpc, mk_egress_net, mk_service, - outbound_api::*, update, with_temp_ns, Resource, + assert_default_accrual_backoff, assert_resource_meta, assert_status_accepted, + await_egress_net_status, await_gateway_route_status, create, create_annotated_egress_network, + create_annotated_service, create_cluster_scoped, create_egress_network, + create_opaque_egress_network, create_opaque_service, create_service, delete_cluster_scoped, + grpc, mk_egress_net, mk_service, outbound_api::*, update, with_temp_ns, Resource, }; use maplit::{btreemap, convert_args}; use std::{collections::BTreeMap, time::Duration}; @@ -48,7 +48,8 @@ async fn egress_net_with_no_http_routes() { with_temp_ns(|client, ns| async move { // Create an egress net let egress = create_egress_network(&client, &ns, "my-egress").await; - await_egress_net_status(&client, &ns, "my-egress").await; + let status = await_egress_net_status(&client, &ns, "my-egress").await; + assert_status_accepted(status.conditions); parent_with_no_http_routes(Resource::EgressNetwork(egress), &client, &ns).await; }) @@ -70,7 +71,8 @@ async fn egress_net_with_http_route_without_rules() { with_temp_ns(|client, ns| async move { // Create an egress net let egress = create_egress_network(&client, &ns, "my-egress").await; - await_egress_net_status(&client, &ns, "my-egress").await; + let status = await_egress_net_status(&client, &ns, "my-egress").await; + assert_status_accepted(status.conditions); parent_with_http_route_without_rules(Resource::EgressNetwork(egress), &client, &ns).await; }) @@ -92,7 +94,8 @@ async fn egress_net_with_http_routes_without_backends() { with_temp_ns(|client, ns| async move { // Create an egress net let egress = create_egress_network(&client, &ns, "my-egress").await; - await_egress_net_status(&client, &ns, "my-egress").await; + let status = await_egress_net_status(&client, &ns, "my-egress").await; + assert_status_accepted(status.conditions); parent_with_http_routes_without_backends(Resource::EgressNetwork(egress), &client, &ns) .await; @@ -122,7 +125,8 @@ async fn egress_net_with_http_routes_with_backend() { with_temp_ns(|client, ns| async move { // Create a service let egress = create_egress_network(&client, &ns, "my-egress").await; - await_egress_net_status(&client, &ns, "my-egress").await; + let status = await_egress_net_status(&client, &ns, "my-egress").await; + assert_status_accepted(status.conditions); parent_with_http_routes_with_backend( Resource::EgressNetwork(egress.clone()), @@ -233,7 +237,8 @@ async fn egress_net_with_http_routes_with_invalid_backend() { with_temp_ns(|client, ns| async move { // Create an egress network let egress = create_egress_network(&client, &ns, "my-egress").await; - await_egress_net_status(&client, &ns, "my-egress").await; + let status = await_egress_net_status(&client, &ns, "my-egress").await; + assert_status_accepted(status.conditions); let backend = mk_egress_net(&ns, "invalid"); @@ -267,7 +272,8 @@ async fn egress_net_with_multiple_http_routes() { with_temp_ns(|client, ns| async move { // Create an egress net let egress = create_egress_network(&client, &ns, "my-egress").await; - await_egress_net_status(&client, &ns, "my-egress").await; + let status = await_egress_net_status(&client, &ns, "my-egress").await; + assert_status_accepted(status.conditions); parent_with_multiple_http_routes(Resource::EgressNetwork(egress), &client, &ns).await; }) @@ -342,7 +348,8 @@ async fn egress_net_with_consecutive_failure_accrual() { ]), ) .await; - await_egress_net_status(&client, &ns, "consecutive-accrual-egress").await; + let status = await_egress_net_status(&client, &ns, "consecutive-accrual-egress").await; + assert_status_accepted(status.conditions); parent_with_consecutive_failure_accrual(Resource::EgressNetwork(egress), &client, &ns) .await; @@ -458,7 +465,8 @@ async fn egress_net_with_consecutive_failure_accrual_defaults_no_config() { )]), ) .await; - await_egress_net_status(&client, &ns, "default-accrual-egress").await; + let status = await_egress_net_status(&client, &ns, "default-accrual-egress").await; + assert_status_accepted(status.conditions); parent_with_consecutive_failure_accrual_defaults_no_config( Resource::EgressNetwork(egress_no_config), @@ -491,7 +499,8 @@ async fn egress_net_with_consecutive_failure_accrual_defaults_max_fails() { ]), ) .await; - await_egress_net_status(&client, &ns, "no-backoff-egress").await; + let status = await_egress_net_status(&client, &ns, "no-backoff-egress").await; + assert_status_accepted(status.conditions); parent_with_consecutive_failure_accrual_defaults_max_fails( Resource::EgressNetwork(egress_max_fails), @@ -524,7 +533,8 @@ async fn egress_net_with_consecutive_failure_accrual_defaults_jitter() { ]), ) .await; - await_egress_net_status(&client, &ns, "only-jitter-egress").await; + let status = await_egress_net_status(&client, &ns, "only-jitter-egress").await; + assert_status_accepted(status.conditions); parent_with_consecutive_failure_accrual_defaults_max_jitter( Resource::EgressNetwork(egress_jitter), @@ -572,7 +582,8 @@ async fn egress_net_with_default_failure_accrual() { with_temp_ns(|client, ns| async move { // Default config for EgressNetwork, no failure accrual let egress_default = create_egress_network(&client, &ns, "default-failure-accrual").await; - await_egress_net_status(&client, &ns, "default-failure-accrual").await; + let status = await_egress_net_status(&client, &ns, "default-failure-accrual").await; + assert_status_accepted(status.conditions); // Create EgressNetwork with consecutive failure accrual config for // max_failures but no mode @@ -586,7 +597,8 @@ async fn egress_net_with_default_failure_accrual() { )]), ) .await; - await_egress_net_status(&client, &ns, "default-max-failure-egress").await; + let status = await_egress_net_status(&client, &ns, "default-max-failure-egress").await; + assert_status_accepted(status.conditions); parent_with_default_failure_accrual( Resource::EgressNetwork(egress_default), @@ -642,7 +654,8 @@ async fn route_with_filters_egress_net() { with_temp_ns(|client, ns| async move { // Create an egress net let egress = create_egress_network(&client, &ns, "my-egress").await; - await_egress_net_status(&client, &ns, "my-egress").await; + let status = await_egress_net_status(&client, &ns, "my-egress").await; + assert_status_accepted(status.conditions); route_with_filters( Resource::EgressNetwork(egress.clone()), @@ -677,7 +690,8 @@ async fn backend_with_filters_egress_net() { with_temp_ns(|client, ns| async move { // Create an egress net let egress = create_egress_network(&client, &ns, "my-egress").await; - await_egress_net_status(&client, &ns, "my-egress").await; + let status = await_egress_net_status(&client, &ns, "my-egress").await; + assert_status_accepted(status.conditions); backend_with_filters( Resource::EgressNetwork(egress.clone()), @@ -987,7 +1001,8 @@ async fn http_route_retries_and_timeouts_egress_net() { with_temp_ns(|client, ns| async move { // Create an egress network let egress = create_egress_network(&client, &ns, "my-egress").await; - await_egress_net_status(&client, &ns, "my-egress").await; + let status = await_egress_net_status(&client, &ns, "my-egress").await; + assert_status_accepted(status.conditions); http_route_retries_and_timeouts(Resource::EgressNetwork(egress), &client, &ns).await; }) @@ -1022,7 +1037,8 @@ async fn egress_net_retries_and_timeouts() { .annotations_mut() .insert("timeout.linkerd.io/response".to_string(), "10s".to_string()); let egress = Resource::EgressNetwork(create(&client, egress).await); - await_egress_net_status(&client, &ns, "my-egress").await; + let status = await_egress_net_status(&client, &ns, "my-egress").await; + assert_status_accepted(status.conditions); retries_and_timeouts(egress, &client, &ns).await; }) @@ -1044,7 +1060,8 @@ async fn egress_net_http_route_reattachment() { with_temp_ns(|client, ns| async move { // Create a egress net let egress = create_egress_network(&client, &ns, "my-egress").await; - await_egress_net_status(&client, &ns, "my-egress").await; + let status = await_egress_net_status(&client, &ns, "my-egress").await; + assert_status_accepted(status.conditions); http_route_reattachment(Resource::EgressNetwork(egress), &client, &ns).await; }) diff --git a/policy-test/tests/outbound_api_grpc.rs b/policy-test/tests/outbound_api_grpc.rs index 5f31f30d13047..e2493694fa53a 100644 --- a/policy-test/tests/outbound_api_grpc.rs +++ b/policy-test/tests/outbound_api_grpc.rs @@ -1,9 +1,9 @@ use futures::prelude::*; use kube::ResourceExt; use linkerd_policy_test::{ - assert_resource_meta, await_egress_net_status, await_grpc_route_status, create, - create_egress_network, create_service, mk_egress_net, mk_service, outbound_api::*, update, - with_temp_ns, Resource, + assert_resource_meta, assert_status_accepted, await_egress_net_status, await_grpc_route_status, + create, create_egress_network, create_service, mk_egress_net, mk_service, outbound_api::*, + update, with_temp_ns, Resource, }; use std::collections::BTreeMap; @@ -23,7 +23,8 @@ async fn egress_net_grpc_route_retries_and_timeouts() { // Create a egress net let egress = Resource::EgressNetwork(create_egress_network(&client, &ns, "my-egress").await); - await_egress_net_status(&client, &ns, "my-egress").await; + let status = await_egress_net_status(&client, &ns, "my-egress").await; + assert_status_accepted(status.conditions); grpc_route_retries_and_timeouts(egress, &client, &ns).await; }) @@ -58,7 +59,8 @@ async fn egress_net_retries_and_timeouts() { .annotations_mut() .insert("timeout.linkerd.io/response".to_string(), "10s".to_string()); let egress = Resource::EgressNetwork(create(&client, egress).await); - await_egress_net_status(&client, &ns, "my-egress").await; + let status = await_egress_net_status(&client, &ns, "my-egress").await; + assert_status_accepted(status.conditions); parent_retries_and_timeouts(egress, &client, &ns).await; }) @@ -80,7 +82,8 @@ async fn egress_net_grpc_route_reattachment() { with_temp_ns(|client, ns| async move { // Create a egress network let egress = create_egress_network(&client, &ns, "my-egress").await; - await_egress_net_status(&client, &ns, "my-egress").await; + let status = await_egress_net_status(&client, &ns, "my-egress").await; + assert_status_accepted(status.conditions); grpc_route_reattachment(Resource::EgressNetwork(egress), &client, &ns).await; }) diff --git a/policy-test/tests/outbound_api_linkerd.rs b/policy-test/tests/outbound_api_linkerd.rs index 93e533b482621..4e1619c8b69cd 100644 --- a/policy-test/tests/outbound_api_linkerd.rs +++ b/policy-test/tests/outbound_api_linkerd.rs @@ -4,11 +4,11 @@ use futures::prelude::*; use kube::ResourceExt; use linkerd_policy_controller_k8s_api as k8s; use linkerd_policy_test::{ - assert_default_accrual_backoff, assert_resource_meta, await_egress_net_status, - await_route_status, create, create_annotated_egress_network, create_annotated_service, - create_cluster_scoped, create_egress_network, create_opaque_egress_network, - create_opaque_service, create_service, delete_cluster_scoped, grpc, mk_egress_net, mk_service, - outbound_api::*, update, with_temp_ns, Resource, + assert_default_accrual_backoff, assert_resource_meta, assert_status_accepted, + await_egress_net_status, await_route_status, create, create_annotated_egress_network, + create_annotated_service, create_cluster_scoped, create_egress_network, + create_opaque_egress_network, create_opaque_service, create_service, delete_cluster_scoped, + grpc, mk_egress_net, mk_service, outbound_api::*, update, with_temp_ns, Resource, }; use maplit::{btreemap, convert_args}; @@ -49,7 +49,8 @@ async fn egress_net_with_no_http_routes() { with_temp_ns(|client, ns| async move { // Create an egress net let egress = create_egress_network(&client, &ns, "my-egress").await; - await_egress_net_status(&client, &ns, "my-egress").await; + let status = await_egress_net_status(&client, &ns, "my-egress").await; + assert_status_accepted(status.conditions); parent_with_no_http_routes(Resource::EgressNetwork(egress), &client, &ns).await; }) @@ -71,7 +72,8 @@ async fn egress_net_with_http_route_without_rules() { with_temp_ns(|client, ns| async move { // Create an egress net let egress = create_egress_network(&client, &ns, "my-egress").await; - await_egress_net_status(&client, &ns, "my-egress").await; + let status = await_egress_net_status(&client, &ns, "my-egress").await; + assert_status_accepted(status.conditions); parent_with_http_route_without_rules(Resource::EgressNetwork(egress), &client, &ns).await; }) @@ -93,7 +95,8 @@ async fn egress_net_with_http_routes_without_backends() { with_temp_ns(|client, ns| async move { // Create an egress net let egress = create_egress_network(&client, &ns, "my-egress").await; - await_egress_net_status(&client, &ns, "my-egress").await; + let status = await_egress_net_status(&client, &ns, "my-egress").await; + assert_status_accepted(status.conditions); parent_with_http_routes_without_backends(Resource::EgressNetwork(egress), &client, &ns) .await; @@ -123,7 +126,8 @@ async fn egress_net_with_http_routes_with_backend() { with_temp_ns(|client, ns| async move { // Create a service let egress = create_egress_network(&client, &ns, "my-egress").await; - await_egress_net_status(&client, &ns, "my-egress").await; + let status = await_egress_net_status(&client, &ns, "my-egress").await; + assert_status_accepted(status.conditions); parent_with_http_routes_with_backend( Resource::EgressNetwork(egress.clone()), @@ -234,7 +238,8 @@ async fn egress_net_with_http_routes_with_invalid_backend() { with_temp_ns(|client, ns| async move { // Create an egress network let egress = create_egress_network(&client, &ns, "my-egress").await; - await_egress_net_status(&client, &ns, "my-egress").await; + let status = await_egress_net_status(&client, &ns, "my-egress").await; + assert_status_accepted(status.conditions); let backend = mk_egress_net(&ns, "invalid"); @@ -268,7 +273,8 @@ async fn egress_net_with_multiple_http_routes() { with_temp_ns(|client, ns| async move { // Create an egress net let egress = create_egress_network(&client, &ns, "my-egress").await; - await_egress_net_status(&client, &ns, "my-egress").await; + let status = await_egress_net_status(&client, &ns, "my-egress").await; + assert_status_accepted(status.conditions); parent_with_multiple_http_routes(Resource::EgressNetwork(egress), &client, &ns).await; }) @@ -343,7 +349,8 @@ async fn egress_net_with_consecutive_failure_accrual() { ]), ) .await; - await_egress_net_status(&client, &ns, "consecutive-accrual-egress").await; + let status = await_egress_net_status(&client, &ns, "consecutive-accrual-egress").await; + assert_status_accepted(status.conditions); parent_with_consecutive_failure_accrual(Resource::EgressNetwork(egress), &client, &ns) .await; @@ -459,7 +466,8 @@ async fn egress_net_with_consecutive_failure_accrual_defaults_no_config() { )]), ) .await; - await_egress_net_status(&client, &ns, "default-accrual-egress").await; + let status = await_egress_net_status(&client, &ns, "default-accrual-egress").await; + assert_status_accepted(status.conditions); parent_with_consecutive_failure_accrual_defaults_no_config( Resource::EgressNetwork(egress_no_config), @@ -492,7 +500,8 @@ async fn egress_net_with_consecutive_failure_accrual_defaults_max_fails() { ]), ) .await; - await_egress_net_status(&client, &ns, "no-backoff-egress").await; + let status = await_egress_net_status(&client, &ns, "no-backoff-egress").await; + assert_status_accepted(status.conditions); parent_with_consecutive_failure_accrual_defaults_max_fails( Resource::EgressNetwork(egress_max_fails), @@ -525,7 +534,8 @@ async fn egress_net_with_consecutive_failure_accrual_defaults_jitter() { ]), ) .await; - await_egress_net_status(&client, &ns, "only-jitter-egress").await; + let status = await_egress_net_status(&client, &ns, "only-jitter-egress").await; + assert_status_accepted(status.conditions); parent_with_consecutive_failure_accrual_defaults_max_jitter( Resource::EgressNetwork(egress_jitter), @@ -573,7 +583,8 @@ async fn egress_net_with_default_failure_accrual() { with_temp_ns(|client, ns| async move { // Default config for EgressNetwork, no failure accrual let egress_default = create_egress_network(&client, &ns, "default-failure-accrual").await; - await_egress_net_status(&client, &ns, "default-failure-accrual").await; + let status = await_egress_net_status(&client, &ns, "default-failure-accrual").await; + assert_status_accepted(status.conditions); // Create EgressNetwork with consecutive failure accrual config for // max_failures but no mode @@ -587,7 +598,8 @@ async fn egress_net_with_default_failure_accrual() { )]), ) .await; - await_egress_net_status(&client, &ns, "default-max-failure-egress").await; + let status = await_egress_net_status(&client, &ns, "default-max-failure-egress").await; + assert_status_accepted(status.conditions); parent_with_default_failure_accrual( Resource::EgressNetwork(egress_default), @@ -643,7 +655,8 @@ async fn route_with_filters_egress_net() { with_temp_ns(|client, ns| async move { // Create an egress net let egress = create_egress_network(&client, &ns, "my-egress").await; - await_egress_net_status(&client, &ns, "my-egress").await; + let status = await_egress_net_status(&client, &ns, "my-egress").await; + assert_status_accepted(status.conditions); route_with_filters( Resource::EgressNetwork(egress.clone()), @@ -678,7 +691,8 @@ async fn backend_with_filters_egress_net() { with_temp_ns(|client, ns| async move { // Create an egress net let egress = create_egress_network(&client, &ns, "my-egress").await; - await_egress_net_status(&client, &ns, "my-egress").await; + let status = await_egress_net_status(&client, &ns, "my-egress").await; + assert_status_accepted(status.conditions); backend_with_filters( Resource::EgressNetwork(egress.clone()), @@ -988,7 +1002,8 @@ async fn http_route_retries_and_timeouts_egress_net() { with_temp_ns(|client, ns| async move { // Create an egress network let egress = create_egress_network(&client, &ns, "my-egress").await; - await_egress_net_status(&client, &ns, "my-egress").await; + let status = await_egress_net_status(&client, &ns, "my-egress").await; + assert_status_accepted(status.conditions); http_route_retries_and_timeouts(Resource::EgressNetwork(egress), &client, &ns).await; }) @@ -1023,7 +1038,8 @@ async fn egress_net_retries_and_timeouts() { .annotations_mut() .insert("timeout.linkerd.io/response".to_string(), "10s".to_string()); let egress = Resource::EgressNetwork(create(&client, egress).await); - await_egress_net_status(&client, &ns, "my-egress").await; + let status = await_egress_net_status(&client, &ns, "my-egress").await; + assert_status_accepted(status.conditions); retries_and_timeouts(egress, &client, &ns).await; }) @@ -1045,7 +1061,8 @@ async fn egress_net_http_route_reattachment() { with_temp_ns(|client, ns| async move { // Create a egress net let egress = create_egress_network(&client, &ns, "my-egress").await; - await_egress_net_status(&client, &ns, "my-egress").await; + let status = await_egress_net_status(&client, &ns, "my-egress").await; + assert_status_accepted(status.conditions); http_route_reattachment(Resource::EgressNetwork(egress), &client, &ns).await; }) diff --git a/policy-test/tests/outbound_api_tcp.rs b/policy-test/tests/outbound_api_tcp.rs index 52db12b6e5f17..7749a6fa92fe0 100644 --- a/policy-test/tests/outbound_api_tcp.rs +++ b/policy-test/tests/outbound_api_tcp.rs @@ -1,8 +1,8 @@ use futures::prelude::*; use linkerd_policy_controller_k8s_api as k8s; use linkerd_policy_test::{ - assert_resource_meta, await_egress_net_status, await_tcp_route_status, create, - create_cluster_scoped, create_egress_network, create_service, delete_cluster_scoped, + assert_resource_meta, assert_status_accepted, await_egress_net_status, await_tcp_route_status, + create, create_cluster_scoped, create_egress_network, create_service, delete_cluster_scoped, mk_egress_net, mk_service, outbound_api::*, update, with_temp_ns, Resource, }; use maplit::{btreemap, convert_args}; @@ -29,7 +29,8 @@ async fn egress_net_with_tcp_routes_with_backend() { with_temp_ns(|client, ns| async move { // Create a service let egress = create_egress_network(&client, &ns, "my-egress").await; - await_egress_net_status(&client, &ns, "my-egress").await; + let status = await_egress_net_status(&client, &ns, "my-egress").await; + assert_status_accepted(status.conditions); parent_with_tcp_routes_with_backend( Resource::EgressNetwork(egress.clone()), @@ -115,7 +116,8 @@ async fn egress_net_with_tcp_routes_with_invalid_backend() { with_temp_ns(|client, ns| async move { // Create an egress network let egress = create_egress_network(&client, &ns, "my-egress").await; - await_egress_net_status(&client, &ns, "my-egress").await; + let status = await_egress_net_status(&client, &ns, "my-egress").await; + assert_status_accepted(status.conditions); let backend = mk_egress_net(&ns, "invalid"); @@ -145,7 +147,8 @@ async fn egress_net_with_multiple_tcp_routes() { with_temp_ns(|client, ns| async move { // Create an egress net let egress = create_egress_network(&client, &ns, "my-egress").await; - await_egress_net_status(&client, &ns, "my-egress").await; + let status = await_egress_net_status(&client, &ns, "my-egress").await; + assert_status_accepted(status.conditions); parent_with_multiple_tcp_routes(Resource::EgressNetwork(egress), &client, &ns).await; }) @@ -390,7 +393,8 @@ async fn egress_net_tcp_route_reattachment() { with_temp_ns(|client, ns| async move { // Create a egress net let egress = create_egress_network(&client, &ns, "my-egress").await; - await_egress_net_status(&client, &ns, "my-egress").await; + let status = await_egress_net_status(&client, &ns, "my-egress").await; + assert_status_accepted(status.conditions); tcp_route_reattachment(Resource::EgressNetwork(egress), &client, &ns).await; }) diff --git a/policy-test/tests/outbound_api_tls.rs b/policy-test/tests/outbound_api_tls.rs index b2fd4d015cf57..cf7569dd15040 100644 --- a/policy-test/tests/outbound_api_tls.rs +++ b/policy-test/tests/outbound_api_tls.rs @@ -1,9 +1,9 @@ use futures::prelude::*; use linkerd_policy_controller_k8s_api as k8s; use linkerd_policy_test::{ - assert_resource_meta, await_egress_net_status, await_tls_route_status, create, - create_cluster_scoped, create_egress_network, create_service, delete_cluster_scoped, grpc, - mk_egress_net, mk_service, outbound_api::*, update, with_temp_ns, Resource, + assert_resource_meta, assert_status_accepted, await_egress_net_status, await_tls_route_status, + create, create_cluster_scoped, create_egress_network, create_service, delete_cluster_scoped, + grpc, mk_egress_net, mk_service, outbound_api::*, update, with_temp_ns, Resource, }; use maplit::{btreemap, convert_args}; @@ -29,7 +29,8 @@ async fn egress_net_with_tls_routes_with_backend() { with_temp_ns(|client, ns| async move { // Create a service let egress = create_egress_network(&client, &ns, "my-egress").await; - await_egress_net_status(&client, &ns, "my-egress").await; + let status = await_egress_net_status(&client, &ns, "my-egress").await; + assert_status_accepted(status.conditions); parent_with_tls_routes_with_backend( Resource::EgressNetwork(egress.clone()), @@ -115,7 +116,8 @@ async fn egress_net_with_tls_routes_with_invalid_backend() { with_temp_ns(|client, ns| async move { // Create an egress network let egress = create_egress_network(&client, &ns, "my-egress").await; - await_egress_net_status(&client, &ns, "my-egress").await; + let status = await_egress_net_status(&client, &ns, "my-egress").await; + assert_status_accepted(status.conditions); let backend = mk_egress_net(&ns, "invalid"); @@ -145,7 +147,8 @@ async fn egress_net_with_multiple_http_routes() { with_temp_ns(|client, ns| async move { // Create an egress net let egress = create_egress_network(&client, &ns, "my-egress").await; - await_egress_net_status(&client, &ns, "my-egress").await; + let status = await_egress_net_status(&client, &ns, "my-egress").await; + assert_status_accepted(status.conditions); parent_with_multiple_tls_routes(Resource::EgressNetwork(egress), &client, &ns).await; }) @@ -390,7 +393,8 @@ async fn egress_net_tls_route_reattachment() { with_temp_ns(|client, ns| async move { // Create a egress net let egress = create_egress_network(&client, &ns, "my-egress").await; - await_egress_net_status(&client, &ns, "my-egress").await; + let status = await_egress_net_status(&client, &ns, "my-egress").await; + assert_status_accepted(status.conditions); tls_route_reattachment(Resource::EgressNetwork(egress), &client, &ns).await; })