Repository: kudu
Updated Branches:
  refs/heads/master 337a731c4 -> 00c2754ca


 Add GetFlags endpoint and tool

This adds an rpc endpoint that retrieves gflags from servers.

It also includes a tool for retrieving flag values from servers.
By default, it returns only flags with non-default values. It
supports returning all flags, and also filtering flags by tags.

Example output from the tool run against a local cluster's master:

          flag          |                     value                     | 
default? |      tags
------------------------+-----------------------------------------------+----------+-----------------
 log_dir                | /tmp/kudu/logs/master/0                       | false 
   | stable
 heap_profile_path      | /tmp/kudu-master.56285                        | false 
   | advanced,stable
 log_filename           | kudu-master                                   | false 
   | stable
 webserver_interface    | 127.0.0.1                                     | false 
   | advanced
 master_addresses       | 127.0.0.1:7053,127.0.0.1:7052,127.0.0.1:7051, | false 
   | stable
 fs_data_dirs           | /tmp/kudu/data/master/0/0                     | false 
   | stable
 rpc_bind_addresses     | 127.0.0.1:7051                                | false 
   | stable
 fs_wal_dir             | /tmp/kudu/wal/master/0                        | false 
   | stable
 evict_failed_followers | false                                         | false 
   | advanced
 webserver_port         | 8051                                          | false 
   | stable

The rpc endpoint will also be used by ksck in a follow-up.

Change-Id: Ia35b4261099c1a3c6e2ff68e907c84df9a7ff699
Reviewed-on: http://gerrit.cloudera.org:8080/9948
Tested-by: Kudu Jenkins
Reviewed-by: Adar Dembo <a...@cloudera.com>


Project: http://git-wip-us.apache.org/repos/asf/kudu/repo
Commit: http://git-wip-us.apache.org/repos/asf/kudu/commit/21f651db
Tree: http://git-wip-us.apache.org/repos/asf/kudu/tree/21f651db
Diff: http://git-wip-us.apache.org/repos/asf/kudu/diff/21f651db

Branch: refs/heads/master
Commit: 21f651db1c51d80c9ce2761e3d07aa1129d1faca
Parents: 337a731
Author: Will Berkeley <wdberke...@apache.org>
Authored: Mon Apr 2 16:13:21 2018 -0700
Committer: Will Berkeley <wdberke...@gmail.com>
Committed: Tue Apr 10 18:44:49 2018 +0000

----------------------------------------------------------------------
 src/kudu/server/generic_service.cc     | 36 ++++++++++++++-
 src/kudu/server/generic_service.h      |  6 +++
 src/kudu/server/server_base.proto      | 24 ++++++++++
 src/kudu/tools/kudu-tool-test.cc       | 48 ++++++++++++++++++++
 src/kudu/tools/tool_action_common.cc   | 44 +++++++++++++++++++
 src/kudu/tools/tool_action_common.h    |  5 +++
 src/kudu/tools/tool_action_master.cc   | 14 ++++++
 src/kudu/tools/tool_action_tserver.cc  | 14 ++++++
 src/kudu/tserver/tablet_server-test.cc | 68 +++++++++++++++++++++++++++++
 src/kudu/util/flags.cc                 | 26 +++++------
 src/kudu/util/flags.h                  |  2 +
 11 files changed, 273 insertions(+), 14 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/kudu/blob/21f651db/src/kudu/server/generic_service.cc
----------------------------------------------------------------------
diff --git a/src/kudu/server/generic_service.cc 
b/src/kudu/server/generic_service.cc
index e786c63..300e37f 100644
--- a/src/kudu/server/generic_service.cc
+++ b/src/kudu/server/generic_service.cc
@@ -17,9 +17,10 @@
 
 #include "kudu/server/generic_service.h"
 
-#include <string>
 #include <ostream>
+#include <string>
 #include <unordered_set>
+#include <utility>
 
 #include <gflags/gflags.h>
 #include <gflags/gflags_declare.h>
@@ -39,6 +40,7 @@
 #include "kudu/util/debug-util.h"
 #include "kudu/util/debug/leak_annotations.h" // IWYU pragma: keep
 #include "kudu/util/flag_tags.h"
