You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kudu.apache.org by ab...@apache.org on 2020/09/02 17:47:41 UTC

[kudu] branch master updated: KUDU-3185 Add table owner to web UI and tools

This is an automated email from the ASF dual-hosted git repository.

abukor pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/kudu.git


The following commit(s) were added to refs/heads/master by this push:
     new dcb9b71  KUDU-3185 Add table owner to web UI and tools
dcb9b71 is described below

commit dcb9b71e04d8c8894040ac261fc2dfc704f3c819
Author: Attila Bukor <ab...@apache.org>
AuthorDate: Tue Sep 1 15:33:28 2020 +0200

    KUDU-3185 Add table owner to web UI and tools
    
    Table ownership has been added earlier, but currently there's no easy
    way to view the owner of a table. This commit adds this information to
    the `kudu table describe` output and the web UI to the /table and
    /tables pages.
    
    Change-Id: I0791847b58925ec9818943c62fe4a1bc00359749
    Reviewed-on: http://gerrit.cloudera.org:8080/16394
    Tested-by: Kudu Jenkins
    Reviewed-by: Grant Henke <gr...@apache.org>
---
 src/kudu/integration-tests/ts_itest-base.cc |  10 +--
 src/kudu/master/master_path_handlers.cc     |   2 +
 src/kudu/tools/kudu-admin-test.cc           | 129 +++++++++++++++++-----------
 src/kudu/tools/tool_action_table.cc         |   3 +
 www/table.mustache                          |   1 +
 www/tables.mustache                         |   2 +
 6 files changed, 93 insertions(+), 54 deletions(-)

diff --git a/src/kudu/integration-tests/ts_itest-base.cc b/src/kudu/integration-tests/ts_itest-base.cc
index 4fb183b..4386f5d 100644
--- a/src/kudu/integration-tests/ts_itest-base.cc
+++ b/src/kudu/integration-tests/ts_itest-base.cc
@@ -22,7 +22,6 @@
 #include <ostream>
 #include <set>
 #include <string>
-#include <type_traits>
 #include <unordered_map>
 #include <unordered_set>
 #include <utility>
@@ -534,10 +533,11 @@ void TabletServerIntegrationTestBase::CreateTable(const string& table_id) {
   client::KuduSchema client_schema(client::KuduSchema::FromSchema(schema_));
   unique_ptr<client::KuduTableCreator> table_creator(client_->NewTableCreator());
   ASSERT_OK(table_creator->table_name(table_id)
-           .schema(&client_schema)
-           .set_range_partition_columns({ "key" })
-           .num_replicas(FLAGS_num_replicas)
-           .Create());
+                .schema(&client_schema)
+                .set_range_partition_columns({"key"})
+                .num_replicas(FLAGS_num_replicas)
+                .set_owner("alice")
+                .Create());
   ASSERT_OK(client_->OpenTable(table_id, &table_));
 }
 
