This is an automated email from the ASF dual-hosted git repository. awong pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/kudu.git
commit c2f4cf7b8b3240feef6ec0060c99f78d3744d76d Author: Andrew Wong <[email protected]> AuthorDate: Wed Jun 9 12:42:31 2021 -0700 [util] flag to specify hosts to fail DNS resolution This patch adds a flag to specify the specific hostports to which failures are injected by --fail_dns_resolution. I intend on using this in a subsequent patch. Change-Id: I25f2d3073fa0fa0a430afacf7c8cd1402e6bd6ab Reviewed-on: http://gerrit.cloudera.org:8080/17584 Reviewed-by: Alexey Serbin <[email protected]> Tested-by: Andrew Wong <[email protected]> --- src/kudu/util/net/net_util-test.cc | 39 ++++++++++++++++++++++++++++++++++++++ src/kudu/util/net/net_util.cc | 24 +++++++++++++++++++++-- 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/src/kudu/util/net/net_util-test.cc b/src/kudu/util/net/net_util-test.cc index ae85220..c409b2b 100644 --- a/src/kudu/util/net/net_util-test.cc +++ b/src/kudu/util/net/net_util-test.cc @@ -25,10 +25,12 @@ #include <string> #include <vector> +#include <gflags/gflags_declare.h> #include <glog/logging.h> #include <gtest/gtest.h> #include "kudu/gutil/strings/join.h" +#include "kudu/gutil/strings/substitute.h" #include "kudu/gutil/strings/util.h" #include "kudu/util/net/sockaddr.h" #include "kudu/util/net/socket.h" @@ -36,8 +38,12 @@ #include "kudu/util/test_macros.h" #include "kudu/util/test_util.h" +DECLARE_bool(fail_dns_resolution); +DECLARE_string(fail_dns_resolution_hostports); + using std::string; using std::vector; +using strings::Substitute; namespace kudu { @@ -128,6 +134,39 @@ TEST_F(NetUtilTest, TestParseAddressesWithScheme) { ASSERT_STR_CONTAINS(s.ToString(), "invalid scheme format"); } +TEST_F(NetUtilTest, TestInjectFailureToResolveAddresses) { + HostPort hp1("localhost", 12345); + HostPort hp2("localhost", 12346); + FLAGS_fail_dns_resolution_hostports = hp1.ToString(); + FLAGS_fail_dns_resolution = true; + + // With a list of bad hostports specified, check that resolution fails as + // expected. + vector<Sockaddr> addrs; + Status s = hp1.ResolveAddresses(&addrs); + ASSERT_TRUE(s.IsNetworkError()) << s.ToString(); + + // Addresses not in the list should resolve fine. + ASSERT_TRUE(addrs.empty()); + ASSERT_OK(hp2.ResolveAddresses(&addrs)); + ASSERT_FALSE(addrs.empty()); + + // With both in the list, resolution should fail. + FLAGS_fail_dns_resolution_hostports = Substitute("$0,$1", hp1.ToString(), hp2.ToString()); + addrs.clear(); + s = hp1.ResolveAddresses(&addrs); + ASSERT_TRUE(s.IsNetworkError()) << s.ToString(); + s = hp2.ResolveAddresses(&addrs); + ASSERT_TRUE(s.IsNetworkError()) << s.ToString(); + + // When a list isn't specified, all resolution fails. + FLAGS_fail_dns_resolution_hostports = ""; + s = hp1.ResolveAddresses(&addrs); + ASSERT_TRUE(s.IsNetworkError()) << s.ToString(); + s = hp2.ResolveAddresses(&addrs); + ASSERT_TRUE(s.IsNetworkError()) << s.ToString(); +} + TEST_F(NetUtilTest, TestResolveAddresses) { HostPort hp("localhost", 12345); vector<Sockaddr> addrs; diff --git a/src/kudu/util/net/net_util.cc b/src/kudu/util/net/net_util.cc index edfa8e6..ce5e156 100644 --- a/src/kudu/util/net/net_util.cc +++ b/src/kudu/util/net/net_util.cc @@ -64,14 +64,19 @@ #define HOST_NAME_MAX 64 #endif -DEFINE_bool(fail_dns_resolution, false, "Whether to fail all dns resolution, for tests."); +DEFINE_bool(fail_dns_resolution, false, "Whether to fail dns resolution, for tests."); TAG_FLAG(fail_dns_resolution, hidden); +DEFINE_string(fail_dns_resolution_hostports, "", + "Comma-separated list of hostports that fail dns resolution. If empty, fails all " + "dns resolution attempts. Only takes effect if --fail_dns_resolution is 'true'."); +TAG_FLAG(fail_dns_resolution_hostports, hidden); using std::function; using std::string; using std::unordered_set; using std::unique_ptr; using std::vector; +using strings::Split; using strings::Substitute; namespace kudu { @@ -215,7 +220,22 @@ Status HostPort::ResolveAddresses(vector<Sockaddr>* addresses) const { } } if (PREDICT_FALSE(FLAGS_fail_dns_resolution)) { - return Status::NetworkError("injected DNS resolution failure"); + if (FLAGS_fail_dns_resolution_hostports.empty()) { + return Status::NetworkError("injected DNS resolution failure"); + } + unordered_set<string> failed_hostports = + Split(FLAGS_fail_dns_resolution_hostports, ","); + for (const auto& hp_str : failed_hostports) { + HostPort hp; + Status s = hp.ParseString(hp_str, /*default_port=*/0); + if (!s.ok()) { + LOG(WARNING) << "Could not parse: " << hp_str; + continue; + } + if (hp == *this) { + return Status::NetworkError("injected DNS resolution failure", hp_str); + } + } } if (addresses) { *addresses = std::move(result_addresses);
