From e0e7628c3bc4227245f15c4f047ddad04912351c Mon Sep 17 00:00:00 2001 From: Yan Xue <3491507+crazyxy@users.noreply.github.com> Date: Mon, 1 Jul 2019 14:58:39 -0700 Subject: [PATCH] dns: adjust DNS refresh rate respecting to record TTL (#6975) Signed-off-by: Yan Xue --- api/envoy/api/v2/cds.proto | 7 +- .../upstream/service_discovery.rst | 12 + docs/root/intro/version_history.rst | 1 + include/envoy/network/dns.h | 16 +- source/common/network/dns_impl.cc | 11 +- source/common/upstream/logical_dns_cluster.cc | 18 +- source/common/upstream/logical_dns_cluster.h | 1 + source/common/upstream/strict_dns_cluster.cc | 26 +- source/common/upstream/strict_dns_cluster.h | 1 + .../clusters/redis/redis_cluster.cc | 13 +- .../extensions/clusters/redis/redis_cluster.h | 4 +- .../dynamic_forward_proxy/dns_cache_impl.cc | 29 +- .../dynamic_forward_proxy/dns_cache_impl.h | 3 +- test/common/network/dns_impl_test.cc | 348 +++++++++++------- test/common/upstream/upstream_impl_test.cc | 35 ++ .../clusters/redis/redis_cluster_test.cc | 5 +- .../dns_cache_impl_test.cc | 40 +- test/test_common/utility.cc | 9 +- test/test_common/utility.h | 5 +- tools/spelling_dictionary.txt | 1 + 20 files changed, 371 insertions(+), 214 deletions(-) diff --git a/api/envoy/api/v2/cds.proto b/api/envoy/api/v2/cds.proto index 004e9ddc4a31..83fe4329e15b 100644 --- a/api/envoy/api/v2/cds.proto +++ b/api/envoy/api/v2/cds.proto @@ -51,7 +51,7 @@ service ClusterDiscoveryService { // [#protodoc-title: Clusters] // Configuration for a single upstream cluster. -// [#comment:next free field: 39] +// [#comment:next free field: 40] message Cluster { // Supplies the name of the cluster which must be unique across all clusters. // The cluster name is used when emitting @@ -274,6 +274,11 @@ message Cluster { google.protobuf.Duration dns_refresh_rate = 16 [(validate.rules).duration.gt = {}, (gogoproto.stdduration) = true]; + // Optional configuration for setting cluster's DNS refresh rate. If the value is set to true, + // cluster's DNS refresh rate will be set to resource record's TTL which comes from DNS + // resolution. + bool respect_dns_ttl = 39; + // When V4_ONLY is selected, the DNS resolver will only perform a lookup for // addresses in the IPv4 family. If V6_ONLY is selected, the DNS resolver will // only perform a lookup for addresses in the IPv6 family. If AUTO is diff --git a/docs/root/intro/arch_overview/upstream/service_discovery.rst b/docs/root/intro/arch_overview/upstream/service_discovery.rst index 4d00f638dbdc..3f6bd5d7b4f4 100644 --- a/docs/root/intro/arch_overview/upstream/service_discovery.rst +++ b/docs/root/intro/arch_overview/upstream/service_discovery.rst @@ -39,6 +39,12 @@ This means that care should be taken if active health checking is used with DNS to the same IPs: if an IP is repeated many times between DNS names it might cause undue load on the upstream host. +If :ref:`respect_dns_ttl ` is enabled, DNS record TTLs and +:ref:`dns_refresh_rate ` are used to control DNS refresh rate. +For strict DNS cluster, if the minimum of all record TTLs is 0, :ref:`dns_refresh_rate ` +will be used as the cluster's DNS refresh rate. :ref:`dns_refresh_rate ` +defaults to 5000ms if not specified. + .. _arch_overview_service_discovery_types_logical_dns: Logical DNS @@ -58,6 +64,12 @@ When interacting with large scale web services, this is the best of all possible asynchronous/eventually consistent DNS resolution, long lived connections, and zero blocking in the forwarding path. +If :ref:`respect_dns_ttl ` is enabled, DNS record TTLs and +:ref:`dns_refresh_rate ` are used to control DNS refresh rate. +For logical DNS cluster, if the TTL of first record is 0, :ref:`dns_refresh_rate ` +will be used as the cluster's DNS refresh rate. :ref:`dns_refresh_rate ` +defaults to 5000ms if not specified. + .. _arch_overview_service_discovery_types_original_destination: Original destination diff --git a/docs/root/intro/version_history.rst b/docs/root/intro/version_history.rst index 453ea130d782..ecd9a14ee2bb 100644 --- a/docs/root/intro/version_history.rst +++ b/docs/root/intro/version_history.rst @@ -17,6 +17,7 @@ Version history * build: releases are built with Clang and linked with LLD. * control-plane: management servers can respond with HTTP 304 to indicate that config is up to date for Envoy proxies polling a :ref:`REST API Config Type ` * csrf: added support for whitelisting additional source origins. +* dns: added support for getting DNS record TTL which is used by STRICT_DNS/LOGICAL_DNS cluster as DNS refresh rate. * dubbo_proxy: support the :ref:`Dubbo proxy filter `. * eds: added support to specify max time for which endpoints can be used :ref:`gRPC filter `. * event: added :ref:`loop duration and poll delay statistics `. diff --git a/include/envoy/network/dns.h b/include/envoy/network/dns.h index 6e898ee9e4e5..26f1f3cbfaa2 100644 --- a/include/envoy/network/dns.h +++ b/include/envoy/network/dns.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -24,6 +25,17 @@ class ActiveDnsQuery { virtual void cancel() PURE; }; +/** + * DNS response. + */ +struct DnsResponse { + DnsResponse(const Address::InstanceConstSharedPtr& address, const std::chrono::seconds ttl) + : address_(address), ttl_(ttl) {} + + const Address::InstanceConstSharedPtr address_; + const std::chrono::seconds ttl_; +}; + enum class DnsLookupFamily { V4Only, V6Only, Auto }; /** @@ -35,10 +47,10 @@ class DnsResolver { /** * Called when a resolution attempt is complete. - * @param address_list supplies the list of resolved IP addresses. The list will be empty if + * @param response supplies the list of resolved IP addresses and TTLs. The list will be empty if * the resolution failed. */ - using ResolveCb = std::function&& address_list)>; + using ResolveCb = std::function&& response)>; /** * Initiate an async DNS resolution. diff --git a/source/common/network/dns_impl.cc b/source/common/network/dns_impl.cc index 29e2b48042fa..c4409d473b6b 100644 --- a/source/common/network/dns_impl.cc +++ b/source/common/network/dns_impl.cc @@ -79,7 +79,7 @@ void DnsResolverImpl::PendingResolution::onAresGetAddrInfoCallback(int status, i completed_ = true; } - std::list address_list; + std::list address_list; if (status == ARES_SUCCESS) { if (addrinfo != nullptr && addrinfo->nodes != nullptr) { if (addrinfo->nodes->ai_family == AF_INET) { @@ -89,7 +89,10 @@ void DnsResolverImpl::PendingResolution::onAresGetAddrInfoCallback(int status, i address.sin_family = AF_INET; address.sin_port = 0; address.sin_addr = reinterpret_cast(ai->ai_addr)->sin_addr; - address_list.emplace_back(new Address::Ipv4Instance(&address)); + + address_list.emplace_back( + DnsResponse(std::make_shared(&address), + std::chrono::seconds(ai->ai_ttl))); } } else if (addrinfo->nodes->ai_family == AF_INET6) { for (const ares_addrinfo_node* ai = addrinfo->nodes; ai != nullptr; ai = ai->ai_next) { @@ -98,7 +101,9 @@ void DnsResolverImpl::PendingResolution::onAresGetAddrInfoCallback(int status, i address.sin6_family = AF_INET6; address.sin6_port = 0; address.sin6_addr = reinterpret_cast(ai->ai_addr)->sin6_addr; - address_list.emplace_back(new Address::Ipv6Instance(address)); + address_list.emplace_back( + DnsResponse(std::make_shared(address), + std::chrono::seconds(ai->ai_ttl))); } } } diff --git a/source/common/upstream/logical_dns_cluster.cc b/source/common/upstream/logical_dns_cluster.cc index 3ae00a4dd17b..88ce5e02da5b 100644 --- a/source/common/upstream/logical_dns_cluster.cc +++ b/source/common/upstream/logical_dns_cluster.cc @@ -26,6 +26,7 @@ LogicalDnsCluster::LogicalDnsCluster( dns_resolver_(dns_resolver), dns_refresh_rate_ms_( std::chrono::milliseconds(PROTOBUF_GET_MS_OR_DEFAULT(cluster, dns_refresh_rate, 5000))), + respect_dns_ttl_(cluster.respect_dns_ttl()), resolve_timer_( factory_context.dispatcher().createTimer([this]() -> void { startResolve(); })), local_info_(factory_context.localInfo()), @@ -70,18 +71,23 @@ void LogicalDnsCluster::startResolve() { active_dns_query_ = dns_resolver_->resolve( dns_address, dns_lookup_family_, - [this, - dns_address](std::list&& address_list) -> void { + [this, dns_address](std::list&& response) -> void { active_dns_query_ = nullptr; ENVOY_LOG(debug, "async DNS resolution complete for {}", dns_address); info_->stats().update_success_.inc(); - if (!address_list.empty()) { + std::chrono::milliseconds refresh_rate = dns_refresh_rate_ms_; + if (!response.empty()) { // TODO(mattklein123): Move port handling into the DNS interface. - ASSERT(address_list.front() != nullptr); + ASSERT(response.front().address_ != nullptr); Network::Address::InstanceConstSharedPtr new_address = - Network::Utility::getAddressWithPort(*address_list.front(), + Network::Utility::getAddressWithPort(*(response.front().address_), Network::Utility::portFromTcpUrl(dns_url_)); + + if (respect_dns_ttl_ && response.front().ttl_ != std::chrono::seconds(0)) { + refresh_rate = response.front().ttl_; + } + if (!logical_host_) { logical_host_.reset( new LogicalHost(info_, hostname_, new_address, localityLbEndpoint(), lbEndpoint())); @@ -107,7 +113,7 @@ void LogicalDnsCluster::startResolve() { } onPreInitComplete(); - resolve_timer_->enableTimer(dns_refresh_rate_ms_); + resolve_timer_->enableTimer(refresh_rate); }); } diff --git a/source/common/upstream/logical_dns_cluster.h b/source/common/upstream/logical_dns_cluster.h index 07829f286533..68e786c80af6 100644 --- a/source/common/upstream/logical_dns_cluster.h +++ b/source/common/upstream/logical_dns_cluster.h @@ -62,6 +62,7 @@ class LogicalDnsCluster : public ClusterImplBase { Network::DnsResolverSharedPtr dns_resolver_; const std::chrono::milliseconds dns_refresh_rate_ms_; + const bool respect_dns_ttl_; Network::DnsLookupFamily dns_lookup_family_; Event::TimerPtr resolve_timer_; std::string dns_url_; diff --git a/source/common/upstream/strict_dns_cluster.cc b/source/common/upstream/strict_dns_cluster.cc index e06bc79a87b1..71aa2b3c71e0 100644 --- a/source/common/upstream/strict_dns_cluster.cc +++ b/source/common/upstream/strict_dns_cluster.cc @@ -12,7 +12,8 @@ StrictDnsClusterImpl::StrictDnsClusterImpl( added_via_api), local_info_(factory_context.localInfo()), dns_resolver_(dns_resolver), dns_refresh_rate_ms_( - std::chrono::milliseconds(PROTOBUF_GET_MS_OR_DEFAULT(cluster, dns_refresh_rate, 5000))) { + std::chrono::milliseconds(PROTOBUF_GET_MS_OR_DEFAULT(cluster, dns_refresh_rate, 5000))), + respect_dns_ttl_(cluster.respect_dns_ttl()) { std::list resolve_targets; const envoy::api::v2::ClusterLoadAssignment load_assignment( cluster.has_load_assignment() ? cluster.load_assignment() @@ -90,24 +91,28 @@ void StrictDnsClusterImpl::ResolveTarget::startResolve() { active_query_ = parent_.dns_resolver_->resolve( dns_address_, parent_.dns_lookup_family_, - [this](std::list&& address_list) -> void { + [this](std::list&& response) -> void { active_query_ = nullptr; ENVOY_LOG(trace, "async DNS resolution complete for {}", dns_address_); parent_.info_->stats().update_success_.inc(); std::unordered_map updated_hosts; HostVector new_hosts; - for (const Network::Address::InstanceConstSharedPtr& address : address_list) { + std::chrono::seconds ttl_refresh_rate = std::chrono::seconds::max(); + for (const auto& resp : response) { // TODO(mattklein123): Currently the DNS interface does not consider port. We need to // make a new address that has port in it. We need to both support IPv6 as well as // potentially move port handling into the DNS interface itself, which would work better // for SRV. - ASSERT(address != nullptr); + ASSERT(resp.address_ != nullptr); new_hosts.emplace_back(new HostImpl( - parent_.info_, dns_address_, Network::Utility::getAddressWithPort(*address, port_), + parent_.info_, dns_address_, + Network::Utility::getAddressWithPort(*(resp.address_), port_), lb_endpoint_.metadata(), lb_endpoint_.load_balancing_weight().value(), locality_lb_endpoint_.locality(), lb_endpoint_.endpoint().health_check_config(), locality_lb_endpoint_.priority(), lb_endpoint_.health_status())); + + ttl_refresh_rate = min(ttl_refresh_rate, resp.ttl_); } HostVector hosts_added; @@ -130,7 +135,16 @@ void StrictDnsClusterImpl::ResolveTarget::startResolve() { // completes. This is not perfect but is easier to code and unclear if the extra // complexity is needed so will start with this. parent_.onPreInitComplete(); - resolve_timer_->enableTimer(parent_.dns_refresh_rate_ms_); + + std::chrono::milliseconds final_refresh_rate = parent_.dns_refresh_rate_ms_; + + if (parent_.respect_dns_ttl_ && ttl_refresh_rate != std::chrono::seconds(0)) { + final_refresh_rate = ttl_refresh_rate; + ENVOY_LOG(debug, "DNS refresh rate reset for {}, refresh rate {} ms", dns_address_, + final_refresh_rate.count()); + } + + resolve_timer_->enableTimer(final_refresh_rate); }); } diff --git a/source/common/upstream/strict_dns_cluster.h b/source/common/upstream/strict_dns_cluster.h index 27b3fc5f3062..2b0c8f4f135d 100644 --- a/source/common/upstream/strict_dns_cluster.h +++ b/source/common/upstream/strict_dns_cluster.h @@ -52,6 +52,7 @@ class StrictDnsClusterImpl : public BaseDynamicClusterImpl { Network::DnsResolverSharedPtr dns_resolver_; std::list resolve_targets_; const std::chrono::milliseconds dns_refresh_rate_ms_; + const bool respect_dns_ttl_; Network::DnsLookupFamily dns_lookup_family_; uint32_t overprovisioning_factor_; }; diff --git a/source/extensions/clusters/redis/redis_cluster.cc b/source/extensions/clusters/redis/redis_cluster.cc index 70cf9e2d9051..06c0ac9d6b0d 100644 --- a/source/extensions/clusters/redis/redis_cluster.cc +++ b/source/extensions/clusters/redis/redis_cluster.cc @@ -128,10 +128,10 @@ void RedisCluster::DnsDiscoveryResolveTarget::startResolve() { active_query_ = parent_.dns_resolver_->resolve( dns_address_, parent_.dns_lookup_family_, - [this](std::list&& address_list) -> void { + [this](std::list&& response) -> void { active_query_ = nullptr; ENVOY_LOG(trace, "async DNS resolution complete for {}", dns_address_); - parent_.redis_discovery_session_.registerDiscoveryAddress(address_list, port_); + parent_.redis_discovery_session_.registerDiscoveryAddress(std::move(response), port_); parent_.redis_discovery_session_.startResolve(); }); } @@ -190,13 +190,12 @@ void RedisCluster::RedisDiscoveryClient::onEvent(Network::ConnectionEvent event) } void RedisCluster::RedisDiscoverySession::registerDiscoveryAddress( - const std::list& address_list, - const uint32_t port) { + std::list&& response, const uint32_t port) { // Since the address from DNS does not have port, we need to make a new address that has port in // it. - for (const Network::Address::InstanceConstSharedPtr& address : address_list) { - ASSERT(address != nullptr); - discovery_address_list_.push_back(Network::Utility::getAddressWithPort(*address, port)); + for (const Network::DnsResponse& res : response) { + ASSERT(res.address_ != nullptr); + discovery_address_list_.push_back(Network::Utility::getAddressWithPort(*(res.address_), port)); } } diff --git a/source/extensions/clusters/redis/redis_cluster.h b/source/extensions/clusters/redis/redis_cluster.h index fad26cafcaa6..d35dc0dfcd39 100644 --- a/source/extensions/clusters/redis/redis_cluster.h +++ b/source/extensions/clusters/redis/redis_cluster.h @@ -195,9 +195,7 @@ class RedisCluster : public Upstream::BaseDynamicClusterImpl { ~RedisDiscoverySession() override; - void registerDiscoveryAddress( - const std::list& address_list, - const uint32_t port); + void registerDiscoveryAddress(std::list&& response, const uint32_t port); // Start discovery against a random host from existing hosts void startResolve(); diff --git a/source/extensions/common/dynamic_forward_proxy/dns_cache_impl.cc b/source/extensions/common/dynamic_forward_proxy/dns_cache_impl.cc index 81dbc25805ca..b8173e2dfd00 100644 --- a/source/extensions/common/dynamic_forward_proxy/dns_cache_impl.cc +++ b/source/extensions/common/dynamic_forward_proxy/dns_cache_impl.cc @@ -134,19 +134,18 @@ void DnsCacheImpl::startResolve(const std::string& host, PrimaryHostInfo& host_i ENVOY_LOG(debug, "starting main thread resolve for host='{}' dns='{}' port='{}'", host, host_info.host_to_resolve_, host_info.port_); ASSERT(host_info.active_query_ == nullptr); + stats_.dns_query_attempt_.inc(); - host_info.active_query_ = resolver_->resolve( - host_info.host_to_resolve_, dns_lookup_family_, - [this, host](const std::list&& address_list) { - finishResolve(host, address_list); - }); + host_info.active_query_ = + resolver_->resolve(host_info.host_to_resolve_, dns_lookup_family_, + [this, host](std::list&& response) { + finishResolve(host, std::move(response)); + }); } -void DnsCacheImpl::finishResolve( - const std::string& host, - const std::list& address_list) { - ENVOY_LOG(debug, "main thread resolve complete for host '{}'. {} results", host, - address_list.size()); +void DnsCacheImpl::finishResolve(const std::string& host, + std::list&& response) { + ENVOY_LOG(debug, "main thread resolve complete for host '{}'. {} results", host, response.size()); const auto primary_host_it = primary_hosts_.find(host); ASSERT(primary_host_it != primary_hosts_.end()); @@ -158,12 +157,12 @@ void DnsCacheImpl::finishResolve( std::make_shared(main_thread_dispatcher_.timeSource()); } - const auto new_address = - !address_list.empty() - ? Network::Utility::getAddressWithPort(*address_list.front(), primary_host_info.port_) - : nullptr; + const auto new_address = !response.empty() + ? Network::Utility::getAddressWithPort(*(response.front().address_), + primary_host_info.port_) + : nullptr; - if (address_list.empty()) { + if (response.empty()) { stats_.dns_query_failure_.inc(); } else { stats_.dns_query_success_.inc(); diff --git a/source/extensions/common/dynamic_forward_proxy/dns_cache_impl.h b/source/extensions/common/dynamic_forward_proxy/dns_cache_impl.h index 7b6cd6940c79..7ecccdf3a8d2 100644 --- a/source/extensions/common/dynamic_forward_proxy/dns_cache_impl.h +++ b/source/extensions/common/dynamic_forward_proxy/dns_cache_impl.h @@ -113,8 +113,7 @@ class DnsCacheImpl : public DnsCache, Logger::Loggable& address_list); + void finishResolve(const std::string& host, std::list&& response); void runAddUpdateCallbacks(const std::string& host, const DnsHostInfoSharedPtr& host_info); void runRemoveCallbacks(const std::string& host); void updateTlsHostsMap(); diff --git a/test/common/network/dns_impl_test.cc b/test/common/network/dns_impl_test.cc index bc2727363c95..78ad6b566524 100644 --- a/test/common/network/dns_impl_test.cc +++ b/test/common/network/dns_impl_test.cc @@ -55,9 +55,9 @@ enum record_type { A, AAAA }; class TestDnsServerQuery { public: TestDnsServerQuery(ConnectionPtr connection, const HostMap& hosts_A, const HostMap& hosts_AAAA, - const CNameMap& cnames) + const CNameMap& cnames, const std::chrono::seconds& record_ttl) : connection_(std::move(connection)), hosts_A_(hosts_A), hosts_AAAA_(hosts_AAAA), - cnames_(cnames) { + cnames_(cnames), record_ttl_(record_ttl) { connection_->addReadFilter(Network::ReadFilterSharedPtr{new ReadFilter(*this)}); } @@ -199,7 +199,7 @@ class TestDnsServerQuery { DNS_RR_SET_TYPE(cname_rr_fixed, T_CNAME); DNS_RR_SET_LEN(cname_rr_fixed, encodedCname.size() + 1); DNS_RR_SET_CLASS(cname_rr_fixed, C_IN); - DNS_RR_SET_TTL(cname_rr_fixed, 0); + DNS_RR_SET_TTL(cname_rr_fixed, parent_.record_ttl_.count()); write_buffer.add(question, name_len); write_buffer.add(cname_rr_fixed, RRFIXEDSZ); write_buffer.add(encodedCname.c_str(), encodedCname.size() + 1); @@ -215,7 +215,7 @@ class TestDnsServerQuery { DNS_RR_SET_LEN(response_rr_fixed, sizeof(in6_addr)); } DNS_RR_SET_CLASS(response_rr_fixed, C_IN); - DNS_RR_SET_TTL(response_rr_fixed, 0); + DNS_RR_SET_TTL(response_rr_fixed, parent_.record_ttl_.count()); if (ips != nullptr) { for (const auto& it : *ips) { write_buffer.add(ip_question, ip_name_len); @@ -253,11 +253,12 @@ class TestDnsServerQuery { const HostMap& hosts_A_; const HostMap& hosts_AAAA_; const CNameMap& cnames_; + const std::chrono::seconds& record_ttl_; }; class TestDnsServer : public ListenerCallbacks { public: - TestDnsServer(Event::Dispatcher& dispatcher) : dispatcher_(dispatcher) {} + TestDnsServer(Event::Dispatcher& dispatcher) : dispatcher_(dispatcher), record_ttl_(0) {} void onAccept(ConnectionSocketPtr&& socket, bool) override { Network::ConnectionPtr new_connection = dispatcher_.createServerConnection( @@ -266,8 +267,8 @@ class TestDnsServer : public ListenerCallbacks { } void onNewConnection(ConnectionPtr&& new_connection) override { - TestDnsServerQuery* query = - new TestDnsServerQuery(std::move(new_connection), hosts_A_, hosts_AAAA_, cnames_); + TestDnsServerQuery* query = new TestDnsServerQuery(std::move(new_connection), hosts_A_, + hosts_AAAA_, cnames_, record_ttl_); queries_.emplace_back(query); } @@ -283,12 +284,15 @@ class TestDnsServer : public ListenerCallbacks { cnames_[hostname] = cname; } + void setRecordTtl(const std::chrono::seconds& ttl) { record_ttl_ = ttl; } + private: Event::Dispatcher& dispatcher_; HostMap hosts_A_; HostMap hosts_AAAA_; CNameMap cnames_; + std::chrono::seconds record_ttl_; // All queries are tracked so we can do resource reclamation when the test is // over. std::vector> queries_; @@ -426,6 +430,15 @@ class DnsImplTest : public testing::TestWithParam { server_.reset(); } + std::list + getAddressList(const std::list& response) { + std::list address; + + for_each(response.begin(), response.end(), + [&](DnsResponse resp) { address.emplace_back(resp.address_); }); + return address; + } + protected: // Should the DnsResolverImpl use a zero timeout for c-ares queries? virtual bool zero_timeout() const { return false; } @@ -459,12 +472,11 @@ INSTANTIATE_TEST_SUITE_P(IpVersions, DnsImplTest, // development, where segfaults were encountered due to callback invocations on // destruction. TEST_P(DnsImplTest, DestructPending) { - EXPECT_NE(nullptr, - resolver_->resolve("", DnsLookupFamily::V4Only, - [&](std::list&& results) -> void { - FAIL(); - UNREFERENCED_PARAMETER(results); - })); + EXPECT_NE(nullptr, resolver_->resolve("", DnsLookupFamily::V4Only, + [&](std::list&& results) -> void { + FAIL(); + UNREFERENCED_PARAMETER(results); + })); // Also validate that pending events are around to exercise the resource // reclamation path. EXPECT_GT(peer_->events().size(), 0U); @@ -475,23 +487,21 @@ TEST_P(DnsImplTest, DestructPending) { // asynchronous behavior or network events. TEST_P(DnsImplTest, LocalLookup) { std::list address_list; - EXPECT_NE(nullptr, - resolver_->resolve("", DnsLookupFamily::V4Only, - [&](std::list&& results) -> void { - address_list = std::move(results); - dispatcher_->exit(); - })); + EXPECT_NE(nullptr, resolver_->resolve("", DnsLookupFamily::V4Only, + [&](std::list&& results) -> void { + address_list = getAddressList(results); + dispatcher_->exit(); + })); dispatcher_->run(Event::Dispatcher::RunType::Block); EXPECT_TRUE(address_list.empty()); if (GetParam() == Address::IpVersion::v4) { // EXPECT_CALL(dispatcher_, post(_)); - EXPECT_EQ(nullptr, - resolver_->resolve("localhost", DnsLookupFamily::V4Only, - [&](std::list&& results) -> void { - address_list = std::move(results); - })); + EXPECT_EQ(nullptr, resolver_->resolve("localhost", DnsLookupFamily::V4Only, + [&](std::list&& results) -> void { + address_list = getAddressList(results); + })); EXPECT_TRUE(hasAddress(address_list, "127.0.0.1")); EXPECT_FALSE(hasAddress(address_list, "::1")); } @@ -500,20 +510,18 @@ TEST_P(DnsImplTest, LocalLookup) { const std::string error_msg = "Synchronous DNS IPv6 localhost resolution failed. Please verify localhost resolves to ::1 " "in /etc/hosts, since this misconfiguration is a common cause of these failures."; - EXPECT_EQ(nullptr, - resolver_->resolve("localhost", DnsLookupFamily::V6Only, - [&](std::list&& results) -> void { - address_list = std::move(results); - })) + EXPECT_EQ(nullptr, resolver_->resolve("localhost", DnsLookupFamily::V6Only, + [&](std::list&& results) -> void { + address_list = getAddressList(results); + })) << error_msg; EXPECT_TRUE(hasAddress(address_list, "::1")) << error_msg; EXPECT_FALSE(hasAddress(address_list, "127.0.0.1")); - EXPECT_EQ(nullptr, - resolver_->resolve("localhost", DnsLookupFamily::Auto, - [&](std::list&& results) -> void { - address_list = std::move(results); - })) + EXPECT_EQ(nullptr, resolver_->resolve("localhost", DnsLookupFamily::Auto, + [&](std::list&& results) -> void { + address_list = getAddressList(results); + })) << error_msg; EXPECT_FALSE(hasAddress(address_list, "127.0.0.1")); EXPECT_TRUE(hasAddress(address_list, "::1")) << error_msg; @@ -523,32 +531,29 @@ TEST_P(DnsImplTest, LocalLookup) { TEST_P(DnsImplTest, DnsIpAddressVersionV6) { std::list address_list; server_->addHosts("some.good.domain", {"1::2"}, AAAA); - EXPECT_NE(nullptr, - resolver_->resolve("some.good.domain", DnsLookupFamily::Auto, - [&](std::list&& results) -> void { - address_list = std::move(results); - dispatcher_->exit(); - })); + EXPECT_NE(nullptr, resolver_->resolve("some.good.domain", DnsLookupFamily::Auto, + [&](std::list&& results) -> void { + address_list = getAddressList(results); + dispatcher_->exit(); + })); dispatcher_->run(Event::Dispatcher::RunType::Block); EXPECT_TRUE(hasAddress(address_list, "1::2")); - EXPECT_NE(nullptr, - resolver_->resolve("some.good.domain", DnsLookupFamily::V4Only, - [&](std::list&& results) -> void { - address_list = std::move(results); - dispatcher_->exit(); - })); + EXPECT_NE(nullptr, resolver_->resolve("some.good.domain", DnsLookupFamily::V4Only, + [&](std::list&& results) -> void { + address_list = getAddressList(results); + dispatcher_->exit(); + })); dispatcher_->run(Event::Dispatcher::RunType::Block); EXPECT_FALSE(hasAddress(address_list, "1::2")); - EXPECT_NE(nullptr, - resolver_->resolve("some.good.domain", DnsLookupFamily::V6Only, - [&](std::list&& results) -> void { - address_list = std::move(results); - dispatcher_->exit(); - })); + EXPECT_NE(nullptr, resolver_->resolve("some.good.domain", DnsLookupFamily::V6Only, + [&](std::list&& results) -> void { + address_list = getAddressList(results); + dispatcher_->exit(); + })); dispatcher_->run(Event::Dispatcher::RunType::Block); EXPECT_TRUE(hasAddress(address_list, "1::2")); @@ -560,18 +565,18 @@ TEST_P(DnsImplTest, CallbackException) { // state providing regression coverage for #4307. EXPECT_EQ(nullptr, resolver_->resolve( "1.2.3.4", DnsLookupFamily::V4Only, - [&](std::list && + [&](const std::list & /*results*/) -> void { throw EnvoyException("Envoy exception"); })); EXPECT_THROW_WITH_MESSAGE(dispatcher_->run(Event::Dispatcher::RunType::Block), EnvoyException, "Envoy exception"); EXPECT_EQ(nullptr, resolver_->resolve( "1.2.3.4", DnsLookupFamily::V4Only, - [&](std::list && + [&](const std::list & /*results*/) -> void { throw std::runtime_error("runtime error"); })); EXPECT_THROW_WITH_MESSAGE(dispatcher_->run(Event::Dispatcher::RunType::Block), EnvoyException, "runtime error"); EXPECT_EQ(nullptr, resolver_->resolve("1.2.3.4", DnsLookupFamily::V4Only, - [&](std::list && + [&](const std::list & /*results*/) -> void { throw std::string(); })); EXPECT_THROW_WITH_MESSAGE(dispatcher_->run(Event::Dispatcher::RunType::Block), EnvoyException, "unknown"); @@ -580,32 +585,29 @@ TEST_P(DnsImplTest, CallbackException) { TEST_P(DnsImplTest, DnsIpAddressVersion) { std::list address_list; server_->addHosts("some.good.domain", {"1.2.3.4"}, A); - EXPECT_NE(nullptr, - resolver_->resolve("some.good.domain", DnsLookupFamily::Auto, - [&](std::list&& results) -> void { - address_list = std::move(results); - dispatcher_->exit(); - })); + EXPECT_NE(nullptr, resolver_->resolve("some.good.domain", DnsLookupFamily::Auto, + [&](std::list&& results) -> void { + address_list = getAddressList(results); + dispatcher_->exit(); + })); dispatcher_->run(Event::Dispatcher::RunType::Block); EXPECT_TRUE(hasAddress(address_list, "1.2.3.4")); - EXPECT_NE(nullptr, - resolver_->resolve("some.good.domain", DnsLookupFamily::V4Only, - [&](std::list&& results) -> void { - address_list = std::move(results); - dispatcher_->exit(); - })); + EXPECT_NE(nullptr, resolver_->resolve("some.good.domain", DnsLookupFamily::V4Only, + [&](std::list&& results) -> void { + address_list = getAddressList(results); + dispatcher_->exit(); + })); dispatcher_->run(Event::Dispatcher::RunType::Block); EXPECT_TRUE(hasAddress(address_list, "1.2.3.4")); - EXPECT_NE(nullptr, - resolver_->resolve("some.good.domain", DnsLookupFamily::V6Only, - [&](std::list&& results) -> void { - address_list = std::move(results); - dispatcher_->exit(); - })); + EXPECT_NE(nullptr, resolver_->resolve("some.good.domain", DnsLookupFamily::V6Only, + [&](std::list&& results) -> void { + address_list = getAddressList(results); + dispatcher_->exit(); + })); dispatcher_->run(Event::Dispatcher::RunType::Block); EXPECT_FALSE(hasAddress(address_list, "1.2.3.4")); @@ -616,22 +618,20 @@ TEST_P(DnsImplTest, DnsIpAddressVersion) { TEST_P(DnsImplTest, RemoteAsyncLookup) { server_->addHosts("some.good.domain", {"201.134.56.7"}, A); std::list address_list; - EXPECT_NE(nullptr, - resolver_->resolve("some.bad.domain", DnsLookupFamily::Auto, - [&](std::list&& results) -> void { - address_list = std::move(results); - dispatcher_->exit(); - })); + EXPECT_NE(nullptr, resolver_->resolve("some.bad.domain", DnsLookupFamily::Auto, + [&](std::list&& results) -> void { + address_list = getAddressList(results); + dispatcher_->exit(); + })); dispatcher_->run(Event::Dispatcher::RunType::Block); EXPECT_TRUE(address_list.empty()); - EXPECT_NE(nullptr, - resolver_->resolve("some.good.domain", DnsLookupFamily::Auto, - [&](std::list&& results) -> void { - address_list = std::move(results); - dispatcher_->exit(); - })); + EXPECT_NE(nullptr, resolver_->resolve("some.good.domain", DnsLookupFamily::Auto, + [&](std::list&& results) -> void { + address_list = getAddressList(results); + dispatcher_->exit(); + })); dispatcher_->run(Event::Dispatcher::RunType::Block); EXPECT_TRUE(hasAddress(address_list, "201.134.56.7")); @@ -641,12 +641,11 @@ TEST_P(DnsImplTest, RemoteAsyncLookup) { TEST_P(DnsImplTest, MultiARecordLookup) { server_->addHosts("some.good.domain", {"201.134.56.7", "123.4.5.6", "6.5.4.3"}, A); std::list address_list; - EXPECT_NE(nullptr, - resolver_->resolve("some.good.domain", DnsLookupFamily::V4Only, - [&](std::list&& results) -> void { - address_list = std::move(results); - dispatcher_->exit(); - })); + EXPECT_NE(nullptr, resolver_->resolve("some.good.domain", DnsLookupFamily::V4Only, + [&](std::list&& results) -> void { + address_list = getAddressList(results); + dispatcher_->exit(); + })); dispatcher_->run(Event::Dispatcher::RunType::Block); EXPECT_TRUE(hasAddress(address_list, "201.134.56.7")); @@ -658,12 +657,11 @@ TEST_P(DnsImplTest, CNameARecordLookupV4) { server_->addCName("root.cnam.domain", "result.cname.domain"); server_->addHosts("result.cname.domain", {"201.134.56.7"}, A); std::list address_list; - EXPECT_NE(nullptr, - resolver_->resolve("root.cnam.domain", DnsLookupFamily::V4Only, - [&](std::list&& results) -> void { - address_list = std::move(results); - dispatcher_->exit(); - })); + EXPECT_NE(nullptr, resolver_->resolve("root.cnam.domain", DnsLookupFamily::V4Only, + [&](std::list&& results) -> void { + address_list = getAddressList(results); + dispatcher_->exit(); + })); dispatcher_->run(Event::Dispatcher::RunType::Block); EXPECT_TRUE(hasAddress(address_list, "201.134.56.7")); @@ -673,12 +671,11 @@ TEST_P(DnsImplTest, CNameARecordLookupWithV6) { server_->addCName("root.cnam.domain", "result.cname.domain"); server_->addHosts("result.cname.domain", {"201.134.56.7"}, A); std::list address_list; - EXPECT_NE(nullptr, - resolver_->resolve("root.cnam.domain", DnsLookupFamily::Auto, - [&](std::list&& results) -> void { - address_list = std::move(results); - dispatcher_->exit(); - })); + EXPECT_NE(nullptr, resolver_->resolve("root.cnam.domain", DnsLookupFamily::Auto, + [&](std::list&& results) -> void { + address_list = getAddressList(results); + dispatcher_->exit(); + })); dispatcher_->run(Event::Dispatcher::RunType::Block); EXPECT_TRUE(hasAddress(address_list, "201.134.56.7")); @@ -688,36 +685,33 @@ TEST_P(DnsImplTest, MultiARecordLookupWithV6) { server_->addHosts("some.good.domain", {"201.134.56.7", "123.4.5.6", "6.5.4.3"}, A); server_->addHosts("some.good.domain", {"1::2", "1::2:3", "1::2:3:4"}, AAAA); std::list address_list; - EXPECT_NE(nullptr, - resolver_->resolve("some.good.domain", DnsLookupFamily::V4Only, - [&](std::list&& results) -> void { - address_list = std::move(results); - dispatcher_->exit(); - })); + EXPECT_NE(nullptr, resolver_->resolve("some.good.domain", DnsLookupFamily::V4Only, + [&](std::list&& results) -> void { + address_list = getAddressList(results); + dispatcher_->exit(); + })); dispatcher_->run(Event::Dispatcher::RunType::Block); EXPECT_TRUE(hasAddress(address_list, "201.134.56.7")); EXPECT_TRUE(hasAddress(address_list, "123.4.5.6")); EXPECT_TRUE(hasAddress(address_list, "6.5.4.3")); - EXPECT_NE(nullptr, - resolver_->resolve("some.good.domain", DnsLookupFamily::Auto, - [&](std::list&& results) -> void { - address_list = std::move(results); - dispatcher_->exit(); - })); + EXPECT_NE(nullptr, resolver_->resolve("some.good.domain", DnsLookupFamily::Auto, + [&](std::list&& results) -> void { + address_list = getAddressList(results); + dispatcher_->exit(); + })); dispatcher_->run(Event::Dispatcher::RunType::Block); EXPECT_TRUE(hasAddress(address_list, "1::2")); EXPECT_TRUE(hasAddress(address_list, "1::2:3")); EXPECT_TRUE(hasAddress(address_list, "1::2:3:4")); - EXPECT_NE(nullptr, - resolver_->resolve("some.good.domain", DnsLookupFamily::V6Only, - [&](std::list&& results) -> void { - address_list = std::move(results); - dispatcher_->exit(); - })); + EXPECT_NE(nullptr, resolver_->resolve("some.good.domain", DnsLookupFamily::V6Only, + [&](std::list&& results) -> void { + address_list = getAddressList(results); + dispatcher_->exit(); + })); dispatcher_->run(Event::Dispatcher::RunType::Block); EXPECT_TRUE(hasAddress(address_list, "1::2")); @@ -729,17 +723,15 @@ TEST_P(DnsImplTest, MultiARecordLookupWithV6) { TEST_P(DnsImplTest, Cancel) { server_->addHosts("some.good.domain", {"201.134.56.7"}, A); - ActiveDnsQuery* query = resolver_->resolve( - "some.domain", DnsLookupFamily::Auto, - [](const std::list &&) -> void { FAIL(); }); + ActiveDnsQuery* query = resolver_->resolve("some.domain", DnsLookupFamily::Auto, + [](std::list &&) -> void { FAIL(); }); std::list address_list; - EXPECT_NE(nullptr, - resolver_->resolve("some.good.domain", DnsLookupFamily::Auto, - [&](std::list&& results) -> void { - address_list = std::move(results); - dispatcher_->exit(); - })); + EXPECT_NE(nullptr, resolver_->resolve("some.good.domain", DnsLookupFamily::Auto, + [&](std::list&& results) -> void { + address_list = getAddressList(results); + dispatcher_->exit(); + })); ASSERT_NE(nullptr, query); query->cancel(); @@ -748,6 +740,89 @@ TEST_P(DnsImplTest, Cancel) { EXPECT_TRUE(hasAddress(address_list, "201.134.56.7")); } +// Validate working of querying ttl of resource record. +TEST_P(DnsImplTest, RecordTtlLookup) { + if (GetParam() == Address::IpVersion::v4) { + EXPECT_EQ(nullptr, resolver_->resolve("localhost", DnsLookupFamily::V4Only, + [](std::list&& results) -> void { + for (auto address : results) { + EXPECT_EQ(address.ttl_, std::chrono::seconds(0)); + } + })); + } + + if (GetParam() == Address::IpVersion::v6) { + EXPECT_EQ(nullptr, resolver_->resolve("localhost", DnsLookupFamily::V6Only, + [](std::list&& results) -> void { + for (auto address : results) { + EXPECT_EQ(address.ttl_, std::chrono::seconds(0)); + } + })); + + EXPECT_EQ(nullptr, resolver_->resolve("localhost", DnsLookupFamily::Auto, + [](std::list&& results) -> void { + for (auto address : results) { + EXPECT_EQ(address.ttl_, std::chrono::seconds(0)); + } + })); + } + + server_->addHosts("some.good.domain", {"201.134.56.7", "123.4.5.6", "6.5.4.3"}, A); + server_->addHosts("some.good.domain", {"1::2", "1::2:3", "1::2:3:4"}, AAAA); + server_->setRecordTtl(std::chrono::seconds(300)); + + EXPECT_NE(nullptr, resolver_->resolve("some.good.domain", DnsLookupFamily::V4Only, + [&](std::list&& results) -> void { + for (auto address : results) { + EXPECT_EQ(address.ttl_, std::chrono::seconds(300)); + } + + dispatcher_->exit(); + })); + + dispatcher_->run(Event::Dispatcher::RunType::Block); + + EXPECT_NE(nullptr, resolver_->resolve("some.good.domain", DnsLookupFamily::Auto, + [&](std::list&& results) -> void { + for (auto address : results) { + EXPECT_EQ(address.ttl_, std::chrono::seconds(300)); + } + dispatcher_->exit(); + })); + + dispatcher_->run(Event::Dispatcher::RunType::Block); + + EXPECT_NE(nullptr, resolver_->resolve("some.good.domain", DnsLookupFamily::V6Only, + [&](std::list&& results) -> void { + for (auto address : results) { + EXPECT_EQ(address.ttl_, std::chrono::seconds(300)); + } + dispatcher_->exit(); + })); + + dispatcher_->run(Event::Dispatcher::RunType::Block); + + std::list address_list; + + server_->addHosts("domain.onion", {"1.2.3.4"}, A); + server_->addHosts("domain.onion.", {"2.3.4.5"}, A); + + // test onion domain + EXPECT_EQ(nullptr, resolver_->resolve("domain.onion", DnsLookupFamily::V4Only, + [&](std::list&& results) -> void { + address_list = getAddressList(results); + dispatcher_->exit(); + })); + EXPECT_TRUE(address_list.empty()); + + EXPECT_EQ(nullptr, resolver_->resolve("domain.onion.", DnsLookupFamily::V4Only, + [&](std::list&& results) -> void { + address_list = getAddressList(results); + dispatcher_->exit(); + })); + EXPECT_TRUE(address_list.empty()); +} + class DnsImplZeroTimeoutTest : public DnsImplTest { protected: bool zero_timeout() const override { return true; } @@ -762,12 +837,11 @@ INSTANTIATE_TEST_SUITE_P(IpVersions, DnsImplZeroTimeoutTest, TEST_P(DnsImplZeroTimeoutTest, Timeout) { server_->addHosts("some.good.domain", {"201.134.56.7"}, A); std::list address_list; - EXPECT_NE(nullptr, - resolver_->resolve("some.good.domain", DnsLookupFamily::V4Only, - [&](std::list&& results) -> void { - address_list = std::move(results); - dispatcher_->exit(); - })); + EXPECT_NE(nullptr, resolver_->resolve("some.good.domain", DnsLookupFamily::V4Only, + [&](std::list&& results) -> void { + address_list = getAddressList(results); + dispatcher_->exit(); + })); dispatcher_->run(Event::Dispatcher::RunType::Block); EXPECT_TRUE(address_list.empty()); @@ -785,7 +859,7 @@ TEST(DnsImplUnitTest, PendingTimerEnable) { EXPECT_CALL(dispatcher, createFileEvent_(_, _, _, _)).WillOnce(Return(file_event)); EXPECT_CALL(*timer, enableTimer(_)); EXPECT_NE(nullptr, resolver.resolve("some.bad.domain.invalid", DnsLookupFamily::V4Only, - [&](std::list&& results) { + [&](std::list&& results) { UNREFERENCED_PARAMETER(results); })); } diff --git a/test/common/upstream/upstream_impl_test.cc b/test/common/upstream/upstream_impl_test.cc index 9001f60c7691..cc94979718b3 100644 --- a/test/common/upstream/upstream_impl_test.cc +++ b/test/common/upstream/upstream_impl_test.cc @@ -886,6 +886,41 @@ TEST_F(StrictDnsClusterImplTest, CustomResolverFails) { EnvoyException, "STRICT_DNS clusters must NOT have a custom resolver name set"); } +TEST_F(StrictDnsClusterImplTest, RecordTtlAsDnsRefreshRate) { + ResolverData resolver(*dns_resolver_, dispatcher_); + + const std::string yaml = R"EOF( + name: name + connect_timeout: 0.25s + type: STRICT_DNS + lb_policy: ROUND_ROBIN + dns_refresh_rate: 4s + respect_dns_ttl: true + hosts: [{ socket_address: { address: localhost1, port_value: 11001 }}] + )EOF"; + + envoy::api::v2::Cluster cluster_config = parseClusterFromV2Yaml(yaml); + Envoy::Stats::ScopePtr scope = stats_.createScope(fmt::format( + "cluster.{}.", cluster_config.alt_stat_name().empty() ? cluster_config.name() + : cluster_config.alt_stat_name())); + Envoy::Server::Configuration::TransportSocketFactoryContextImpl factory_context( + admin_, ssl_context_manager_, *scope, cm_, local_info_, dispatcher_, random_, stats_, + singleton_manager_, tls_, validation_visitor_, *api_); + StrictDnsClusterImpl cluster(cluster_config, runtime_, dns_resolver_, factory_context, + std::move(scope), false); + ReadyWatcher membership_updated; + cluster.prioritySet().addPriorityUpdateCb( + [&](uint32_t, const HostVector&, const HostVector&) -> void { membership_updated.ready(); }); + + cluster.initialize([] {}); + + EXPECT_CALL(membership_updated, ready()); + + EXPECT_CALL(*resolver.timer_, enableTimer(std::chrono::milliseconds(5000))); + resolver.dns_callback_( + TestUtility::makeDnsResponse({"192.168.1.1", "192.168.1.2"}, std::chrono::seconds(5))); +} + TEST(HostImplTest, HostCluster) { MockClusterMockPrioritySet cluster; HostSharedPtr host = makeTestHost(cluster.info_, "tcp://10.0.0.1:1234", 1); diff --git a/test/extensions/clusters/redis/redis_cluster_test.cc b/test/extensions/clusters/redis/redis_cluster_test.cc index 7e69602477bc..c035354cb101 100644 --- a/test/extensions/clusters/redis/redis_cluster_test.cc +++ b/test/extensions/clusters/redis/redis_cluster_test.cc @@ -430,8 +430,9 @@ class RedisClusterTest : public testing::Test, void testRedisResolve() { EXPECT_CALL(dispatcher_, createTimer_(_)); RedisCluster::RedisDiscoverySession discovery_session(*cluster_, *this); - discovery_session.registerDiscoveryAddress( - TestUtility::makeDnsResponse(std::list({"127.0.0.1", "127.0.0.2"})), 22120); + auto dns_response = + TestUtility::makeDnsResponse(std::list({"127.0.0.1", "127.0.0.2"})); + discovery_session.registerDiscoveryAddress(std::move(dns_response), 22120); expectRedisResolve(true); discovery_session.startResolve(); diff --git a/test/extensions/common/dynamic_forward_proxy/dns_cache_impl_test.cc b/test/extensions/common/dynamic_forward_proxy/dns_cache_impl_test.cc index 799a65b7a4bb..3fe6ddad32d3 100644 --- a/test/extensions/common/dynamic_forward_proxy/dns_cache_impl_test.cc +++ b/test/extensions/common/dynamic_forward_proxy/dns_cache_impl_test.cc @@ -5,6 +5,7 @@ #include "test/mocks/network/mocks.h" #include "test/mocks/thread_local/mocks.h" #include "test/test_common/simulated_time_system.h" +#include "test/test_common/utility.h" using testing::InSequence; using testing::Return; @@ -16,15 +17,6 @@ namespace Common { namespace DynamicForwardProxy { namespace { -std::list -makeAddressList(const std::list address_list) { - std::list ret; - for (const auto& address : address_list) { - ret.emplace_back(Network::Utility::parseInternetAddress(address)); - } - return ret; -} - class DnsCacheImplTest : public testing::Test, public Event::TestUsingSimulatedTime { public: void initialize() { @@ -95,7 +87,7 @@ TEST_F(DnsCacheImplTest, ResolveSuccess) { onDnsHostAddOrUpdate("foo.com", SharedAddressEquals("10.0.0.1:80"))); EXPECT_CALL(callbacks, onLoadDnsCacheComplete()); EXPECT_CALL(*resolve_timer, enableTimer(std::chrono::milliseconds(60000))); - resolve_cb(makeAddressList({"10.0.0.1"})); + resolve_cb(TestUtility::makeDnsResponse({"10.0.0.1"})); checkStats(1 /* attempt */, 1 /* success */, 0 /* failure */, 1 /* address changed */, 1 /* added */, 0 /* removed */, 1 /* num hosts */); @@ -110,7 +102,7 @@ TEST_F(DnsCacheImplTest, ResolveSuccess) { // Address does not change. EXPECT_CALL(*resolve_timer, enableTimer(std::chrono::milliseconds(60000))); - resolve_cb(makeAddressList({"10.0.0.1"})); + resolve_cb(TestUtility::makeDnsResponse({"10.0.0.1"})); checkStats(2 /* attempt */, 2 /* success */, 0 /* failure */, 1 /* address changed */, 1 /* added */, 0 /* removed */, 1 /* num hosts */); @@ -127,7 +119,7 @@ TEST_F(DnsCacheImplTest, ResolveSuccess) { EXPECT_CALL(update_callbacks_, onDnsHostAddOrUpdate("foo.com", SharedAddressEquals("10.0.0.2:80"))); EXPECT_CALL(*resolve_timer, enableTimer(std::chrono::milliseconds(60000))); - resolve_cb(makeAddressList({"10.0.0.2"})); + resolve_cb(TestUtility::makeDnsResponse({"10.0.0.2"})); checkStats(3 /* attempt */, 3 /* success */, 0 /* failure */, 2 /* address changed */, 1 /* added */, 0 /* removed */, 1 /* num hosts */); @@ -154,7 +146,7 @@ TEST_F(DnsCacheImplTest, TTL) { onDnsHostAddOrUpdate("foo.com", SharedAddressEquals("10.0.0.1:80"))); EXPECT_CALL(callbacks, onLoadDnsCacheComplete()); EXPECT_CALL(*resolve_timer, enableTimer(std::chrono::milliseconds(60000))); - resolve_cb(makeAddressList({"10.0.0.1"})); + resolve_cb(TestUtility::makeDnsResponse({"10.0.0.1"}, std::chrono::seconds(0))); checkStats(1 /* attempt */, 1 /* success */, 0 /* failure */, 1 /* address changed */, 1 /* added */, 0 /* removed */, 1 /* num hosts */); @@ -168,7 +160,7 @@ TEST_F(DnsCacheImplTest, TTL) { 1 /* added */, 0 /* removed */, 1 /* num hosts */); EXPECT_CALL(*resolve_timer, enableTimer(std::chrono::milliseconds(60000))); - resolve_cb(makeAddressList({"10.0.0.1"})); + resolve_cb(TestUtility::makeDnsResponse({"10.0.0.1"})); checkStats(2 /* attempt */, 2 /* success */, 0 /* failure */, 1 /* address changed */, 1 /* added */, 0 /* removed */, 1 /* num hosts */); @@ -211,7 +203,7 @@ TEST_F(DnsCacheImplTest, TTLWithCustomParameters) { onDnsHostAddOrUpdate("foo.com", SharedAddressEquals("10.0.0.1:80"))); EXPECT_CALL(callbacks, onLoadDnsCacheComplete()); EXPECT_CALL(*resolve_timer, enableTimer(std::chrono::milliseconds(30000))); - resolve_cb(makeAddressList({"10.0.0.1"})); + resolve_cb(TestUtility::makeDnsResponse({"10.0.0.1"}, std::chrono::seconds(0))); // Re-resolve with ~30s passed. TTL should still be OK at 60s. simTime().sleep(std::chrono::milliseconds(30001)); @@ -219,7 +211,7 @@ TEST_F(DnsCacheImplTest, TTLWithCustomParameters) { .WillOnce(DoAll(SaveArg<2>(&resolve_cb), Return(&resolver_->active_query_))); resolve_timer->invokeCallback(); EXPECT_CALL(*resolve_timer, enableTimer(std::chrono::milliseconds(30000))); - resolve_cb(makeAddressList({"10.0.0.1"})); + resolve_cb(TestUtility::makeDnsResponse({"10.0.0.1"})); // Re-resolve with ~30s passed. TTL should expire. simTime().sleep(std::chrono::milliseconds(30001)); @@ -243,7 +235,7 @@ TEST_F(DnsCacheImplTest, InlineResolve) { EXPECT_CALL(*resolver_, resolve("localhost", _, _)) .WillOnce(Invoke([](const std::string&, Network::DnsLookupFamily, Network::DnsResolver::ResolveCb callback) { - callback(makeAddressList({"127.0.0.1"})); + callback(TestUtility::makeDnsResponse({"127.0.0.1"})); return nullptr; })); EXPECT_CALL(update_callbacks_, @@ -270,7 +262,7 @@ TEST_F(DnsCacheImplTest, ResolveFailure) { EXPECT_CALL(update_callbacks_, onDnsHostAddOrUpdate(_, _)).Times(0); EXPECT_CALL(callbacks, onLoadDnsCacheComplete()); - resolve_cb(makeAddressList({})); + resolve_cb(TestUtility::makeDnsResponse({})); checkStats(1 /* attempt */, 0 /* success */, 1 /* failure */, 0 /* address changed */, 1 /* added */, 0 /* removed */, 1 /* num hosts */); @@ -295,7 +287,7 @@ TEST_F(DnsCacheImplTest, CancelResolve) { result.handle_.reset(); EXPECT_CALL(update_callbacks_, onDnsHostAddOrUpdate("foo.com", SharedAddressEquals("10.0.0.1:80"))); - resolve_cb(makeAddressList({"10.0.0.1"})); + resolve_cb(TestUtility::makeDnsResponse({"10.0.0.1"})); } // Two cache loads that are trying to resolve the same host. Make sure we only do a single resolve @@ -321,7 +313,7 @@ TEST_F(DnsCacheImplTest, MultipleResolveSameHost) { onDnsHostAddOrUpdate("foo.com", SharedAddressEquals("10.0.0.1:80"))); EXPECT_CALL(callbacks2, onLoadDnsCacheComplete()); EXPECT_CALL(callbacks1, onLoadDnsCacheComplete()); - resolve_cb(makeAddressList({"10.0.0.1"})); + resolve_cb(TestUtility::makeDnsResponse({"10.0.0.1"})); } // Two cache loads that are resolving different hosts. @@ -348,12 +340,12 @@ TEST_F(DnsCacheImplTest, MultipleResolveDifferentHost) { EXPECT_CALL(update_callbacks_, onDnsHostAddOrUpdate("bar.com", SharedAddressEquals("10.0.0.1:443"))); EXPECT_CALL(callbacks2, onLoadDnsCacheComplete()); - resolve_cb2(makeAddressList({"10.0.0.1"})); + resolve_cb2(TestUtility::makeDnsResponse({"10.0.0.1"})); EXPECT_CALL(update_callbacks_, onDnsHostAddOrUpdate("foo.com", SharedAddressEquals("10.0.0.2:80"))); EXPECT_CALL(callbacks1, onLoadDnsCacheComplete()); - resolve_cb1(makeAddressList({"10.0.0.2"})); + resolve_cb1(TestUtility::makeDnsResponse({"10.0.0.2"})); } // A successful resolve followed by a cache hit. @@ -372,7 +364,7 @@ TEST_F(DnsCacheImplTest, CacheHit) { EXPECT_CALL(update_callbacks_, onDnsHostAddOrUpdate("foo.com", SharedAddressEquals("10.0.0.1:80"))); EXPECT_CALL(callbacks, onLoadDnsCacheComplete()); - resolve_cb(makeAddressList({"10.0.0.1"})); + resolve_cb(TestUtility::makeDnsResponse({"10.0.0.1"})); result = dns_cache_->loadDnsCacheEntry("foo.com", 80, callbacks); EXPECT_EQ(DnsCache::LoadDnsCacheEntryStatus::InCache, result.status_); @@ -411,7 +403,7 @@ TEST_F(DnsCacheImplTest, InvalidPort) { EXPECT_CALL(update_callbacks_, onDnsHostAddOrUpdate(_, _)).Times(0); EXPECT_CALL(callbacks, onLoadDnsCacheComplete()); - resolve_cb(makeAddressList({})); + resolve_cb(TestUtility::makeDnsResponse({})); } // Max host overflow. diff --git a/test/test_common/utility.cc b/test/test_common/utility.cc index bd3392da5b0f..02b950cb102d 100644 --- a/test/test_common/utility.cc +++ b/test/test_common/utility.cc @@ -181,11 +181,12 @@ void TestUtility::waitForGaugeEq(Stats::Store& store, const std::string& name, u } } -std::list -TestUtility::makeDnsResponse(const std::list& addresses) { - std::list ret; +std::list +TestUtility::makeDnsResponse(const std::list& addresses, std::chrono::seconds ttl) { + std::list ret; for (const auto& address : addresses) { - ret.emplace_back(Network::Utility::parseInternetAddress(address)); + + ret.emplace_back(Network::DnsResponse(Network::Utility::parseInternetAddress(address), ttl)); } return ret; } diff --git a/test/test_common/utility.h b/test/test_common/utility.h index 8f1bdcc721c3..7e33eeff7d1e 100644 --- a/test/test_common/utility.h +++ b/test/test_common/utility.h @@ -223,8 +223,9 @@ class TestUtility { * Convert a string list of IP addresses into a list of network addresses usable for DNS * response testing. */ - static std::list - makeDnsResponse(const std::list& addresses); + static std::list + makeDnsResponse(const std::list& addresses, + std::chrono::seconds = std::chrono::seconds(0)); /** * List files in a given directory path diff --git a/tools/spelling_dictionary.txt b/tools/spelling_dictionary.txt index 7fdc7d95db96..21ef6280e234 100644 --- a/tools/spelling_dictionary.txt +++ b/tools/spelling_dictionary.txt @@ -269,6 +269,7 @@ TPROXY TSAN TSI TTL +TTLs TX TXT UA