+#include "kudu/util/flags.h"
 #include "kudu/util/status.h"
 
 DECLARE_string(time_source);
@@ -71,6 +73,38 @@ bool GenericServiceImpl::AuthorizeClient(const 
google::protobuf::Message* /*req*
 }
 
 
+void GenericServiceImpl::GetFlags(const GetFlagsRequestPB* req,
+                                  GetFlagsResponsePB* resp,
+                                  rpc::RpcContext* rpc) {
+  // If no tags were specified, return all flags that have non-default values.
+  // If tags were specified, also filter flags that don't match any tag.
+  bool all_flags = req->all_flags();
+  for (const auto& entry : GetFlagsMap()) {
+    if (entry.second.is_default && !all_flags) {
+      continue;
+    }
+    unordered_set<string> tags;
+    GetFlagTags(entry.first, &tags);
+    bool matches = req->tags().empty();
+    for (const auto& tag : req->tags()) {
+      if (ContainsKey(tags, tag)) {
+        matches = true;
+        break;
+      }
+    }
+    if (!matches) continue;
+
+    auto* flag = resp->add_flags();
+    flag->set_name(entry.first);
+    flag->set_value(CheckFlagAndRedact(entry.second, EscapeMode::NONE));
+    flag->set_is_default_value(entry.second.current_value == 
entry.second.default_value);
+    for (const auto& tag : tags) {
+      flag->add_tags(tag);
+    }
+  }
+  rpc->RespondSuccess();
+}
+
 void GenericServiceImpl::SetFlag(const SetFlagRequestPB* req,
                                  SetFlagResponsePB* resp,
                                  rpc::RpcContext* rpc) {

http://git-wip-us.apache.org/repos/asf/kudu/blob/21f651db/src/kudu/server/generic_service.h
----------------------------------------------------------------------
diff --git a/src/kudu/server/generic_service.h 
b/src/kudu/server/generic_service.h
index bfc8704..4cf0f79 100644
--- a/src/kudu/server/generic_service.h
+++ b/src/kudu/server/generic_service.h
@@ -39,6 +39,8 @@ class CheckLeaksRequestPB;
 class CheckLeaksResponsePB;
 class FlushCoverageRequestPB;
 class FlushCoverageResponsePB;
+class GetFlagsRequestPB;
+class GetFlagsResponsePB;
 class GetStatusRequestPB;
 class GetStatusResponsePB;
 class ServerBase;
@@ -62,6 +64,10 @@ class GenericServiceImpl : public GenericServiceIf {
                        google::protobuf::Message* resp,
                        rpc::RpcContext* rpc) override;
 
+  virtual void GetFlags(const GetFlagsRequestPB* req,
+                        GetFlagsResponsePB* resp,
+                        rpc::RpcContext* rpc) OVERRIDE;
+
   virtual void SetFlag(const SetFlagRequestPB* req,
                        SetFlagResponsePB* resp,
                        rpc::RpcContext* rpc) OVERRIDE;

http://git-wip-us.apache.org/repos/asf/kudu/blob/21f651db/src/kudu/server/server_base.proto
----------------------------------------------------------------------
diff --git a/src/kudu/server/server_base.proto 
b/src/kudu/server/server_base.proto
index a80c962..cf680dd 100644
--- a/src/kudu/server/server_base.proto
+++ b/src/kudu/server/server_base.proto
@@ -39,6 +39,27 @@ message ServerStatusPB {
   // So, do not expose anything here which may be sensitive!
 }
 
+// Retrieve the values of command line flags.
+message GetFlagsRequestPB {
+  // Whether to return all flags, or only flags with non-default values.
+  optional bool all_flags = 1;
+  // A list of flag tags. Flags that match at least one tag are returned. If
+  // no tags are specified, all flags match.
+  repeated string tags = 2;
+}
+
+message GetFlagsResponsePB {
+  message Flag {
+    optional string name = 1;
+    optional string value = 2;
+    repeated string tags = 3;
+    // true if the flag has its default value.
+    optional bool is_default_value = 4;
+  }
+
+  repeated Flag flags = 1;
+}
+
 // Attempt to set a command line flag.
 // Note that many command line flags do not take effect if changed
 // at runtime.
@@ -127,6 +148,9 @@ message SetServerWallClockForTestsResponsePB {
 service GenericService {
   option (kudu.rpc.default_authz_method) = "AuthorizeSuperUser";
 
+  rpc GetFlags(GetFlagsRequestPB)
+    returns (GetFlagsResponsePB);
+
   rpc SetFlag(SetFlagRequestPB)
     returns (SetFlagResponsePB);
 

http://git-wip-us.apache.org/repos/asf/kudu/blob/21f651db/src/kudu/tools/kudu-tool-test.cc
----------------------------------------------------------------------
diff --git a/src/kudu/tools/kudu-tool-test.cc b/src/kudu/tools/kudu-tool-test.cc
index 361b8be..d436f9e 100644
--- a/src/kudu/tools/kudu-tool-test.cc
+++ b/src/kudu/tools/kudu-tool-test.cc
@@ -477,6 +477,7 @@ TEST_F(ToolTest, TestModeHelp) {
   }
   {
     const vector<string> kMasterModeRegexes = {
+        "get_flags.*Get the gflags",
         "set_flag.*Change a gflag value",
         "status.*Get the status",
         "timestamp.*Get the current timestamp"
@@ -537,6 +538,7 @@ TEST_F(ToolTest, TestModeHelp) {
   }
   {
     const vector<string> kTServerModeRegexes = {
+        "get_flags.*Get the gflags",
         "set_flag.*Change a gflag value",
         "status.*Get the status",
         "timestamp.*Get the current timestamp",
@@ -2481,5 +2483,51 @@ TEST_F(ToolTest, TestReplaceTablet) {
   ASSERT_GE(workload.rows_inserted(), CountTableRows(workload_table.get()));
 }
 
+TEST_F(ToolTest, TestGetFlags) {
+  ExternalMiniClusterOptions opts;
+  opts.num_tablet_servers = 1;
+  NO_FATALS(StartExternalMiniCluster(std::move(opts)));
+
+  // Check that we get non-default flags.
+  // CSV formatting is easiest to match against.
+  // It seems safe to assume that -help and -logemaillevel will not be
+  // set, and that fs_wal_dir will be set to a non-default value.
+  for (const string& daemon_type : { "master", "tserver" }) {
+    const string& daemon_addr = daemon_type == "master" ?
+                                
cluster_->master()->bound_rpc_addr().ToString() :
+                                
cluster_->tablet_server(0)->bound_rpc_addr().ToString();
+    const string& wal_dir = daemon_type == "master" ?
+                            cluster_->master()->wal_dir() :
+                            cluster_->tablet_server(0)->wal_dir();
+    string out;
+    NO_FATALS(RunActionStdoutString(
+          Substitute("$0 get_flags $1 -format=csv", daemon_type, daemon_addr),
+          &out));
+    ASSERT_STR_NOT_MATCHES(out, "help,*");
+    ASSERT_STR_NOT_MATCHES(out, "logemaillevel,*");
+    ASSERT_STR_CONTAINS(out, Substitute("fs_wal_dir,$0,false", wal_dir));
+
+    // Check that we get all flags with -all_flags.
+    out.clear();
+    NO_FATALS(RunActionStdoutString(
+          Substitute("$0 get_flags $1 -format=csv -all_flags", daemon_type, 
daemon_addr),
+          &out));
+    ASSERT_STR_CONTAINS(out, "help,false,true");
+    ASSERT_STR_CONTAINS(out, "logemaillevel,999,true");
+    ASSERT_STR_CONTAINS(out, Substitute("fs_wal_dir,$0,false", wal_dir));
+
+    // Check that -flag_tags filter to matching tags.
+    // -logemaillevel is an unsafe flag.
+    out.clear();
+    NO_FATALS(RunActionStdoutString(
+          Substitute("$0 get_flags $1 -format=csv -all_flags 
-flag_tags=stable",
+                     daemon_type, daemon_addr),
+          &out));
+    ASSERT_STR_CONTAINS(out, "help,false,true");
+    ASSERT_STR_NOT_MATCHES(out, "logemaillevel,*");
+    ASSERT_STR_CONTAINS(out, Substitute("fs_wal_dir,$0,false", wal_dir));
+  }
+}
+
 } // namespace tools
 } // namespace kudu

http://git-wip-us.apache.org/repos/asf/kudu/blob/21f651db/src/kudu/tools/tool_action_common.cc
----------------------------------------------------------------------
diff --git a/src/kudu/tools/tool_action_common.cc 
b/src/kudu/tools/tool_action_common.cc
index df019d3..9edc548 100644
--- a/src/kudu/tools/tool_action_common.cc
+++ b/src/kudu/tools/tool_action_common.cc
@@ -24,6 +24,7 @@
 #include <cstddef>
 #include <iomanip>
 #include <iostream>
+#include <iterator>
 #include <memory>
 #include <numeric>
 #include <string>
@@ -50,6 +51,7 @@
 #include "kudu/gutil/endian.h"
 #include "kudu/gutil/map-util.h"
 #include "kudu/gutil/ref_counted.h"
+#include "kudu/gutil/strings/join.h"
 #include "kudu/gutil/strings/numbers.h"
 #include "kudu/gutil/strings/split.h"
 #include "kudu/gutil/strings/substitute.h"
@@ -94,6 +96,11 @@ DEFINE_string(format, "pretty",
               "Format to use for printing list output tables.\n"
               "Possible values: pretty, space, tsv, csv, and json");
 
+DEFINE_string(flag_tags, "", "Comma-separated list of tags used to restrict 
which "
+                             "flags are returned. An empty value matches all 
tags");
+DEFINE_bool(all_flags, false, "Whether to return all flags, or only flags that 
"
+                              "were explicitly set.");
+
 namespace boost {
 template <typename Signature>
 class function;
@@ -133,6 +140,8 @@ using rpc::MessengerBuilder;
 using rpc::RequestIdPB;
 using rpc::RpcController;
 using server::GenericServiceProxy;
+using server::GetFlagsRequestPB;
+using server::GetFlagsResponsePB;
 using server::GetStatusRequestPB;
 using server::GetStatusResponsePB;
 using server::ServerClockRequestPB;
@@ -354,6 +363,41 @@ Status PrintSegment(const 
scoped_refptr<ReadableLogSegment>& segment) {
   return Status::OK();
 }
 
+Status PrintServerFlags(const string& address, uint16_t default_port) {
+  unique_ptr<GenericServiceProxy> proxy;
+  RETURN_NOT_OK(BuildProxy(address, default_port, &proxy));
+
+  GetFlagsRequestPB req;
+  GetFlagsResponsePB resp;
+  RpcController rpc;
+  rpc.set_timeout(MonoDelta::FromMilliseconds(FLAGS_timeout_ms));
+
+  req.set_all_flags(FLAGS_all_flags);
+  vector<string> tags = strings::Split(FLAGS_flag_tags, ",", 
strings::SkipEmpty());
+  for (const auto& tag : tags) {
+    req.add_tags(tag);
+  }
+  RETURN_NOT_OK(proxy->GetFlags(req, &resp, &rpc));
+
+  vector<GetFlagsResponsePB::Flag> flags(resp.flags().begin(), 
resp.flags().end());
+  std::sort(flags.begin(), flags.end(),
+      [](const GetFlagsResponsePB::Flag& left,
+         const GetFlagsResponsePB::Flag& right) -> bool {
+        return left.name() < right.name();
+      });
+  DataTable table({ "flag", "value", "default value?", "tags" });
+  for (const auto& flag : flags) {
+    tags.clear();
+    std::copy(flag.tags().begin(), flag.tags().end(), 
std::back_inserter(tags));
+    std::sort(tags.begin(), tags.end());
+    table.AddRow({ flag.name(),
+                   flag.value(),
+                   Substitute("$0", flag.is_default_value()),
+                   JoinStrings(tags, ",") });
+  }
+  return table.PrintTo(cout);
+}
+
 Status SetServerFlag(const string& address, uint16_t default_port,
                      const string& flag, const string& value) {
   unique_ptr<GenericServiceProxy> proxy;

http://git-wip-us.apache.org/repos/asf/kudu/blob/21f651db/src/kudu/tools/tool_action_common.h
----------------------------------------------------------------------
diff --git a/src/kudu/tools/tool_action_common.h 
b/src/kudu/tools/tool_action_common.h
index e7e46cd..3f4a179 100644
--- a/src/kudu/tools/tool_action_common.h
+++ b/src/kudu/tools/tool_action_common.h
@@ -105,6 +105,11 @@ Status PrintServerStatus(const std::string& address, 
uint16_t default_port);
 // If 'address' does not contain a port, 'default_port' is used instead.
 Status PrintServerTimestamp(const std::string& address, uint16_t default_port);
 
+// Prints the values of the gflags set for the Kudu server running at 
'address'.
+//
+// If 'address' does not contain a port, 'default_port' is used instead.
+Status PrintServerFlags(const std::string& address, uint16_t default_port);
+
 // Changes the value of the gflag given by 'flag' to the value in 'value' on
 // the Kudu server running at 'address'.
 //

http://git-wip-us.apache.org/repos/asf/kudu/blob/21f651db/src/kudu/tools/tool_action_master.cc
----------------------------------------------------------------------
diff --git a/src/kudu/tools/tool_action_master.cc 
b/src/kudu/tools/tool_action_master.cc
index 611b36a..ae07172 100644
--- a/src/kudu/tools/tool_action_master.cc
+++ b/src/kudu/tools/tool_action_master.cc
@@ -65,6 +65,11 @@ const char* const kMasterAddressDesc = "Address of a Kudu 
Master of form "
 const char* const kFlagArg = "flag";
 const char* const kValueArg = "value";
 
+Status MasterGetFlags(const RunnerContext& context) {
+  const string& address = FindOrDie(context.required_args, kMasterAddressArg);
+  return PrintServerFlags(address, master::Master::kDefaultPort);
+}
+
 Status MasterSetFlag(const RunnerContext& context) {
   const string& address = FindOrDie(context.required_args, kMasterAddressArg);
   const string& flag = FindOrDie(context.required_args, kFlagArg);
@@ -152,6 +157,14 @@ Status ListMasters(const RunnerContext& context) {
 } // anonymous namespace
 
 unique_ptr<Mode> BuildMasterMode() {
+  unique_ptr<Action> get_flags =
+      ActionBuilder("get_flags", &MasterGetFlags)
+      .Description("Get the gflags for a Kudu Master")
+      .AddRequiredParameter({ kMasterAddressArg, kMasterAddressDesc })
+      .AddOptionalParameter("all_flags")
+      .AddOptionalParameter("flag_tags")
+      .Build();
+
   unique_ptr<Action> set_flag =
       ActionBuilder("set_flag", &MasterSetFlag)
       .Description("Change a gflag value on a Kudu Master")
@@ -187,6 +200,7 @@ unique_ptr<Mode> BuildMasterMode() {
 
   return ModeBuilder("master")
       .Description("Operate on a Kudu Master")
+      .AddAction(std::move(get_flags))
       .AddAction(std::move(set_flag))
       .AddAction(std::move(status))
       .AddAction(std::move(timestamp))

http://git-wip-us.apache.org/repos/asf/kudu/blob/21f651db/src/kudu/tools/tool_action_tserver.cc
----------------------------------------------------------------------
diff --git a/src/kudu/tools/tool_action_tserver.cc 
b/src/kudu/tools/tool_action_tserver.cc
index 1a1dc85..03e007f 100644
--- a/src/kudu/tools/tool_action_tserver.cc
+++ b/src/kudu/tools/tool_action_tserver.cc
@@ -64,6 +64,11 @@ const char* const kTServerAddressDesc = "Address of a Kudu 
Tablet Server of "
 const char* const kFlagArg = "flag";
 const char* const kValueArg = "value";
 
+Status TServerGetFlags(const RunnerContext& context) {
+  const string& address = FindOrDie(context.required_args, kTServerAddressArg);
+  return PrintServerFlags(address, tserver::TabletServer::kDefaultPort);
+}
+
 Status TServerSetFlag(const RunnerContext& context) {
   const string& address = FindOrDie(context.required_args, kTServerAddressArg);
   const string& flag = FindOrDie(context.required_args, kFlagArg);
@@ -146,6 +151,14 @@ Status ListTServers(const RunnerContext& context) {
 } // anonymous namespace
 
 unique_ptr<Mode> BuildTServerMode() {
+  unique_ptr<Action> get_flags =
+      ActionBuilder("get_flags", &TServerGetFlags)
+      .Description("Get the gflags for a Kudu Tablet Server")
+      .AddRequiredParameter({ kTServerAddressArg, kTServerAddressDesc })
+      .AddOptionalParameter("all_flags")
+      .AddOptionalParameter("flag_tags")
+      .Build();
+
   unique_ptr<Action> set_flag =
       ActionBuilder("set_flag", &TServerSetFlag)
       .Description("Change a gflag value on a Kudu Tablet Server")
@@ -182,6 +195,7 @@ unique_ptr<Mode> BuildTServerMode() {
 
   return ModeBuilder("tserver")
       .Description("Operate on a Kudu Tablet Server")
+      .AddAction(std::move(get_flags))
       .AddAction(std::move(set_flag))
       .AddAction(std::move(status))
       .AddAction(std::move(timestamp))

http://git-wip-us.apache.org/repos/asf/kudu/blob/21f651db/src/kudu/tserver/tablet_server-test.cc
----------------------------------------------------------------------
diff --git a/src/kudu/tserver/tablet_server-test.cc 
b/src/kudu/tserver/tablet_server-test.cc
index 63b2998..6dba667 100644
--- a/src/kudu/tserver/tablet_server-test.cc
+++ b/src/kudu/tserver/tablet_server-test.cc
@@ -256,6 +256,74 @@ TEST_F(TabletServerTest, TestServerClock) {
   ASSERT_GT(mini_server_->server()->clock()->Now().ToUint64(), 
resp.timestamp());
 }
 
+TEST_F(TabletServerTest, TestGetFlags) {
+  server::GenericServiceProxy proxy(
+      client_messenger_, mini_server_->bound_rpc_addr(),
+      mini_server_->bound_rpc_addr().host());
+
+  server::GetFlagsRequestPB req;
+  server::GetFlagsResponsePB resp;
+
+  // Check that a default request returns flags set to a non-default value and
+  // does not return flags set to a default value.
+  // Throughout, we make the reasonable assumption that the -fs_wal_dir flag
+  // will have a non-default value, and the -help and unsafe -logemaillevel
+  // flags will have default values.
+  {
+    RpcController controller;
+    ASSERT_OK(proxy.GetFlags(req, &resp, &controller));
+    SCOPED_TRACE(SecureDebugString(resp));
+    EXPECT_TRUE(std::any_of(resp.flags().begin(), resp.flags().end(),
+          [](const server::GetFlagsResponsePB::Flag& flag) -> bool {
+            return flag.name() == "log_dir";
+          }));
+    EXPECT_TRUE(std::none_of(resp.flags().begin(), resp.flags().end(),
+          [](const server::GetFlagsResponsePB::Flag& flag) -> bool {
+            return flag.name() == "help";
+          }));
+  }
+
+  // Check that specifying all flags returns even flags with default values.
+  {
+    RpcController controller;
+    req.set_all_flags(true);
+    ASSERT_OK(proxy.GetFlags(req, &resp, &controller));
+    SCOPED_TRACE(SecureDebugString(resp));
+    EXPECT_TRUE(std::any_of(resp.flags().begin(), resp.flags().end(),
+          [](const server::GetFlagsResponsePB::Flag& flag) -> bool {
+            return flag.name() == "log_dir";
+          }));
+    EXPECT_TRUE(std::any_of(resp.flags().begin(), resp.flags().end(),
+          [](const server::GetFlagsResponsePB::Flag& flag) -> bool {
+            return flag.name() == "help";
+          }));
+    EXPECT_TRUE(std::any_of(resp.flags().begin(), resp.flags().end(),
+          [](const server::GetFlagsResponsePB::Flag& flag) -> bool {
+            return flag.name() == "logemaillevel";
+          }));
+  }
+
+  // Check that filtering on tags excludes flags with no matching tag.
+  {
+    RpcController controller;
+    req.add_tags("stable");
+    ASSERT_OK(proxy.GetFlags(req, &resp, &controller));
+    SCOPED_TRACE(SecureDebugString(resp));
+    EXPECT_TRUE(std::any_of(resp.flags().begin(), resp.flags().end(),
+          [](const server::GetFlagsResponsePB::Flag& flag) -> bool {
+            return flag.name() == "log_dir";
+          }));
+    EXPECT_TRUE(std::any_of(resp.flags().begin(), resp.flags().end(),
+          [](const server::GetFlagsResponsePB::Flag& flag) -> bool {
+            return flag.name() == "help";
+          }));
+    EXPECT_TRUE(std::none_of(resp.flags().begin(), resp.flags().end(),
+          [](const server::GetFlagsResponsePB::Flag& flag) -> bool {
+            return flag.name() == "logemaillevel";
+          }));
+  }
+}
+
 TEST_F(TabletServerTest, TestSetFlags) {
   server::GenericServiceProxy proxy(
       client_messenger_, mini_server_->bound_rpc_addr(),

http://git-wip-us.apache.org/repos/asf/kudu/blob/21f651db/src/kudu/util/flags.cc
----------------------------------------------------------------------
diff --git a/src/kudu/util/flags.cc b/src/kudu/util/flags.cc
index e091d3d..3520be5 100644
--- a/src/kudu/util/flags.cc
+++ b/src/kudu/util/flags.cc
@@ -450,6 +450,19 @@ void RunCustomValidators() {
   }
 }
 
+void SetUmask() {
+  // We already validated with a nice error message using the ValidateUmask
+  // FlagValidator above.
+  CHECK(safe_strtou32_base(FLAGS_umask.c_str(), &g_parsed_umask, 8));
+  uint32_t old_mask = umask(g_parsed_umask);
+  if (old_mask != g_parsed_umask) {
+    VLOG(2) << "Changed umask from " << StringPrintf("%03o", old_mask) << " to 
"
+            << StringPrintf("%03o", g_parsed_umask);
+  }
+}
+
+} // anonymous namespace
+
 // If --redact indicates, redact the flag tagged as 'sensitive'.
 // Otherwise, return its value as-is. If EscapeMode is set to HTML,
 // return HTML escaped string.
@@ -469,19 +482,6 @@ string CheckFlagAndRedact(const CommandLineFlagInfo& flag, 
EscapeMode mode) {
   return ret_value;
 }
 
-void SetUmask() {
-  // We already validated with a nice error message using the ValidateUmask
-  // FlagValidator above.
-  CHECK(safe_strtou32_base(FLAGS_umask.c_str(), &g_parsed_umask, 8));
-  uint32_t old_mask = umask(g_parsed_umask);
-  if (old_mask != g_parsed_umask) {
-    VLOG(2) << "Changed umask from " << StringPrintf("%03o", old_mask) << " to 
"
-            << StringPrintf("%03o", g_parsed_umask);
-  }
-}
-
-} // anonymous namespace
-
 int ParseCommandLineFlags(int* argc, char*** argv, bool remove_flags) {
   // The logbufsecs default is 30 seconds which is a bit too long.
   google::SetCommandLineOptionWithMode("logbufsecs", "5",

http://git-wip-us.apache.org/repos/asf/kudu/blob/21f651db/src/kudu/util/flags.h
----------------------------------------------------------------------
diff --git a/src/kudu/util/flags.h b/src/kudu/util/flags.h
index 032c3e3..83cb152 100644
--- a/src/kudu/util/flags.h
+++ b/src/kudu/util/flags.h
@@ -83,5 +83,7 @@ enum class TriStateFlag {
 Status ParseTriState(const char* flag_name, const std::string& flag_value,
     TriStateFlag* tri_state);
 
+std::string CheckFlagAndRedact(const google::CommandLineFlagInfo& flag, 
EscapeMode mode);
+
 } // namespace kudu
 #endif /* KUDU_UTIL_FLAGS_H */

Reply via email to