[Tools] support set_flag_for_all in tserver use optional parameter 'force'.

This patch adds support for the command `kudu tserver set_flag_for_all`
using --force flag.

Change-Id: I716c2a8be4a6041aa28b5191b55022158536d97c
Reviewed-on: http://gerrit.cloudera.org:8080/19243
Tested-by: Kudu Jenkins
Reviewed-by: Alexey Serbin <alexey@apache.org>
diff --git a/src/kudu/tools/kudu-tool-test.cc b/src/kudu/tools/kudu-tool-test.cc
index 2f24822..48c763c 100644
--- a/src/kudu/tools/kudu-tool-test.cc
+++ b/src/kudu/tools/kudu-tool-test.cc
@@ -227,6 +227,7 @@
 using std::unordered_map;
 using std::unordered_set;
 using std::vector;
+using std::tuple;
 using strings::Substitute;
 
 namespace kudu {
@@ -8624,46 +8625,57 @@
     master_addresses.emplace_back(cluster_->master(i)->bound_rpc_addr().ToString());
   }
   string str_master_addresses = JoinMapped(master_addresses, [](string addr){return addr;}, ",");
-  const string flag_key = "max_log_size";
-  const string flag_value = "10";
-  NO_FATALS(RunActionStdoutNone(
-      Substitute("$0 set_flag_for_all $1 $2 $3",
-          role, str_master_addresses, flag_key, flag_value)));
 
-  int hosts_num = is_master? opts.num_masters : opts.num_tablet_servers;
-  string out;
-  for (int i = 0; i < hosts_num; i++) {
-    if (is_master) {
-      NO_FATALS(RunActionStdoutString(
-          Substitute("$0 get_flags $1 --format=json", role,
-              cluster_->master(i)->bound_rpc_addr().ToString()),
-              &out));
-    } else {
-      NO_FATALS(RunActionStdoutString(
-          Substitute("$0 get_flags $1 --format=json", role,
-          cluster_->tablet_server(i)->bound_rpc_addr().ToString()),
-          &out));
-    }
-    rapidjson::Document doc;
-    doc.Parse<0>(out.c_str());
-    for (int i = 0; i < doc.Size(); i++) {
-      const rapidjson::Value& item = doc[i];
-      ASSERT_TRUE(item["flag"].IsString());
-      if (item["flag"].GetString() == flag_key) {
-        ASSERT_TRUE(item["value"].IsString());
-        ASSERT_TRUE(item["value"].GetString() == flag_value);
-        return;
+  // <flag key, flag value, optional parameter>
+  vector<tuple<string , string , string>> command_parameters;
+  command_parameters.emplace_back(tuple<string, string, string>("max_log_size", "10" , ""));
+  command_parameters.emplace_back(tuple<string, string, string>("log_async", "false" , "--force"));
+
+  for (auto command_parameter : command_parameters) {
+    const string flag_key = std::get<0>(command_parameter);
+    const string flag_value = std::get<1>(command_parameter);
+    const string optional_parameter = std::get<2>(command_parameter);
+    NO_FATALS(RunActionStdoutNone(
+        Substitute("$0 set_flag_for_all $1 $2 $3 $4",
+            role, str_master_addresses, flag_key, flag_value, optional_parameter)));
+
+    int hosts_num = is_master? opts.num_masters : opts.num_tablet_servers;
+    string out;
+    for (int i = 0; i < hosts_num; i++) {
+      if (is_master) {
+        NO_FATALS(RunActionStdoutString(
+            Substitute("$0 get_flags $1 --format=json", role,
+                cluster_->master(i)->bound_rpc_addr().ToString()),
+                &out));
+      } else {
+        NO_FATALS(RunActionStdoutString(
+            Substitute("$0 get_flags $1 --format=json", role,
+            cluster_->tablet_server(i)->bound_rpc_addr().ToString()),
+            &out));
+      }
+      rapidjson::Document doc;
+      doc.Parse<0>(out.c_str());
+      for (int i = 0; i < doc.Size(); i++) {
+        const rapidjson::Value& item = doc[i];
+        ASSERT_TRUE(item["flag"].IsString());
+        if (item["flag"].GetString() == flag_key) {
+          ASSERT_TRUE(item["value"].IsString());
+          ASSERT_TRUE(item["value"].GetString() == flag_value);
+          break;
+        }
       }
     }
   }
 
   // A test for setting a non-existing flag.
+  string stdout;
+  string stderr;
   Status s = RunTool(
-      Substitute("$0 set_flag_for_all $2 test_flag test_value",
+      Substitute("$0 set_flag_for_all $1 test_flag test_value",
           role, str_master_addresses),
-      nullptr, nullptr, nullptr, nullptr);
+      &stdout, &stderr, nullptr, nullptr);
   ASSERT_TRUE(s.IsRuntimeError());
-  ASSERT_STR_CONTAINS(s.ToString(), "set flag failed");
+  ASSERT_STR_CONTAINS(stderr, "result: NO_SUCH_FLAG");
 }
 
 } // namespace tools
diff --git a/src/kudu/tools/tool_action_tserver.cc b/src/kudu/tools/tool_action_tserver.cc
index 4134c9d..4aeb962 100644
--- a/src/kudu/tools/tool_action_tserver.cc
+++ b/src/kudu/tools/tool_action_tserver.cc
@@ -37,7 +37,6 @@
 #include "kudu/master/master.h"
 #include "kudu/master/master.pb.h"
 #include "kudu/master/master.proxy.h"
-#include "kudu/rpc/response_callback.h"
 #include "kudu/rpc/rpc_controller.h"
 #include "kudu/tools/tool_action.h"
 #include "kudu/tools/tool_action_common.h"
@@ -430,6 +429,7 @@
       .Description("Change a gflag value for all Kudu Tablet Servers in the cluster")
       .AddRequiredParameter({ kFlagArg, "Name of the gflag" })
       .AddRequiredParameter({ kValueArg, "New value for the gflag" })
+      .AddOptionalParameter("force")
       .Build();
 
   unique_ptr<Action> status =