diff --git a/docs/root/intro/version_history.rst b/docs/root/intro/version_history.rst index 0ea68a3954..d477e1cc06 100644 --- a/docs/root/intro/version_history.rst +++ b/docs/root/intro/version_history.rst @@ -6,7 +6,7 @@ Pending Release Breaking changes: -- None +- api: replace the `drainConnections()` method with a broader `resetConnectivityState()`. (:issue:`#2225 <2225>`). Bugfixes: @@ -15,6 +15,7 @@ Bugfixes: Features: - api: add option to extend the keepalive timeout when any frame is received on the owning HTTP/2 connection. (:issue:`#2229 <2229>`) +- api: add option to control whether Envoy should drain connections after a soft DNS refresh completes. (:issue:`#2225 <2225>`, :issue:`#2242 <2242>`) 0.4.6 (April 26, 2022) ======================== diff --git a/library/objective-c/EnvoyConfiguration.m b/library/objective-c/EnvoyConfiguration.m index bd94e2b9d1..db3d68a194 100644 --- a/library/objective-c/EnvoyConfiguration.m +++ b/library/objective-c/EnvoyConfiguration.m @@ -15,6 +15,7 @@ - (instancetype)initWithAdminInterfaceEnabled:(BOOL)adminInterfaceEnabled dnsPreresolveHostnames:(NSString *)dnsPreresolveHostnames enableHappyEyeballs:(BOOL)enableHappyEyeballs enableInterfaceBinding:(BOOL)enableInterfaceBinding + enableDrainPostDnsRefresh:(BOOL)enableDrainPostDnsRefresh enforceTrustChainVerification:(BOOL)enforceTrustChainVerification h2ConnectionKeepaliveIdleIntervalMilliseconds: (UInt32)h2ConnectionKeepaliveIdleIntervalMilliseconds @@ -53,6 +54,7 @@ - (instancetype)initWithAdminInterfaceEnabled:(BOOL)adminInterfaceEnabled self.dnsPreresolveHostnames = dnsPreresolveHostnames; self.enableHappyEyeballs = enableHappyEyeballs; self.enableInterfaceBinding = enableInterfaceBinding; + self.enableDrainPostDnsRefresh = enableDrainPostDnsRefresh; self.enforceTrustChainVerification = enforceTrustChainVerification; self.h2ConnectionKeepaliveIdleIntervalMilliseconds = h2ConnectionKeepaliveIdleIntervalMilliseconds; @@ -149,6 +151,8 @@ - (nullable NSString *)resolveTemplate:(NSString *)templateYAML { self.h2ExtendKeepaliveTimeout ? @"true" : @"false"]; [definitions appendFormat:@"- &dns_refresh_rate %lus\n", (unsigned long)self.dnsRefreshSeconds]; [definitions appendFormat:@"- &dns_resolver_name envoy.network.dns_resolver.apple\n"]; + [definitions appendFormat:@"- &enable_drain_post_dns_refresh %@\n", + self.enableDrainPostDnsRefresh ? @"true" : @"false"]; // No additional values are currently needed for Apple-based DNS resolver. [definitions appendFormat:@"- &dns_resolver_config " diff --git a/library/objective-c/EnvoyEngine.h b/library/objective-c/EnvoyEngine.h index dc6d212d45..cc23a80b28 100644 --- a/library/objective-c/EnvoyEngine.h +++ b/library/objective-c/EnvoyEngine.h @@ -342,6 +342,7 @@ extern const int kEnvoyFilterResumeStatusResumeIteration; @property (nonatomic, assign) UInt32 dnsRefreshSeconds; @property (nonatomic, assign) BOOL enableHappyEyeballs; @property (nonatomic, assign) BOOL enableInterfaceBinding; +@property (nonatomic, assign) BOOL enableDrainPostDnsRefresh; @property (nonatomic, assign) BOOL enforceTrustChainVerification; @property (nonatomic, assign) UInt32 h2ConnectionKeepaliveIdleIntervalMilliseconds; @property (nonatomic, assign) UInt32 h2ConnectionKeepaliveTimeoutSeconds; @@ -374,6 +375,7 @@ extern const int kEnvoyFilterResumeStatusResumeIteration; dnsPreresolveHostnames:(NSString *)dnsPreresolveHostnames enableHappyEyeballs:(BOOL)enableHappyEyeballs enableInterfaceBinding:(BOOL)enableInterfaceBinding + enableDrainPostDnsRefresh:(BOOL)enableDrainPostDnsRefresh enforceTrustChainVerification:(BOOL)enforceTrustChainVerification h2ConnectionKeepaliveIdleIntervalMilliseconds: (UInt32)h2ConnectionKeepaliveIdleIntervalMilliseconds diff --git a/library/swift/EngineBuilder.swift b/library/swift/EngineBuilder.swift index a08670fb88..69fb4eff93 100644 --- a/library/swift/EngineBuilder.swift +++ b/library/swift/EngineBuilder.swift @@ -25,6 +25,7 @@ open class EngineBuilder: NSObject { private var enableHappyEyeballs: Bool = false private var enableInterfaceBinding: Bool = false private var enforceTrustChainVerification: Bool = true + private var enableDrainPostDnsRefresh: Bool = false private var h2ConnectionKeepaliveIdleIntervalMilliseconds: UInt32 = 100000000 private var h2ConnectionKeepaliveTimeoutSeconds: UInt32 = 10 private var h2ExtendKeepaliveTimeout: Bool = false @@ -176,6 +177,20 @@ open class EngineBuilder: NSObject { return self } + /// Specify whether to drain connections after the resolution of a soft DNS refresh. + /// A refresh may be triggered directly via the Engine API, or as a result of a network + /// status update provided by the OS. Draining connections does not interrupt existing + /// connections or requests, but will establish new connections for any further requests. + /// + /// - parameter enableDrainPostDnsRefresh: whether to drain connections after soft DNS refresh. + /// + /// - returns: This builder. + @discardableResult + public func enableDrainPostDnsRefresh(_ enableDrainPostDnsRefresh: Bool) -> Self { + self.enableDrainPostDnsRefresh = enableDrainPostDnsRefresh + return self + } + /// Specify whether to enforce TLS trust chain verification for secure sockets. /// /// - parameter enforceTrustChainVerification: whether to enforce trust chain verification. @@ -441,6 +456,7 @@ open class EngineBuilder: NSObject { dnsPreresolveHostnames: self.dnsPreresolveHostnames, enableHappyEyeballs: self.enableHappyEyeballs, enableInterfaceBinding: self.enableInterfaceBinding, + enableDrainPostDnsRefresh: self.enableDrainPostDnsRefresh, enforceTrustChainVerification: self.enforceTrustChainVerification, h2ConnectionKeepaliveIdleIntervalMilliseconds: self.h2ConnectionKeepaliveIdleIntervalMilliseconds, diff --git a/test/swift/EngineBuilderTests.swift b/test/swift/EngineBuilderTests.swift index b3f3990d47..2654a48240 100644 --- a/test/swift/EngineBuilderTests.swift +++ b/test/swift/EngineBuilderTests.swift @@ -431,6 +431,7 @@ final class EngineBuilderTests: XCTestCase { dnsPreresolveHostnames: "[test]", enableHappyEyeballs: true, enableInterfaceBinding: true, + enableDrainPostDnsRefresh: false, enforceTrustChainVerification: false, h2ConnectionKeepaliveIdleIntervalMilliseconds: 1, h2ConnectionKeepaliveTimeoutSeconds: 333, @@ -465,6 +466,7 @@ final class EngineBuilderTests: XCTestCase { XCTAssertTrue(resolvedYAML.contains("&dns_multiple_addresses true")) XCTAssertTrue(resolvedYAML.contains("&enable_interface_binding true")) XCTAssertTrue(resolvedYAML.contains("&trust_chain_verification ACCEPT_UNTRUSTED")) + XCTAssertTrue(resolvedYAML.contains("&enable_drain_post_dns_refresh false")) // HTTP/2 XCTAssertTrue(resolvedYAML.contains("&h2_connection_keepalive_idle_interval 0.001s")) @@ -509,6 +511,7 @@ final class EngineBuilderTests: XCTestCase { dnsPreresolveHostnames: "[test]", enableHappyEyeballs: false, enableInterfaceBinding: false, + enableDrainPostDnsRefresh: true, enforceTrustChainVerification: true, h2ConnectionKeepaliveIdleIntervalMilliseconds: 1, h2ConnectionKeepaliveTimeoutSeconds: 333, @@ -537,6 +540,7 @@ final class EngineBuilderTests: XCTestCase { XCTAssertTrue(resolvedYAML.contains("&enable_interface_binding false")) XCTAssertTrue(resolvedYAML.contains("&trust_chain_verification VERIFY_TRUST_CHAIN")) XCTAssertTrue(resolvedYAML.contains("&h2_delay_keepalive_timeout false")) + XCTAssertTrue(resolvedYAML.contains("&enable_drain_post_dns_refresh true")) } func testReturnsNilWhenUnresolvedValueInTemplate() { @@ -552,6 +556,7 @@ final class EngineBuilderTests: XCTestCase { dnsPreresolveHostnames: "[test]", enableHappyEyeballs: false, enableInterfaceBinding: false, + enableDrainPostDnsRefresh: false, enforceTrustChainVerification: true, h2ConnectionKeepaliveIdleIntervalMilliseconds: 222, h2ConnectionKeepaliveTimeoutSeconds: 333,