diff --git a/src/app/config.rs b/src/app/config.rs index efe4a364e1..f3aa78e7c2 100644 --- a/src/app/config.rs +++ b/src/app/config.rs @@ -31,7 +31,7 @@ pub struct Config { pub inbound_listener: Listener, /// Where to listen for connections initiated by the control plane. - pub control_listener: Listener, + pub control_listener: Option, /// Where to serve admin HTTP. pub admin_listener: Listener, @@ -278,6 +278,7 @@ pub const ENV_DESTINATION_CONTEXT: &str = "LINKERD2_PROXY_DESTINATION_CONTEXT"; pub const ENV_CONTROL_EXP_BACKOFF_MIN: &str = "LINKERD2_PROXY_CONTROL_EXP_BACKOFF_MIN"; pub const ENV_CONTROL_EXP_BACKOFF_MAX: &str = "LINKERD2_PROXY_CONTROL_EXP_BACKOFF_MAX"; pub const ENV_CONTROL_EXP_BACKOFF_JITTER: &str = "LINKERD2_PROXY_CONTROL_EXP_BACKOFF_JITTER"; +pub const ENV_TAP_DISABLED: &str = "LINKERD2_PROXY_TAP_DISABLED"; const ENV_CONTROL_CONNECT_TIMEOUT: &str = "LINKERD2_PROXY_CONTROL_CONNECT_TIMEOUT"; const ENV_CONTROL_DISPATCH_TIMEOUT: &str = "LINKERD2_PROXY_CONTROL_DISPATCH_TIMEOUT"; const ENV_RESOLV_CONF: &str = "LINKERD2_PROXY_RESOLV_CONF"; @@ -382,7 +383,6 @@ impl Config { // defer returning any errors until all of them have been parsed. let outbound_listener_addr = parse(strings, ENV_OUTBOUND_LISTEN_ADDR, parse_socket_addr); let inbound_listener_addr = parse(strings, ENV_INBOUND_LISTEN_ADDR, parse_socket_addr); - let control_listener_addr = parse(strings, ENV_CONTROL_LISTEN_ADDR, parse_socket_addr); let admin_listener_addr = parse(strings, ENV_ADMIN_LISTEN_ADDR, parse_socket_addr); let inbound_forward = parse(strings, ENV_INBOUND_FORWARD, parse_socket_addr); @@ -464,6 +464,8 @@ impl Config { let initial_connection_window_size = parse(strings, ENV_INITIAL_CONNECTION_WINDOW_SIZE, parse_number); + let control_listener = parse_control_listener(strings); + Ok(Config { outbound_listener: Listener { addr: outbound_listener_addr? @@ -473,10 +475,7 @@ impl Config { addr: inbound_listener_addr? .unwrap_or_else(|| parse_socket_addr(DEFAULT_INBOUND_LISTEN_ADDR).unwrap()), }, - control_listener: Listener { - addr: control_listener_addr? - .unwrap_or_else(|| parse_socket_addr(DEFAULT_CONTROL_LISTEN_ADDR).unwrap()), - }, + control_listener: control_listener?, admin_listener: Listener { addr: admin_listener_addr? .unwrap_or_else(|| parse_socket_addr(DEFAULT_ADMIN_LISTEN_ADDR).unwrap()), @@ -614,6 +613,21 @@ impl Strings for TestEnv { // ===== Parsing ===== +fn parse_control_listener(strings: &Strings) -> Result, Error> { + let tap_disabled = strings + .get(ENV_TAP_DISABLED)? + .map(|d| !d.is_empty()) + .unwrap_or(false); + + if tap_disabled { + Ok(None) + } else { + let addr = parse(strings, ENV_CONTROL_LISTEN_ADDR, parse_socket_addr)? + .unwrap_or_else(|| parse_socket_addr(DEFAULT_CONTROL_LISTEN_ADDR).unwrap()); + Ok(Some(Listener { addr })) + } +} + fn parse_number(s: &str) -> Result where T: FromStr, diff --git a/src/app/main.rs b/src/app/main.rs index 80d026cf1e..6195251b66 100644 --- a/src/app/main.rs +++ b/src/app/main.rs @@ -64,7 +64,7 @@ struct ProxyParts { start_time: SystemTime, admin_listener: Listen, - control_listener: Listen, + control_listener: Option>, inbound_listener: Listen, outbound_listener: Listen, @@ -96,8 +96,10 @@ where let identity = config.identity_config.as_ref().map(identity::Local::new); let local_identity = identity.as_ref().map(|(l, _)| l.clone()); - let control_listener = Listen::bind(config.control_listener.addr, local_identity.clone()) - .expect("dst_svc listener bind"); + let control_listener = config + .control_listener + .as_ref() + .map(|l| Listen::bind(l.addr, local_identity.clone()).expect("dst_svc listener bind")); let admin_listener = Listen::bind(config.admin_listener.addr, local_identity.clone()) .expect("metrics listener bind"); @@ -135,8 +137,11 @@ where } } - pub fn control_addr(&self) -> SocketAddr { - self.proxy_parts.control_listener.local_addr() + pub fn control_addr(&self) -> Option { + self.proxy_parts + .control_listener + .as_ref() + .map(|l| l.local_addr().clone()) } pub fn inbound_addr(&self) -> SocketAddr { @@ -378,8 +383,10 @@ where Admin::new(report, readiness), )); - rt.spawn(tap_daemon.map_err(|_| ())); - rt.spawn(serve_tap(control_listener, TapServer::new(tap_grpc))); + if let Some(listener) = control_listener { + rt.spawn(tap_daemon.map_err(|_| ())); + rt.spawn(serve_tap(listener, TapServer::new(tap_grpc))); + } rt.spawn(::logging::admin().bg("dns-resolver").future(dns_bg)); diff --git a/tests/support/proxy.rs b/tests/support/proxy.rs index 840206a2d0..307c52c351 100644 --- a/tests/support/proxy.rs +++ b/tests/support/proxy.rs @@ -19,7 +19,7 @@ pub struct Proxy { } pub struct Listening { - pub control: SocketAddr, + pub control: Option, pub inbound: SocketAddr, pub outbound: SocketAddr, pub metrics: SocketAddr, @@ -273,7 +273,10 @@ fn run(proxy: Proxy, mut env: app::config::TestEnv) -> Listening { // printlns will show if the test fails... println!( "proxy running; destination={}, identity={:?}, inbound={}{}, outbound={}{}, metrics={}", - control_addr, + control_addr + .as_ref() + .map(SocketAddr::to_string) + .unwrap_or_else(String::new), identity_addr, inbound_addr, inbound diff --git a/tests/tap.rs b/tests/tap.rs index 79ed612c29..ea21757c51 100644 --- a/tests/tap.rs +++ b/tests/tap.rs @@ -15,7 +15,7 @@ fn inbound_http1() { let proxy = proxy::new().inbound(srv).run(); - let mut tap = tap::client(proxy.control); + let mut tap = tap::client(proxy.control.unwrap()); let events = tap.observe(tap::observe_request()); let authority = "tap.test.svc.cluster.local"; @@ -54,7 +54,7 @@ fn grpc_headers_end() { let proxy = proxy::new().inbound(srv).run(); - let mut tap = tap::client(proxy.control); + let mut tap = tap::client(proxy.control.unwrap()); let events = tap.observe(tap::observe_request()); let authority = "tap.test.svc.cluster.local"; @@ -73,3 +73,22 @@ fn grpc_headers_end() { assert_eq!(ev.response_end_eos_grpc(), 1); } + +#[test] +fn tap_enabled_by_default() { + let _ = env_logger_init(); + let proxy = proxy::new().run(); + + assert!(proxy.control.is_some()) +} + +#[test] +fn can_disable_tap() { + let _ = env_logger_init(); + let mut env = app::config::TestEnv::new(); + env.put(app::config::ENV_TAP_DISABLED, "true".to_owned()); + + let proxy = proxy::new().run_with_test_env(env); + + assert!(proxy.control.is_none()) +}