diff --git a/src/kudu/master/master_path_handlers.cc b/src/kudu/master/master_path_handlers.cc
index 4b106c2..f3573a6 100644
--- a/src/kudu/master/master_path_handlers.cc
+++ b/src/kudu/master/master_path_handlers.cc
@@ -261,6 +261,7 @@ void MasterPathHandlers::HandleCatalogManager(const Webserver::WebRequest& req,
     EasyJson table_json = tables_json.PushBack(EasyJson::kObject);
     table_json["name"] = EscapeForHtmlToString(l.data().name());
     table_json["id"] = EscapeForHtmlToString(table->id());
+    table_json["owner"] = EscapeForHtmlToString(l.data().owner());
     table_json["state"] = state;
     table_json["message"] = EscapeForHtmlToString(l.data().pb.state_msg());
     table_json["tablet_count"] = HumanReadableInt::ToString(table->num_tablets());
@@ -356,6 +357,7 @@ void MasterPathHandlers::HandleTablePage(const Webserver::WebRequest& req,
   {
     TableMetadataLock l(table.get(), LockMode::READ);
     (*output)["name"] = l.data().name();
+    (*output)["owner"] = l.data().owner();
 
     // Not all Kudu tablenames are also valid Impala identifiers. We need to
     // replace such names with a placeholder when they are used as Impala
diff --git a/src/kudu/tools/kudu-admin-test.cc b/src/kudu/tools/kudu-admin-test.cc
index a91c0c7..1294377 100644
--- a/src/kudu/tools/kudu-admin-test.cc
+++ b/src/kudu/tools/kudu-admin-test.cc
@@ -1744,19 +1744,19 @@ TEST_F(AdminCliTest, TestDescribeTable) {
   }, &stdout, &stderr);
   ASSERT_TRUE(s.ok()) << ToolRunInfo(s, stdout, stderr);
 
-  ASSERT_STR_CONTAINS(
-      stdout,
-      "(\n"
-      "    key INT32 NOT NULL,\n"
-      "    int_val INT32 NOT NULL,\n"
-      "    string_val STRING NULLABLE,\n"
-      "    PRIMARY KEY (key)\n"
-      ")\n"
-      "RANGE (key) (\n"
-      "    PARTITION UNBOUNDED"
-      "\n"
-      ")\n"
-      "REPLICAS 1");
+  ASSERT_STR_CONTAINS(stdout,
+                      "(\n"
+                      "    key INT32 NOT NULL,\n"
+                      "    int_val INT32 NOT NULL,\n"
+                      "    string_val STRING NULLABLE,\n"
+                      "    PRIMARY KEY (key)\n"
+                      ")\n"
+                      "RANGE (key) (\n"
+                      "    PARTITION UNBOUNDED"
+                      "\n"
+                      ")\n"
+                      "OWNER alice\n"
+                      "REPLICAS 1");
 
   // Test a table with all types in its schema, multiple hash partitioning
   // levels, multiple range partitions, and non-covered ranges.
@@ -1813,14 +1813,15 @@ TEST_F(AdminCliTest, TestDescribeTable) {
     ASSERT_OK(upper_bound1->SetInt32("key_range", 3));
     unique_ptr<KuduTableCreator> table_creator(client_->NewTableCreator());
     ASSERT_OK(table_creator->table_name(kAnotherTableId)
-             .schema(&schema)
-             .add_hash_partitions({ "key_hash0" }, 2)
-             .add_hash_partitions({ "key_hash1", "key_hash2" }, 3)
-             .set_range_partition_columns({ "key_range" })
-             .add_range_partition(lower_bound0.release(), upper_bound0.release())
-             .add_range_partition(lower_bound1.release(), upper_bound1.release())
-             .num_replicas(FLAGS_num_replicas)
-             .Create());
+                  .schema(&schema)
+                  .add_hash_partitions({"key_hash0"}, 2)
+                  .add_hash_partitions({"key_hash1", "key_hash2"}, 3)
+                  .set_range_partition_columns({"key_range"})
+                  .add_range_partition(lower_bound0.release(), upper_bound0.release())
+                  .add_range_partition(lower_bound1.release(), upper_bound1.release())
+                  .num_replicas(FLAGS_num_replicas)
+                  .set_owner("alice")
+                  .Create());
   }
 
   // OK, all that busywork is done. Test the describe output.
@@ -1834,34 +1835,34 @@ TEST_F(AdminCliTest, TestDescribeTable) {
   }, &stdout, &stderr);
   ASSERT_TRUE(s.ok()) << ToolRunInfo(s, stdout, stderr);
 
-  ASSERT_STR_CONTAINS(
-      stdout,
-      "(\n"
-      "    key_hash0 INT32 NOT NULL,\n"
-      "    key_hash1 INT32 NOT NULL,\n"
-      "    key_hash2 INT32 NOT NULL,\n"
-      "    key_range INT32 NOT NULL,\n"
-      "    int8_val INT8 NULLABLE,\n"
-      "    int16_val INT16 NULLABLE,\n"
-      "    int32_val INT32 NULLABLE,\n"
-      "    int64_val INT64 NULLABLE,\n"
-      "    timestamp_val UNIXTIME_MICROS NULLABLE,\n"
-      "    date_val DATE NULLABLE,\n"
-      "    string_val STRING NULLABLE,\n"
-      "    bool_val BOOL NULLABLE,\n"
-      "    float_val FLOAT NULLABLE,\n"
-      "    double_val DOUBLE NULLABLE,\n"
-      "    binary_val BINARY NULLABLE,\n"
-      "    decimal_val DECIMAL(30, 4) NULLABLE,\n"
-      "    PRIMARY KEY (key_hash0, key_hash1, key_hash2, key_range)\n"
-      ")\n"
-      "HASH (key_hash0) PARTITIONS 2,\n"
-      "HASH (key_hash1, key_hash2) PARTITIONS 3,\n"
-      "RANGE (key_range) (\n"
-      "    PARTITION 0 <= VALUES < 1,\n"
-      "    PARTITION 2 <= VALUES < 3\n"
-      ")\n"
-      "REPLICAS 1");
+  ASSERT_STR_CONTAINS(stdout,
+                      "(\n"
+                      "    key_hash0 INT32 NOT NULL,\n"
+                      "    key_hash1 INT32 NOT NULL,\n"
+                      "    key_hash2 INT32 NOT NULL,\n"
+                      "    key_range INT32 NOT NULL,\n"
+                      "    int8_val INT8 NULLABLE,\n"
+                      "    int16_val INT16 NULLABLE,\n"
+                      "    int32_val INT32 NULLABLE,\n"
+                      "    int64_val INT64 NULLABLE,\n"
+                      "    timestamp_val UNIXTIME_MICROS NULLABLE,\n"
+                      "    date_val DATE NULLABLE,\n"
+                      "    string_val STRING NULLABLE,\n"
+                      "    bool_val BOOL NULLABLE,\n"
+                      "    float_val FLOAT NULLABLE,\n"
+                      "    double_val DOUBLE NULLABLE,\n"
+                      "    binary_val BINARY NULLABLE,\n"
+                      "    decimal_val DECIMAL(30, 4) NULLABLE,\n"
+                      "    PRIMARY KEY (key_hash0, key_hash1, key_hash2, key_range)\n"
+                      ")\n"
+                      "HASH (key_hash0) PARTITIONS 2,\n"
+                      "HASH (key_hash1, key_hash2) PARTITIONS 3,\n"
+                      "RANGE (key_range) (\n"
+                      "    PARTITION 0 <= VALUES < 1,\n"
+                      "    PARTITION 2 <= VALUES < 3\n"
+                      ")\n"
+                      "OWNER alice\n"
+                      "REPLICAS 1");
 
   // Test the describe output with `-show_attributes=true`.
   stdout.clear();
