Skip to content

Commit

Permalink
dns: add ability to set dns failure refresh rate (#714)
Browse files Browse the repository at this point in the history
Description: updates envoy ref to include envoyproxy/envoy#10137. Exposes client builder function to add dns failure refresh rate.
Risk Level: low, new configuration option
Testing: local apps, CI
Docs Changes: created #715 to create a section in the docs for all the builder options.

Fixes #673
  • Loading branch information
junr03 authored Mar 2, 2020
1 parent e3cebfe commit 824ba9d
Show file tree
Hide file tree
Showing 11 changed files with 120 additions and 50 deletions.
2 changes: 1 addition & 1 deletion envoy
Submodule envoy updated 484 files
35 changes: 10 additions & 25 deletions library/common/config_template.cc
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,13 @@ const char* config_template = R"(
- name: envoy.filters.http.dynamic_forward_proxy
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.dynamic_forward_proxy.v3.FilterConfig
dns_cache_config:
dns_cache_config: &dns_cache_config
name: dynamic_forward_proxy_cache_config
dns_lookup_family: AUTO
dns_refresh_rate: {{ dns_refresh_rate_seconds }}s
dns_failure_refresh_rate:
base_interval: {{ dns_failure_refresh_rate_seconds_base }}s
max_interval: {{ dns_failure_refresh_rate_seconds_max }}s
- name: envoy.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
Expand All @@ -48,10 +51,7 @@ const char* config_template = R"(
name: envoy.clusters.dynamic_forward_proxy
typed_config:
"@type": type.googleapis.com/envoy.extensions.clusters.dynamic_forward_proxy.v3.ClusterConfig
dns_cache_config:
name: dynamic_forward_proxy_cache_config
dns_lookup_family: AUTO
dns_refresh_rate: {{ dns_refresh_rate_seconds }}s
dns_cache_config: *dns_cache_config
transport_socket: &base_transport_socket
name: envoy.transport_sockets.tls
typed_config:
Expand All @@ -75,10 +75,7 @@ const char* config_template = R"(
name: envoy.clusters.dynamic_forward_proxy
typed_config:
"@type": type.googleapis.com/envoy.extensions.clusters.dynamic_forward_proxy.v3.ClusterConfig
dns_cache_config:
name: dynamic_forward_proxy_cache_config
dns_lookup_family: AUTO
dns_refresh_rate: {{ dns_refresh_rate_seconds }}s
dns_cache_config: *dns_cache_config
transport_socket: *base_transport_socket
upstream_connection_options: *upstream_opts
- name: base_wwan
Expand All @@ -88,10 +85,7 @@ const char* config_template = R"(
name: envoy.clusters.dynamic_forward_proxy
typed_config:
"@type": type.googleapis.com/envoy.extensions.clusters.dynamic_forward_proxy.v3.ClusterConfig
dns_cache_config:
name: dynamic_forward_proxy_cache_config
dns_lookup_family: AUTO
dns_refresh_rate: {{ dns_refresh_rate_seconds }}s
dns_cache_config: *dns_cache_config
transport_socket: *base_transport_socket
upstream_connection_options: *upstream_opts
- name: base_h2
Expand All @@ -102,10 +96,7 @@ const char* config_template = R"(
name: envoy.clusters.dynamic_forward_proxy
typed_config:
"@type": type.googleapis.com/envoy.extensions.clusters.dynamic_forward_proxy.v3.ClusterConfig
dns_cache_config:
name: dynamic_forward_proxy_cache_config
dns_lookup_family: AUTO
dns_refresh_rate: {{ dns_refresh_rate_seconds }}s
dns_cache_config: *dns_cache_config
transport_socket: *base_transport_socket
upstream_connection_options: *upstream_opts
- name: base_wlan_h2
Expand All @@ -116,10 +107,7 @@ const char* config_template = R"(
name: envoy.clusters.dynamic_forward_proxy
typed_config:
"@type": type.googleapis.com/envoy.extensions.clusters.dynamic_forward_proxy.v3.ClusterConfig
dns_cache_config:
name: dynamic_forward_proxy_cache_config
dns_lookup_family: AUTO
dns_refresh_rate: {{ dns_refresh_rate_seconds }}s
dns_cache_config: *dns_cache_config
transport_socket: *base_transport_socket
upstream_connection_options: *upstream_opts
- name: base_wwan_h2
Expand All @@ -130,10 +118,7 @@ const char* config_template = R"(
name: envoy.clusters.dynamic_forward_proxy
typed_config:
"@type": type.googleapis.com/envoy.extensions.clusters.dynamic_forward_proxy.v3.ClusterConfig
dns_cache_config:
name: dynamic_forward_proxy_cache_config
dns_lookup_family: AUTO
dns_refresh_rate: {{ dns_refresh_rate_seconds }}s
dns_cache_config: *dns_cache_config
transport_socket: *base_transport_socket
upstream_connection_options: *upstream_opts
- name: stats
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,29 @@ public class EnvoyConfiguration {
public final String statsDomain;
public final Integer connectTimeoutSeconds;
public final Integer dnsRefreshSeconds;
public final Integer dnsFailureRefreshSecondsBase;
public final Integer dnsFailureRefreshSecondsMax;
public final Integer statsFlushSeconds;

/**
* Create an EnvoyConfiguration with a user provided configuration values.
*
* @param statsDomain The domain to flush stats to.
* @param connectTimeoutSeconds timeout for new network connections to hosts in
* the cluster.
* @param dnsRefreshSeconds rate in seconds to refresh DNS.
* @param statsFlushSeconds interval at which to flush Envoy stats.
* @param statsDomain the domain to flush stats to.
* @param connectTimeoutSeconds timeout for new network connections to hosts in
* the cluster.
* @param dnsRefreshSeconds rate in seconds to refresh DNS.
* @param dnsFailureRefreshSecondsBase base rate in seconds to refresh DNS on failure.
* @param dnsFailureRefreshSecondsMax max rate in seconds to refresh DNS on failure.
* @param statsFlushSeconds interval at which to flush Envoy stats.
*/
public EnvoyConfiguration(String statsDomain, int connectTimeoutSeconds, int dnsRefreshSeconds,
int dnsFailureRefreshSecondsBase, int dnsFailureRefreshSecondsMax,
int statsFlushSeconds) {
this.statsDomain = statsDomain;
this.connectTimeoutSeconds = connectTimeoutSeconds;
this.dnsRefreshSeconds = dnsRefreshSeconds;
this.dnsFailureRefreshSecondsBase = dnsFailureRefreshSecondsBase;
this.dnsFailureRefreshSecondsMax = dnsFailureRefreshSecondsMax;
this.statsFlushSeconds = statsFlushSeconds;
}

Expand All @@ -38,6 +45,10 @@ String resolveTemplate(String templateYAML) {
templateYAML.replace("{{ stats_domain }}", String.format("%s", statsDomain))
.replace("{{ connect_timeout_seconds }}", String.format("%s", connectTimeoutSeconds))
.replace("{{ dns_refresh_rate_seconds }}", String.format("%s", dnsRefreshSeconds))
.replace("{{ dns_failure_refresh_rate_seconds_base }}",
String.format("%s", dnsFailureRefreshSecondsBase))
.replace("{{ dns_failure_refresh_rate_seconds_max }}",
String.format("%s", dnsFailureRefreshSecondsMax))
.replace("{{ stats_flush_interval_seconds }}", String.format("%s", statsFlushSeconds))
.replace("{{ device_os }}", "Android");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ mock_template:
stats_domain: {{ stats_domain }}
connect_timeout: {{ connect_timeout_seconds }}s
dns_refresh_rate: {{ dns_refresh_rate_seconds }}s
dns_failure_refresh_rate:
base_interval: {{ dns_failure_refresh_rate_seconds_base }}s
max_interval: {{ dns_failure_refresh_rate_seconds_max }}s
stats_flush_interval: {{ stats_flush_interval_seconds }}s
os: {{ device_os }}
"""
Expand All @@ -18,20 +21,22 @@ class EnvoyConfigurationTest {

@Test
fun `resolving with default configuration resolves with values`() {
val envoyConfiguration = EnvoyConfiguration("stats.foo.com", 123, 234, 345)
val envoyConfiguration = EnvoyConfiguration("stats.foo.com", 123, 234, 345, 456, 567)

val resolvedTemplate = envoyConfiguration.resolveTemplate(TEST_CONFIG)
assertThat(resolvedTemplate).contains("stats_domain: stats.foo.com")
assertThat(resolvedTemplate).contains("connect_timeout: 123s")
assertThat(resolvedTemplate).contains("dns_refresh_rate: 234s")
assertThat(resolvedTemplate).contains("stats_flush_interval: 345s")
assertThat(resolvedTemplate).contains("base_interval: 345s")
assertThat(resolvedTemplate).contains("max_interval: 456s")
assertThat(resolvedTemplate).contains("stats_flush_interval: 567s")
assertThat(resolvedTemplate).contains("os: Android")
}


@Test(expected = EnvoyConfiguration.ConfigurationException::class)
fun `resolve templates with invalid templates will throw on build`() {
val envoyConfiguration = EnvoyConfiguration("stats.foo.com", 123, 234, 345)
val envoyConfiguration = EnvoyConfiguration("stats.foo.com", 123, 234, 345, 456, 567)

envoyConfiguration.resolveTemplate("{{ }}")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ open class EnvoyClientBuilder(
private var statsDomain = "0.0.0.0"
private var connectTimeoutSeconds = 30
private var dnsRefreshSeconds = 60
private var dnsFailureRefreshSecondsBase = 2
private var dnsFailureRefreshSecondsMax = 10
private var statsFlushSeconds = 60

/**
Expand Down Expand Up @@ -58,6 +60,18 @@ open class EnvoyClientBuilder(
return this
}

/**
* Add a rate at which to refresh DNS in case of DNS failure.
*
* @param base rate in seconds.
* @param max rate in seconds.
*/
fun addDNSFailureRefreshSeconds(base: Int, max: Int): EnvoyClientBuilder {
this.dnsFailureRefreshSecondsBase = base
this.dnsFailureRefreshSecondsMax = max
return this
}

/**
* Add an interval at which to flush Envoy stats.
*
Expand All @@ -79,7 +93,7 @@ open class EnvoyClientBuilder(
return Envoy(engineType(), configuration.yaml, logLevel)
}
is Standard -> {
Envoy(engineType(), EnvoyConfiguration(statsDomain, connectTimeoutSeconds, dnsRefreshSeconds, statsFlushSeconds), logLevel)
Envoy(engineType(), EnvoyConfiguration(statsDomain, connectTimeoutSeconds, dnsRefreshSeconds, dnsFailureRefreshSecondsBase, dnsFailureRefreshSecondsMax, statsFlushSeconds), logLevel)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,6 @@ import org.assertj.core.api.Assertions.assertThat
import org.junit.Test
import org.mockito.Mockito.mock

private const val TEST_CONFIG = """
mock_template:
- name: mock
connect_timeout: {{ connect_timeout_seconds }}
dns_refresh_rate: {{ dns_refresh_rate_seconds }}
stats_flush_interval: {{ stats_flush_interval_seconds }}
stats_domain: {{ stats_domain }}
os: {{ device_os }}
"""

class EnvoyBuilderTest {

private lateinit var clientBuilder: EnvoyClientBuilder
Expand All @@ -23,7 +13,7 @@ class EnvoyBuilderTest {

@Test
fun `adding log level builder uses log level for running Envoy`() {
clientBuilder = EnvoyClientBuilder(Custom(TEST_CONFIG))
clientBuilder = EnvoyClientBuilder(Standard())
clientBuilder.addEngineType { engine }

clientBuilder.addLogLevel(LogLevel.DEBUG)
Expand Down Expand Up @@ -61,6 +51,17 @@ class EnvoyBuilderTest {
assertThat(envoy.envoyConfiguration!!.dnsRefreshSeconds).isEqualTo(1234)
}

@Test
fun `specifying DNS failure refresh overrides default`() {
clientBuilder = EnvoyClientBuilder(Standard())
clientBuilder.addEngineType { engine }

clientBuilder.addDNSFailureRefreshSeconds(1234, 5678)
val envoy = clientBuilder.build()
assertThat(envoy.envoyConfiguration!!.dnsFailureRefreshSecondsBase).isEqualTo(1234)
assertThat(envoy.envoyConfiguration!!.dnsFailureRefreshSecondsMax).isEqualTo(5678)
}

@Test
fun `specifying stats flush overrides default`() {
clientBuilder = EnvoyClientBuilder(Standard())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class EnvoyClientTest {

private val engine = mock(EnvoyEngine::class.java)
private val stream = mock(EnvoyHTTPStream::class.java)
private val config = EnvoyConfiguration("stats.foo.com", 0, 0, 0)
private val config = EnvoyConfiguration("stats.foo.com", 0, 0, 0, 0, 0)

@Test
fun `starting a stream on envoy sends headers`() {
Expand Down
8 changes: 8 additions & 0 deletions library/objective-c/EnvoyConfiguration.m
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ @implementation EnvoyConfiguration
- (instancetype)initWithStatsDomain:(NSString *)statsDomain
connectTimeoutSeconds:(UInt32)connectTimeoutSeconds
dnsRefreshSeconds:(UInt32)dnsRefreshSeconds
dnsFailureRefreshSecondsBase:(UInt32)dnsFailureRefreshSecondsBase
dnsFailureRefreshSecondsMax:(UInt32)dnsFailureRefreshSecondsMax
statsFlushSeconds:(UInt32)statsFlushSeconds {
self = [super init];
if (!self) {
Expand All @@ -16,6 +18,8 @@ - (instancetype)initWithStatsDomain:(NSString *)statsDomain
self.statsDomain = statsDomain;
self.connectTimeoutSeconds = connectTimeoutSeconds;
self.dnsRefreshSeconds = dnsRefreshSeconds;
self.dnsFailureRefreshSecondsBase = dnsFailureRefreshSecondsBase;
self.dnsFailureRefreshSecondsMax = dnsFailureRefreshSecondsMax;
self.statsFlushSeconds = statsFlushSeconds;
return self;
}
Expand All @@ -27,6 +31,10 @@ - (nullable NSString *)resolveTemplate:(NSString *)templateYAML {
[NSString stringWithFormat:@"%lu", (unsigned long)self.connectTimeoutSeconds],
@"dns_refresh_rate_seconds" :
[NSString stringWithFormat:@"%lu", (unsigned long)self.dnsRefreshSeconds],
@"dns_failure_refresh_rate_seconds_base" :
[NSString stringWithFormat:@"%lu", (unsigned long)self.dnsFailureRefreshSecondsBase],
@"dns_failure_refresh_rate_seconds_max" :
[NSString stringWithFormat:@"%lu", (unsigned long)self.dnsFailureRefreshSecondsMax],
@"stats_flush_interval_seconds" :
[NSString stringWithFormat:@"%lu", (unsigned long)self.statsFlushSeconds],
@"device_os" : @"iOS"
Expand Down
4 changes: 4 additions & 0 deletions library/objective-c/EnvoyEngine.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,8 @@ typedef NSDictionary<NSString *, NSArray<NSString *> *> EnvoyHeaders;
@property (nonatomic, strong) NSString *statsDomain;
@property (nonatomic, assign) UInt32 connectTimeoutSeconds;
@property (nonatomic, assign) UInt32 dnsRefreshSeconds;
@property (nonatomic, assign) UInt32 dnsFailureRefreshSecondsBase;
@property (nonatomic, assign) UInt32 dnsFailureRefreshSecondsMax;
@property (nonatomic, assign) UInt32 statsFlushSeconds;

/**
Expand All @@ -141,6 +143,8 @@ typedef NSDictionary<NSString *, NSArray<NSString *> *> EnvoyHeaders;
- (instancetype)initWithStatsDomain:(NSString *)statsDomain
connectTimeoutSeconds:(UInt32)connectTimeoutSeconds
dnsRefreshSeconds:(UInt32)dnsRefreshSeconds
dnsFailureRefreshSecondsBase:(UInt32)dnsFailureRefreshSecondsBase
dnsFailureRefreshSecondsMax:(UInt32)dnsFailureRefreshSecondsMax
statsFlushSeconds:(UInt32)statsFlushSeconds;

/**
Expand Down
18 changes: 18 additions & 0 deletions library/swift/src/EnvoyClientBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ public final class EnvoyClientBuilder: NSObject {
private var statsDomain: String = "0.0.0.0"
private var connectTimeoutSeconds: UInt32 = 30
private var dnsRefreshSeconds: UInt32 = 60
private var dnsFailureRefreshSecondsBase: UInt32 = 2
private var dnsFailureRefreshSecondsMax: UInt32 = 10
private var statsFlushSeconds: UInt32 = 60

// MARK: - Public
Expand Down Expand Up @@ -77,6 +79,19 @@ public final class EnvoyClientBuilder: NSObject {
return self
}

/// Add a rate at which to refresh DNS in case of DNS failure.
///
/// - parameter base: base rate in seconds.
/// - parameter max: max rate in seconds.
///
/// - returns: This builder.
@discardableResult
public func addDNSFailureRefreshSeconds(base: UInt32, max: UInt32) -> EnvoyClientBuilder {
self.dnsFailureRefreshSecondsBase = base
self.dnsFailureRefreshSecondsMax = max
return self
}

/// Add an interval at which to flush Envoy stats.
///
/// - parameter statsFlushSeconds: Interval at which to flush Envoy stats.
Expand All @@ -100,6 +115,9 @@ public final class EnvoyClientBuilder: NSObject {
let config = EnvoyConfiguration(statsDomain: self.statsDomain,
connectTimeoutSeconds: self.connectTimeoutSeconds,
dnsRefreshSeconds: self.dnsRefreshSeconds,
dnsFailureRefreshSecondsBase:
self.dnsFailureRefreshSecondsBase,
dnsFailureRefreshSecondsMax: self.dnsFailureRefreshSecondsMax,
statsFlushSeconds: self.statsFlushSeconds)
return EnvoyClient(config: config, logLevel: self.logLevel, engine: engine)
}
Expand Down
Loading

0 comments on commit 824ba9d

Please sign in to comment.