@@ -1902,9 +1903,39 @@ TEST_F(AdminCliTest, TestDescribeTable) {
       "    PARTITION 0 <= VALUES < 1,\n"
       "    PARTITION 2 <= VALUES < 3\n"
       ")\n"
+      "OWNER alice\n"
       "REPLICAS 1");
 }
 
+TEST_F(AdminCliTest, TestDescribeTableNoOwner) {
+  NO_FATALS(BuildAndStart({}, {"--allow_empty_owner=true"}));
+  KuduSchema schema;
+  KuduSchemaBuilder builder;
+  builder.AddColumn("foo")->Type(KuduColumnSchema::INT32)->NotNull()->PrimaryKey();
+  ASSERT_OK(builder.Build(&schema));
+
+  const string kTableName = "table_without_owner";
+
+  unique_ptr<KuduTableCreator> table_creator(client_->NewTableCreator());
+  ASSERT_OK(table_creator->table_name(kTableName)
+                .schema(&schema)
+                .set_range_partition_columns({"foo"})
+                .num_replicas(1)
+                .set_owner("")
+                .Create());
+
+  string stdout;
+  ASSERT_OK(RunKuduTool(
+      {
+          "table",
+          "describe",
+          cluster_->master()->bound_rpc_addr().ToString(),
+          kTableName,
+      },
+      &stdout));
+  ASSERT_STR_CONTAINS(stdout, "OWNER \n");
+}
+
 TEST_F(AdminCliTest, TestLocateRow) {
   FLAGS_num_tablet_servers = 1;
   FLAGS_num_replicas = 1;
diff --git a/src/kudu/tools/tool_action_table.cc b/src/kudu/tools/tool_action_table.cc
index ff09039..2071ae7 100644
--- a/src/kudu/tools/tool_action_table.cc
+++ b/src/kudu/tools/tool_action_table.cc
@@ -233,6 +233,9 @@ Status DescribeTable(const RunnerContext& context) {
   cout << partition_schema.DisplayString(schema_internal, partition_strs)
        << endl;
 
+  // The owner.
+  cout << "OWNER " << table->owner() << endl;
+
   // Finally, the replication factor.
   cout << "REPLICAS " << table->num_replicas() << endl;
 
diff --git a/www/table.mustache b/www/table.mustache
index af1a6de..4b7aee4 100644
--- a/www/table.mustache
+++ b/www/table.mustache
@@ -29,6 +29,7 @@ under the License.
   <h2>Table: {{name}} ({{id}})</h2>
   <table class="table table-striped">
     <tbody>
+    <tr><td>Owner:</td><td>{{owner}}</td></tr>
     <tr><td>Version:</td><td>{{version}}</td></tr>
     <tr><td>State:</td><td>{{state}} {{#state_msg}}({{.}}){{/state_msg}}</td></tr>
     <tr><td>Column Count:</td><td>{{column_count}}</td></tr>
diff --git a/www/tables.mustache b/www/tables.mustache
index 5d2e82b..e2871cd 100644
--- a/www/tables.mustache
+++ b/www/tables.mustache
@@ -32,6 +32,7 @@ There are {{num_tables}} tables.
   <thead><tr>
     <th data-sorter="stringsSorter" data-sortable="true">Table Name</th>
     <th>Table Id</th>
+    <th data-sorter="stringsSorter" data-sortable="true">Owner</th>
     <th>State</th>
     <th>State Message</th>
     <th data-sorter="numericStringsSorter" data-sortable="true">Tablet Count</th>
@@ -44,6 +45,7 @@ There are {{num_tables}} tables.
     <tr>
       <td>{{name}}</td>
       <td><a href="{{base_url}}/table?id={{id}}">{{id}}</a></td>
+      <td>{{owner}}</td>
       <td>{{state}}</td>
       <td>{{message}}</td>
       <td>{{tablet_count}}</td>