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

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


The following commit(s) were added to refs/heads/master by this push:
     new b804e2b  KNOX-2343 - Enhanced API services' display on the Knox Home 
page (#355)
b804e2b is described below

commit b804e2b01418c544eeb5d432de0df9a339d9f92d
Author: Sandor Molnar <[email protected]>
AuthorDate: Wed Jul 1 17:04:11 2020 +0200

    KNOX-2343 - Enhanced API services' display on the Knox Home page (#355)
---
 .../knox/gateway/service/definition/Metadata.java  | 14 ++++
 .../definition/{Metadata.java => Sample.java}      | 71 ++++++----------
 .../resources/services/ambari/2.2.0/service.xml    | 26 ++++++
 .../resources/services/atlas-api/2.0.0/service.xml | 21 +++++
 .../resources/services/cm-api/1.0.0/service.xml    | 16 ++++
 .../services/druid-broker/0.0.1/service.xml        | 21 +++++
 .../services/druid-coordinator/0.0.1/service.xml   | 22 +++++
 .../services/druid-overlord/0.0.1/service.xml      | 16 ++++
 .../services/druid-router/0.0.1/service.xml        | 21 +++++
 .../resources/services/hbase/0.98.0/service.xml    | 26 ++++++
 .../resources/services/oozie/4.0.0/service.xml     | 16 ++++
 .../resources/services/ranger/1.0.0/service.xml    | 16 ++++
 .../resources/services/storm/0.9.3/service.xml     | 16 ++++
 .../resources/services/webhcat/0.13.0/service.xml  | 16 ++++
 .../resources/services/webhdfs/2.4.0/service.xml   | 21 +++++
 .../resources/services/yarn-rm/2.5.0/service.xml   | 16 ++++
 .../services/zeppelinws/0.8.1/service.xml          | 21 +++++
 .../gateway/service/metadata/ServiceModel.java     | 55 ++++++++++--
 knox-homepage-ui/home/app/app.module.ts            |  6 +-
 .../home/app/topologies/{service.ts => sample.ts}  |  9 +-
 knox-homepage-ui/home/app/topologies/service.ts    |  2 +
 .../topologies/topology.information.component.html | 98 +++++++++++++++-------
 .../topologies/topology.information.component.ts   | 12 ++-
 knox-homepage-ui/package-lock.json                 | 16 ++--
 knox-homepage-ui/package.json                      |  2 +-
 25 files changed, 471 insertions(+), 105 deletions(-)

diff --git 
a/gateway-service-definitions/src/main/java/org/apache/knox/gateway/service/definition/Metadata.java
 
b/gateway-service-definitions/src/main/java/org/apache/knox/gateway/service/definition/Metadata.java
index 960971d..ed9d7e3 100644
--- 
a/gateway-service-definitions/src/main/java/org/apache/knox/gateway/service/definition/Metadata.java
+++ 
b/gateway-service-definitions/src/main/java/org/apache/knox/gateway/service/definition/Metadata.java
@@ -17,7 +17,10 @@
  */
 package org.apache.knox.gateway.service.definition;
 
+import java.util.List;
+
 import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
 import javax.xml.bind.annotation.XmlType;
 
 import org.apache.commons.lang3.builder.EqualsBuilder;
@@ -32,6 +35,7 @@ public class Metadata {
   private String context;
   private String shortDesc;
   private String description;
+  private List<Sample> samples;
 
   @XmlElement(name = "type")
   public String getType() {
@@ -69,6 +73,16 @@ public class Metadata {
     this.description = description;
   }
 
+  @XmlElement(name = "sample")
+  @XmlElementWrapper(name = "samples")
+  public List<Sample> getSamples() {
+    return samples;
+  }
+
+  public void setSamples(List<Sample> samples) {
+    this.samples = samples;
+  }
+
   @Override
   public boolean equals(Object obj) {
     return EqualsBuilder.reflectionEquals(obj, this);
diff --git 
a/gateway-service-definitions/src/main/java/org/apache/knox/gateway/service/definition/Metadata.java
 
b/gateway-service-definitions/src/main/java/org/apache/knox/gateway/service/definition/Sample.java
similarity index 51%
copy from 
gateway-service-definitions/src/main/java/org/apache/knox/gateway/service/definition/Metadata.java
copy to 
gateway-service-definitions/src/main/java/org/apache/knox/gateway/service/definition/Sample.java
index 960971d..b69bce3 100644
--- 
a/gateway-service-definitions/src/main/java/org/apache/knox/gateway/service/definition/Metadata.java
+++ 
b/gateway-service-definitions/src/main/java/org/apache/knox/gateway/service/definition/Sample.java
@@ -20,68 +20,47 @@ package org.apache.knox.gateway.service.definition;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlType;
 
-import org.apache.commons.lang3.builder.EqualsBuilder;
-import org.apache.commons.lang3.builder.HashCodeBuilder;
-import org.apache.commons.lang3.builder.ToStringBuilder;
-import org.apache.commons.lang3.builder.ToStringStyle;
-
-@XmlType(name = "metadata")
-public class Metadata {
-
-  private String type;
-  private String context;
-  private String shortDesc;
+@XmlType(name = "sample")
+public class Sample {
   private String description;
+  private String method;
+  private String path;
+  private String value;
 
-  @XmlElement(name = "type")
-  public String getType() {
-    return type;
-  }
-
-  public void setType(String type) {
-    this.type = type;
-  }
-
-  @XmlElement(name = "context")
-  public String getContext() {
-    return context;
-  }
-
-  public void setContext(String context) {
-    this.context = context;
+  @XmlElement(name = "description")
+  public String getDescription() {
+    return description;
   }
 
-  @XmlElement(name = "shortDesc")
-  public String getShortDesc() {
-    return shortDesc;
+  public void setDescription(String description) {
+    this.description = description;
   }
 
-  public void setShortDesc(String shortDesc) {
-    this.shortDesc = shortDesc;
+  @XmlElement(name = "method")
+  public String getMethod() {
+    return method;
   }
 
-  @XmlElement(name = "description")
-  public String getDescription() {
-    return description;
+  public void setMethod(String method) {
+    this.method = method;
   }
 
-  public void setDescription(String description) {
-    this.description = description;
+  @XmlElement(name = "path")
+  public String getPath() {
+    return path;
   }
 
-  @Override
-  public boolean equals(Object obj) {
-    return EqualsBuilder.reflectionEquals(obj, this);
+  public void setPath(String path) {
+    this.path = path;
   }
 
-  @Override
-  public int hashCode() {
-    return HashCodeBuilder.reflectionHashCode(this);
+  @XmlElement(name = "value")
+  public String getValue() {
+    return value;
   }
 
-  @Override
-  public String toString() {
-    return ToStringBuilder.reflectionToString(this, 
ToStringStyle.SHORT_PREFIX_STYLE);
+  public void setValue(String value) {
+    this.value = value;
   }
 
 }
diff --git 
a/gateway-service-definitions/src/main/resources/services/ambari/2.2.0/service.xml
 
b/gateway-service-definitions/src/main/resources/services/ambari/2.2.0/service.xml
index 05da7ac..6e18736 100644
--- 
a/gateway-service-definitions/src/main/resources/services/ambari/2.2.0/service.xml
+++ 
b/gateway-service-definitions/src/main/resources/services/ambari/2.2.0/service.xml
@@ -20,6 +20,32 @@
         <context>/ambari/api</context>
         <shortDesc>Apache Ambari API</shortDesc>
         <description>The Ambari API facilitates the management and monitoring 
of the resources of an Apache Hadoop cluster.</description>
+        <samples>
+            <sample>
+                <description>Fetch all Ambari-managed clusters</description>
+                <method>GET</method>
+                <path>v1/clusters</path>
+            </sample>
+            <sample>
+                <description>Get the DATANODE component resource for the HDFS 
service of the cluster named 'c1'</description>
+                <method>GET</method>
+                <path>v1/clusters/c1/services/HDFS/components/DATANODE</path>
+            </sample>
+            <sample>
+                <description>Create the HDFS service.</description>
+                <method>POST</method>
+                <path>v1/clusters/c1/services/HDFS</path>
+            </sample>
+            <sample>
+                <description>Delete the cluster named 'c1'</description>
+                <method>DELETE</method>
+                <path>v1/clusters/c1</path>
+            </sample>
+            <sample>
+                <description>See the Apache Ambari's REST API documentation 
here</description>
+                
<value>https://github.com/apache/ambari/blob/trunk/ambari-server/docs/api/v1/index.md</value>
+            </sample>
+        </samples>
     </metadata>
     <policies>
         <policy role="webappsec"/>
diff --git 
a/gateway-service-definitions/src/main/resources/services/atlas-api/2.0.0/service.xml
 
b/gateway-service-definitions/src/main/resources/services/atlas-api/2.0.0/service.xml
index 5ba13d0..e8ec387 100644
--- 
a/gateway-service-definitions/src/main/resources/services/atlas-api/2.0.0/service.xml
+++ 
b/gateway-service-definitions/src/main/resources/services/atlas-api/2.0.0/service.xml
@@ -20,6 +20,27 @@
         <context>/atlas/api</context>
         <shortDesc>Atlas API</shortDesc>
         <description>Atlas exposes a variety of REST endpoints to work with 
types, entities, lineage and data discovery.</description>
+        <samples>
+            <sample>
+                <description>Retrieve data for the specified attribute search 
query</description>
+                <method>GET</method>
+                <path>v2/search/attribute</path>
+            </sample>
+            <sample>
+                <description>Attribute based search for entities satisfying 
the search parameters</description>
+                <method>POST</method>
+                <path>v2/search/basic</path>
+            </sample>
+            <sample>
+                <description>Bulk API to delete list of entities identified by 
its GUIDs</description>
+                <method>DELETE</method>
+                <path>v2/entity/bulk</path>
+            </sample>
+            <sample>
+                <description>You can check out Apache Atlas's REST API 
documentation (including a Swagger UI representation) here</description>
+                <value>https://atlas.apache.org/api/v2/</value>
+            </sample>
+        </samples>
     </metadata>
     <routes>
         <route path="/atlas/api/**"/>
diff --git 
a/gateway-service-definitions/src/main/resources/services/cm-api/1.0.0/service.xml
 
b/gateway-service-definitions/src/main/resources/services/cm-api/1.0.0/service.xml
index cbbad9e..bf77630 100644
--- 
a/gateway-service-definitions/src/main/resources/services/cm-api/1.0.0/service.xml
+++ 
b/gateway-service-definitions/src/main/resources/services/cm-api/1.0.0/service.xml
@@ -26,6 +26,22 @@
         <context>/cm-api</context>
         <shortDesc>Cloudera Manager REST API</shortDesc>
         <description>Cloudera Manager's REST API lets you work with existing 
tools, and programmatically manage your Hadoop clusters. The API is available 
in both Cloudera Express and Cloudera Enterprise, and comes with open-source 
client libraries.</description>
+        <samples>
+            <sample>
+                <description>Fetch all CM-managed clusters</description>
+                <method>GET</method>
+                <path>clusters</path>
+            </sample>
+            <sample>
+                <description>Fetches HDFS service details from cluster named 
'c1'</description>
+                <method>GET</method>
+                <path>clusters/c1/services/HDFS</path>
+            </sample>
+            <sample>
+                <description>You can checkout CM's API (v41) document 
here</description>
+                <value>https://cloudera.github.io/cm_api//</value>
+            </sample>
+        </samples>
     </metadata>
   <routes>
     <route path="/cm-api/**">
diff --git 
a/gateway-service-definitions/src/main/resources/services/druid-broker/0.0.1/service.xml
 
b/gateway-service-definitions/src/main/resources/services/druid-broker/0.0.1/service.xml
index ab089c0..34ccd60 100644
--- 
a/gateway-service-definitions/src/main/resources/services/druid-broker/0.0.1/service.xml
+++ 
b/gateway-service-definitions/src/main/resources/services/druid-broker/0.0.1/service.xml
@@ -22,6 +22,27 @@
         <description>The Broker is the process to route queries to if you want 
to run a distributed cluster. 
             It understands the metadata published to ZooKeeper about what 
segments exist on what processes and routes queries such that they hit the 
right processes. 
             This process also merges the result sets from all of the 
individual processes together. On start up, Historical processes announce 
themselves and the segments they are serving in Zookeeper.</description>
+        <samples>
+            <sample>
+                <description>Fetch a list of queryable 
datasources</description>
+                <method>GET</method>
+                <path>druid/v2/datasources</path>
+            </sample>
+            <sample>
+                <description>Fetch the dimensions and metrics of the 
datasource</description>
+                <method>GET</method>
+                <path>druid/v2/datasources/{dataSourceName}</path>
+            </sample>
+            <sample>
+                <description>Fetch the metrics of the datasource</description>
+                <method>GET</method>
+                <path>druid/v2/datasources/{dataSourceName}/metrics</path>
+            </sample>
+            <sample>
+                <description>You may check out Apache Druid Broker's REST API 
documentation here</description>
+                
<value>https://druid.apache.org/docs/latest/operations/api-reference.html#broker</value>
+            </sample>
+        </samples>
     </metadata>
     <routes>
     <route path="druid-broker/druid/broker/v1/{**}?{**}">
diff --git 
a/gateway-service-definitions/src/main/resources/services/druid-coordinator/0.0.1/service.xml
 
b/gateway-service-definitions/src/main/resources/services/druid-coordinator/0.0.1/service.xml
index 244e50f..33fcdfa 100644
--- 
a/gateway-service-definitions/src/main/resources/services/druid-coordinator/0.0.1/service.xml
+++ 
b/gateway-service-definitions/src/main/resources/services/druid-coordinator/0.0.1/service.xml
@@ -22,6 +22,28 @@
         <description>The Druid Coordinator process is primarily responsible 
for segment management and distribution. 
             More specifically, the Druid Coordinator process communicates to 
Historical processes to load or drop segments based on configurations. 
             The Druid Coordinator is responsible for loading new segments, 
dropping outdated segments, managing segment replication, and balancing segment 
load.</description>
+        <samples>
+            <sample>
+                <description>Fetch the current leader coordinator of the 
cluster</description>
+                <method>GET</method>
+                <path>druid/coordinator/v1/leader</path>
+            </sample>
+             <sample>
+                <description>Fetch the percentage of segments actually loaded 
in the cluster versus segments that should be loaded in the 
cluster</description>
+                <method>GET</method>
+                <path>druid/coordinator/v1/loadstatus</path>
+            </sample>
+            <sample>
+                <description>Marks as unused all segments belonging to a data 
source. Returns a JSON object of the form {"numChangedSegments": 
&lt;number&gt;} 
+                    with the number of segments in the database whose state 
has been changed (that is, the segments were marked as unused) as the result of 
this API call</description>
+                <method>DELETE</method>
+                <path>druid/coordinator/v1/datasources/{dataSourceName}</path>
+            </sample>
+            <sample>
+                <description>You may check out Apache Druid Coordinator's REST 
API documentation here</description>
+                
<value>https://druid.apache.org/docs/latest/operations/api-reference.html#coordinator</value>
+            </sample>
+        </samples>
     </metadata>
     <routes>
     <route path="druid-coordinator/status">
diff --git 
a/gateway-service-definitions/src/main/resources/services/druid-overlord/0.0.1/service.xml
 
b/gateway-service-definitions/src/main/resources/services/druid-overlord/0.0.1/service.xml
index 4968bc2..0dc6827 100644
--- 
a/gateway-service-definitions/src/main/resources/services/druid-overlord/0.0.1/service.xml
+++ 
b/gateway-service-definitions/src/main/resources/services/druid-overlord/0.0.1/service.xml
@@ -21,6 +21,22 @@
         <shortDesc>Druid Overlord API</shortDesc>
         <description>The Overlord process is responsible for accepting tasks, 
coordinating task distribution, creating locks around tasks, and returning 
statuses to callers. 
             Overlord can be configured to run in one of two modes - local or 
remote (local being default).</description>
+        <samples>
+            <sample>
+                <description>Fetch the current leader Overlord of the cluster. 
If you have multiple Overlords, just one is leading at any given time. The 
others are on standby</description>
+                <method>GET</method>
+                <path>druid/indexer/v1/leader</path>
+            </sample>
+             <sample>
+                <description>Fetch a list of ALL tasks</description>
+                <method>GET</method>
+                <path>druid/indexer/v1/tasks</path>
+            </sample>
+            <sample>
+                <description>You may check out Apache Druid Overlord's REST 
API documentation here</description>
+                
<value>https://druid.apache.org/docs/latest/operations/api-reference.html#overlord</value>
+            </sample>
+        </samples>
     </metadata>
   <routes>
     <route path="druid-overlord/druid/indexer/v1/{**}?{**}">
diff --git 
a/gateway-service-definitions/src/main/resources/services/druid-router/0.0.1/service.xml
 
b/gateway-service-definitions/src/main/resources/services/druid-router/0.0.1/service.xml
index 3245132..cf716cc 100644
--- 
a/gateway-service-definitions/src/main/resources/services/druid-router/0.0.1/service.xml
+++ 
b/gateway-service-definitions/src/main/resources/services/druid-router/0.0.1/service.xml
@@ -20,6 +20,27 @@
         <context>/druid-router</context>
         <shortDesc>Druid Router API</shortDesc>
         <description>The Apache Druid Router process can be used to route 
queries to different Broker processes. By default, the broker routes queries 
based on how Rules are set up</description>
+        <samples>
+            <sample>
+                <description>Fetch a list of queryable 
datasources</description>
+                <method>GET</method>
+                <path>druid/v2/datasources</path>
+            </sample>
+             <sample>
+                <description>Fetch the dimensions and metrics of the 
datasource</description>
+                <method>GET</method>
+                <path>druid/v2/datasources/{dataSourceName}</path>
+            </sample>
+            <sample>
+                <description>Fetch the metrics of the datasource</description>
+                <method>GET</method>
+                <path>druid/v2/datasources/{dataSourceName}/metrics</path>
+            </sample>
+            <sample>
+                <description>You may check out Apache Druid Router's REST API 
documentation here</description>
+                
<value>https://druid.apache.org/docs/latest/operations/api-reference.html#router</value>
+            </sample>
+        </samples>
     </metadata>
   <policies>
     <policy role="webappsec"/>
diff --git 
a/gateway-service-definitions/src/main/resources/services/hbase/0.98.0/service.xml
 
b/gateway-service-definitions/src/main/resources/services/hbase/0.98.0/service.xml
index 8d3d611..ece3501 100644
--- 
a/gateway-service-definitions/src/main/resources/services/hbase/0.98.0/service.xml
+++ 
b/gateway-service-definitions/src/main/resources/services/hbase/0.98.0/service.xml
@@ -20,6 +20,32 @@
         <context>/hbase</context>
         <shortDesc>Web HBase</shortDesc>
         <description>The HBase REST server exposes endpoints that provide CRUD 
(create, read, update, delete) operations for each HBase process, as well as 
tables, regions, and namespaces.</description>
+        <samples>
+            <sample>
+                <description>List all namespaces</description>
+                <method>GET</method>
+                <path>namespaces</path>
+            </sample>
+            <sample>
+                <description>Describe a specific namespace</description>
+                <method>GET</method>
+                <path>namespaces/special_ns</path>
+            </sample>
+            <sample>
+                <description>Create a new namespace</description>
+                <method>POST</method>
+                <path>namespaces/special_ns</path>
+            </sample>
+            <sample>
+                <description>Delete a namespace. The namespace must be 
empty.</description>
+                <method>DELETE</method>
+                <path>namespaces/special_ns</path>
+            </sample>
+            <sample>
+                <description>You may check out Apache Web HBase's REST API 
documentation here</description>
+                
<value>https://hbase.apache.org/book.html#_using_rest_endpointsl</value>
+            </sample>
+        </samples>
     </metadata>
     <routes>
         <route path="/hbase/?**">
diff --git 
a/gateway-service-definitions/src/main/resources/services/oozie/4.0.0/service.xml
 
b/gateway-service-definitions/src/main/resources/services/oozie/4.0.0/service.xml
index e2c2526..5e355fc 100644
--- 
a/gateway-service-definitions/src/main/resources/services/oozie/4.0.0/service.xml
+++ 
b/gateway-service-definitions/src/main/resources/services/oozie/4.0.0/service.xml
@@ -21,6 +21,22 @@
         <context>/oozie</context>
         <shortDesc>Oozie Web Services API</shortDesc>
         <description>Oozie is a workflow scheduler system to manage Apache 
Hadoop jobs. The Oozie Web Services API is a HTTP REST JSON API.</description>
+        <samples>
+            <sample>
+                <description>Fetch the supported Oozie protocol versions by 
the server</description>
+                <method>GET</method>
+                <path>oozie/versions</path>
+            </sample>
+             <sample>
+                <description>Fetch the system status</description>
+                <method>GET</method>
+                <path>oozie/v1/admin/status</path>
+            </sample>
+            <sample>
+                <description>You may check out Apache Oozie's REST API 
documentation here</description>
+                
<value>https://oozie.apache.org/docs/4.0.1/WebServicesAPI.html</value>
+            </sample>
+        </samples>
     </metadata>
     <routes>
         <route path="/oozie/**?**">
diff --git 
a/gateway-service-definitions/src/main/resources/services/ranger/1.0.0/service.xml
 
b/gateway-service-definitions/src/main/resources/services/ranger/1.0.0/service.xml
index db13e4b..947bb03 100644
--- 
a/gateway-service-definitions/src/main/resources/services/ranger/1.0.0/service.xml
+++ 
b/gateway-service-definitions/src/main/resources/services/ranger/1.0.0/service.xml
@@ -21,6 +21,22 @@
         <shortDesc>Ranger Admin REST API</shortDesc>
         <description>Apache Ranger is a framework to enable, monitor and 
manage comprehensive data security across the Hadoop platform. 
             Apache Ranger currently provides a centralized security 
adminstration, fine grain access control and detailed auditing for user access 
within Apache Hadoop, Apache Hive, Apache HBase and other Apache 
components</description>
+        <samples>
+            <sample>
+                <description>Fetch all policies</description>
+                <method>GET</method>
+                <path>public/v2/api/policy</path>
+            </sample>
+            <sample>
+                <description>Delete a role named 'name1'</description>
+                <method>DELETE</method>
+                <path>roles/roles/name/name1</path>
+            </sample>
+            <sample>
+                <description>You may check out Apache Ranger's REST API 
documentation here</description>
+                <value>https://ranger.apache.org/apidocs/index.html</value>
+            </sample>
+        </samples>
     </metadata>
     <routes>
         <route path="/ranger/service/public/**"/>
diff --git 
a/gateway-service-definitions/src/main/resources/services/storm/0.9.3/service.xml
 
b/gateway-service-definitions/src/main/resources/services/storm/0.9.3/service.xml
index 3549e7e..00cc757 100644
--- 
a/gateway-service-definitions/src/main/resources/services/storm/0.9.3/service.xml
+++ 
b/gateway-service-definitions/src/main/resources/services/storm/0.9.3/service.xml
@@ -21,6 +21,22 @@
         <shortDesc>Apache Storm API</shortDesc>
         <description>Apache Storm is a free and open source distributed 
realtime computation system. 
             Apache Storm makes it easy to reliably process unbounded streams 
of data, doing for realtime processing what Hadoop did for batch 
processing.</description>
+        <samples>
+            <sample>
+                <description>Fetch the cluster configuration</description>
+                <method>GET</method>
+                <path>api/v1/cluster/configuration</path>
+            </sample>
+            <sample>
+                <description>Fetch summary for a supervisors running on a host 
named 'supervisor-daemon-host-name'</description>
+                <method>GET</method>
+                <path>api/v1/supervisor?host=supervisor-daemon-host-name</path>
+            </sample>
+            <sample>
+                <description>You may check out Apache Storm's REST API 
documentation here</description>
+                
<value>http://storm.apache.org/releases/current/STORM-UI-REST-API.html</value>
+            </sample>
+        </samples>
     </metadata>
     <routes>
         <route path="/storm/api/**"/>
diff --git 
a/gateway-service-definitions/src/main/resources/services/webhcat/0.13.0/service.xml
 
b/gateway-service-definitions/src/main/resources/services/webhcat/0.13.0/service.xml
index b5adb31..7b0625b 100644
--- 
a/gateway-service-definitions/src/main/resources/services/webhcat/0.13.0/service.xml
+++ 
b/gateway-service-definitions/src/main/resources/services/webhcat/0.13.0/service.xml
@@ -21,6 +21,22 @@
         <context>/templeton</context>
         <shortDesc>WebHCat</shortDesc>
         <description>WebHCat is the REST API for HCatalog, a table and storage 
management layer for Hadoop.</description>
+        <samples>
+            <sample>
+                <description>List HCatalog databases</description>
+                <method>GET</method>
+                <path>ddl/database</path>
+            </sample>
+            <sample>
+                <description>List the tables in an HCatalog database named 
'db1'</description>
+                <method>GET</method>
+                <path>ddl/database/db1</path>
+            </sample>
+            <sample>
+                <description>You may check out Apache HCatalog's REST API 
documentation here</description>
+                
<value>https://cwiki.apache.org/confluence/display/Hive/WebHCat+Reference</value>
+            </sample>
+        </samples>
     </metadata>
     <routes>
         <route path="/templeton/v1/?**"/>
diff --git 
a/gateway-service-definitions/src/main/resources/services/webhdfs/2.4.0/service.xml
 
b/gateway-service-definitions/src/main/resources/services/webhdfs/2.4.0/service.xml
index a6b9e1b..48a7d41 100644
--- 
a/gateway-service-definitions/src/main/resources/services/webhdfs/2.4.0/service.xml
+++ 
b/gateway-service-definitions/src/main/resources/services/webhdfs/2.4.0/service.xml
@@ -21,6 +21,27 @@
         <context>/webhdfs</context>
         <shortDesc>Web HDFS</shortDesc>
         <description>An HTTP REST API which supports the complete FileSystem 
interface for HDFS.</description>
+        <samples>
+            <sample>
+                <description>List all files under 'testPath'</description>
+                <method>GET</method>
+                <path>v1/testPath?op=LISTSTATUS</path>
+            </sample>
+            <sample>
+                <description>Rename a File/Directory under </description>
+                <method>PUT</method>
+                
<path>v1/testPath/testFile?op=RENAME&amp;destination=testPath/renamedFile</path>
+            </sample>
+            <sample>
+                <description>Get Home Directory</description>
+                <method>GET</method>
+                <path>v1/?op=GETHOMEDIRECTORY</path>
+            </sample>
+            <sample>
+                <description>You may check out Apache WebHDFS's REST API 
documentation here</description>
+                
<value>https://hadoop.apache.org/docs/current/hadoop-project-dist/hadoop-hdfs/WebHDFS.html</value>
+            </sample>
+        </samples>
     </metadata>
     <routes>
         <route path="/webhdfs/v1/?**">
diff --git 
a/gateway-service-definitions/src/main/resources/services/yarn-rm/2.5.0/service.xml
 
b/gateway-service-definitions/src/main/resources/services/yarn-rm/2.5.0/service.xml
index 722abc6..76bbb18 100644
--- 
a/gateway-service-definitions/src/main/resources/services/yarn-rm/2.5.0/service.xml
+++ 
b/gateway-service-definitions/src/main/resources/services/yarn-rm/2.5.0/service.xml
@@ -21,6 +21,22 @@
         <context>/resourcemanager</context>
         <shortDesc>YARN Resource Manager</shortDesc>
         <description>The YARN Resource Manager Service (RM) is the central 
controlling authority for resource management and makes allocation decisions 
ResourceManager has two main components: Scheduler and 
ApplicationsManager.</description>
+        <samples>
+            <sample>
+                <description>Fetch cluster info</description>
+                <method>GET</method>
+                <path>ws/v1/cluster/info</path>
+            </sample>
+            <sample>
+                <description>Fetch cluster metrics</description>
+                <method>GET</method>
+                <path>ws/v1/cluster/metrics</path>
+            </sample>
+            <sample>
+                <description>You may check out Apache YARN Resource Manager's 
REST API documentation here</description>
+                
<value>https://hadoop.apache.org/docs/current/hadoop-yarn/hadoop-yarn-site/ResourceManagerRest.html</value>
+            </sample>
+        </samples>
     </metadata>
     <routes>
         <route path="/resourcemanager/v1/cluster/"/>
diff --git 
a/gateway-service-definitions/src/main/resources/services/zeppelinws/0.8.1/service.xml
 
b/gateway-service-definitions/src/main/resources/services/zeppelinws/0.8.1/service.xml
index 2e42b33..a743cf2 100644
--- 
a/gateway-service-definitions/src/main/resources/services/zeppelinws/0.8.1/service.xml
+++ 
b/gateway-service-definitions/src/main/resources/services/zeppelinws/0.8.1/service.xml
@@ -21,6 +21,27 @@
         <context>/zeppelin/ws</context>
         <shortDesc>Zeppelin WS API</shortDesc>
         <description>Apache Zeppelin is a web-based notebook that enables 
data-driven, interactive data analytics and collaborative documents with SQL, 
Scala and more.</description>
+        <samples>
+            <sample>
+                <description>Fetch the available notebooks on your 
server</description>
+                <method>GET</method>
+                <path>api/notebook</path>
+            </sample>
+            <sample>
+                <description>Fetch the status of all paragraphs by the given 
note id (e.g. 'note1')</description>
+                <method>GET</method>
+                <path>api/notebook/job/note1</path>
+            </sample>
+            <sample>
+                <description>Delete a note by the given note id (e.g. 
'note1')</description>
+                <method>DELETE</method>
+                <path>api/notebook/note1</path>
+            </sample>
+            <sample>
+                <description>You may check out Apache Zeppelin WS's REST API 
documentation here</description>
+                
<value>http://zeppelin.apache.org/docs/0.8.1/usage/rest_api/notebook.html</value>
+            </sample>
+        </samples>
     </metadata>
   <routes>
     <route path="/zeppelin/ws">
diff --git 
a/gateway-service-metadata/src/main/java/org/apache/knox/gateway/service/metadata/ServiceModel.java
 
b/gateway-service-metadata/src/main/java/org/apache/knox/gateway/service/metadata/ServiceModel.java
index 135684e..b00501c 100644
--- 
a/gateway-service-metadata/src/main/java/org/apache/knox/gateway/service/metadata/ServiceModel.java
+++ 
b/gateway-service-metadata/src/main/java/org/apache/knox/gateway/service/metadata/ServiceModel.java
@@ -20,19 +20,24 @@ package org.apache.knox.gateway.service.metadata;
 import java.io.UncheckedIOException;
 import java.net.MalformedURLException;
 import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Locale;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.xml.bind.annotation.XmlAccessType;
 import javax.xml.bind.annotation.XmlAccessorType;
 import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
 import javax.xml.bind.annotation.XmlRootElement;
 
+import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.builder.EqualsBuilder;
 import org.apache.commons.lang3.builder.HashCodeBuilder;
 import org.apache.commons.lang3.builder.ToStringBuilder;
 import org.apache.commons.lang3.builder.ToStringStyle;
 import org.apache.knox.gateway.service.definition.Metadata;
+import org.apache.knox.gateway.service.definition.Sample;
 import org.apache.knox.gateway.topology.Service;
 
 @XmlRootElement(name = "service")
@@ -40,6 +45,7 @@ import org.apache.knox.gateway.topology.Service;
 public class ServiceModel implements Comparable<ServiceModel> {
 
   static final String SERVICE_URL_TEMPLATE = "%s://%s:%s/%s/%s%s";
+  static final String CURL_SAMPLE_TEMPLATE = "curl -iv -X %s \"%s%s\"";
   static final String HIVE_SERVICE_NAME = "HIVE";
   static final String HIVE_SERVICE_URL_TEMPLATE = 
"jdbc:hive2://%s:%d/;ssl=true;transportMode=http;httpPath=%s/%s/hive";
 
@@ -122,22 +128,37 @@ public class ServiceModel implements 
Comparable<ServiceModel> {
     if (HIVE_SERVICE_NAME.equals(getServiceName())) {
       return String.format(Locale.ROOT, HIVE_SERVICE_URL_TEMPLATE, 
request.getServerName(), request.getServerPort(), gatewayPath, topologyName);
     } else {
+      return getServiceUrl(context);
+    }
+  }
+
+  private String getServiceUrl(String context) {
+    final String resolvedContext = resolvePlaceholdersFromBackendUrl(context);
+    return String.format(Locale.ROOT, SERVICE_URL_TEMPLATE, 
request.getScheme(), request.getServerName(), request.getServerPort(), 
gatewayPath, topologyName, resolvedContext);
+  }
+
+  private String resolvePlaceholdersFromBackendUrl(String resolveable) {
+    String toBeResolved = resolveable;
+    if (toBeResolved != null) {
       final String backendUrlString = getBackendServiceUrl();
-      if (context.indexOf("{{BACKEND_HOST}}") > -1) {
-        context = context.replace("{{BACKEND_HOST}}", backendUrlString);
+
+      if (toBeResolved.indexOf("{{BACKEND_HOST}}") > -1) {
+        toBeResolved = toBeResolved.replace("{{BACKEND_HOST}}", 
backendUrlString);
       }
-      if (context.indexOf("{{SCHEME}}") > -1 || context.indexOf("{{HOST}}") > 
-1 || context.indexOf("{{PORT}}") > -1) {
+
+      if (toBeResolved.indexOf("{{SCHEME}}") > -1 || 
toBeResolved.indexOf("{{HOST}}") > -1 || toBeResolved.indexOf("{{PORT}}") > -1) 
{
         try {
           final URL backendUrl = new URL(backendUrlString);
-          context = context.replace("{{SCHEME}}", backendUrl.getProtocol());
-          context = context.replace("{{HOST}}", backendUrl.getHost());
-          context = context.replace("{{PORT}}", 
String.valueOf(backendUrl.getPort()));
+          toBeResolved = toBeResolved.replace("{{SCHEME}}", 
backendUrl.getProtocol());
+          toBeResolved = toBeResolved.replace("{{HOST}}", 
backendUrl.getHost());
+          toBeResolved = toBeResolved.replace("{{PORT}}", 
String.valueOf(backendUrl.getPort()));
         } catch (MalformedURLException e) {
           throw new UncheckedIOException("Error while converting " + 
backendUrlString + " to a URL", e);
         }
       }
-      return String.format(Locale.ROOT, SERVICE_URL_TEMPLATE, 
request.getScheme(), request.getServerName(), request.getServerPort(), 
gatewayPath, topologyName, context);
     }
+
+    return toBeResolved;
   }
 
   String getBackendServiceUrl() {
@@ -145,6 +166,26 @@ public class ServiceModel implements 
Comparable<ServiceModel> {
     return backendServiceUrl == null ? "" : backendServiceUrl;
   }
 
+  @XmlElement(name = "sample")
+  @XmlElementWrapper(name = "samples")
+  public List<Sample> getSamples() {
+    final List<Sample> samples = new ArrayList<>();
+    if (serviceMetadata != null && serviceMetadata.getSamples() != null) {
+      serviceMetadata.getSamples().forEach(sample -> {
+        final Sample resolvedSample = new Sample();
+        resolvedSample.setDescription(sample.getDescription());
+        if (StringUtils.isNotBlank(sample.getValue())) {
+          resolvedSample.setValue(sample.getValue());
+        } else {
+          final String method = StringUtils.isBlank(sample.getMethod()) ? 
"GET" : sample.getMethod();
+          resolvedSample.setValue(String.format(Locale.ROOT, 
CURL_SAMPLE_TEMPLATE, method, getServiceUrl(), sample.getPath()));
+        }
+        samples.add(resolvedSample);
+      });
+    }
+    return samples;
+  }
+
   @Override
   public boolean equals(Object obj) {
     if (obj == this) {
diff --git a/knox-homepage-ui/home/app/app.module.ts 
b/knox-homepage-ui/home/app/app.module.ts
index d72bbe4..964e84e 100644
--- a/knox-homepage-ui/home/app/app.module.ts
+++ b/knox-homepage-ui/home/app/app.module.ts
@@ -15,10 +15,10 @@
  * limitations under the License.
  */
 import {NgModule} from '@angular/core';
-import {DataTableModule} from 'angular2-datatable';
 import {BrowserModule} from '@angular/platform-browser';
 import {HttpClientModule, HttpClientXsrfModule} from '@angular/common/http';
 import {MatGridListModule} from '@angular/material/grid-list';
+import {BsModalModule} from 'ng2-bs3-modal/ng2-bs3-modal';
 
 import {GeneralProxyInformationComponent} from 
'./generalProxyInformation/general.proxy.information.component';
 import {TopologyInformationsComponent} from 
'./topologies/topology.information.component';
@@ -28,8 +28,8 @@ import {HomepageService} from './homepage.service';
     imports: [BrowserModule,
         HttpClientModule,
         HttpClientXsrfModule,
-        DataTableModule,
-        MatGridListModule
+        MatGridListModule,
+        BsModalModule
     ],
     declarations: [GeneralProxyInformationComponent,
                    TopologyInformationsComponent
diff --git a/knox-homepage-ui/home/app/topologies/service.ts 
b/knox-homepage-ui/home/app/topologies/sample.ts
similarity index 84%
copy from knox-homepage-ui/home/app/topologies/service.ts
copy to knox-homepage-ui/home/app/topologies/sample.ts
index c3ae63d..2d92417 100644
--- a/knox-homepage-ui/home/app/topologies/service.ts
+++ b/knox-homepage-ui/home/app/topologies/sample.ts
@@ -15,12 +15,7 @@
  * limitations under the License.
  */
 
-export class Service {
+export class Sample {
     description: string;
-    serviceName: string;
-    version: string;
-    serviceUrl: string;
-    shortDesc: string;
-    type: string;
-    context: string;
+    value: string;
 }
diff --git a/knox-homepage-ui/home/app/topologies/service.ts 
b/knox-homepage-ui/home/app/topologies/service.ts
index c3ae63d..dca781a 100644
--- a/knox-homepage-ui/home/app/topologies/service.ts
+++ b/knox-homepage-ui/home/app/topologies/service.ts
@@ -14,6 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+import {Sample} from './sample';
 
 export class Service {
     description: string;
@@ -23,4 +24,5 @@ export class Service {
     shortDesc: string;
     type: string;
     context: string;
+    samples: Sample[];
 }
diff --git 
a/knox-homepage-ui/home/app/topologies/topology.information.component.html 
b/knox-homepage-ui/home/app/topologies/topology.information.component.html
index 4ba685f..281ce60 100644
--- a/knox-homepage-ui/home/app/topologies/topology.information.component.html
+++ b/knox-homepage-ui/home/app/topologies/topology.information.component.html
@@ -33,6 +33,8 @@
 
     <div class="table-responsive" *ngIf="this['showTopology_' + 
topology.topology]">
 
+        <h5 *ngIf="topology.uiServices.service.length > 0">UI Services</h5>
+
         <!-- UI services -->
         <mat-grid-list cols="4" rowHeight="130px">
             <mat-grid-tile *ngFor="let service of topology.uiServices.service" 
[colspan]="1" [rowspan]="1">
@@ -51,38 +53,72 @@
             </mat-grid-tile>
         </mat-grid-list>
 
+        <h5 *ngIf="topology.apiServices.service.length > 0">API Services</h5>
+
         <!-- API services -->
-        <table class="table table-hover" 
[mfData]="topology.apiServices.service" #api="mfDataTable" [mfRowsOnPage]="5">
-            <colgroup>
-                <col width="30%">
-                <col width="70%">
-            </colgroup>
-            <thead>
-                <tr *ngIf="topology.apiServices.service.length == 0"><th 
colspan="2">No API services found</th></tr>
-                <tr *ngIf="topology.apiServices.service.length > 0"><th 
colspan="2">API services</th></tr>
-            </thead>
-            <tbody>
-                <tr *ngFor="let service of api.data">
-                    <td>
-                        <span class="inline-glyph glyphicon 
glyphicon-info-sign btn btn-xs"
-                        title="{{service.description}}"
-                        data-toggle="tooltip"></span>
-                        {{service.shortDesc}} <span class="small" 
*ngIf="service.version">(v{{service.version}})</span>
-                    </td>
-                    <td>
-                        <a 
href="{{service.serviceUrl}}">{{service.serviceUrl}}</a>
-                    </td>
-                </tr>
-            </tbody>
-      <tfoot>
-          <tr>
-              <td colspan="4">
-                  <mfBootstrapPaginator 
[rowsOnPageSet]="[5,10,15]"></mfBootstrapPaginator>
-              </td>
-          </tr>
-      </tfoot>
-        </table>
+        <mat-grid-list cols="4" rowHeight="130px">
+            <mat-grid-tile *ngFor="let service of 
topology.apiServices.service" [colspan]="1" [rowspan]="1">
+                <span *ngIf="!this['enableServiceText_' + 
service.serviceName.toLowerCase()]" 
(click)="openApiServiceInformationModal(service)">
+                    <img 
src="assets/service-logos/{{service.serviceName.toLowerCase()}}.png" 
height="50px" (error)="enableServiceText('enableServiceText_' + 
service.serviceName.toLowerCase())"/>
+                </span>
+                <span *ngIf="this['enableServiceText_' + 
service.serviceName.toLowerCase()]" 
(click)="openApiServiceInformationModal(service)">
+                    {{service.shortDesc}}
+                </span>
+                <mat-grid-tile-footer class="tile-shortDesc">
+                    <h3>{{service.shortDesc}} <span class="small" 
*ngIf="service.version">(v{{service.version}})</span></h3>
+                </mat-grid-tile-footer>
+                <mat-grid-tile-footer class="tile-longDesc" 
style="height:100px;">
+                    <h3>{{service.description}}</h3>
+                </mat-grid-tile-footer>
+            </mat-grid-tile>
+        </mat-grid-list>
     </div>
 </ng-container>
 <hr />
-</div>
\ No newline at end of file
+</div>
+
+<bs-modal #apiServiceInformationModal>
+    <bs-modal-header [showDismiss]="true" *ngIf="selectedApiService">
+        <h4 class="modal-title">{{selectedApiService.shortDesc}}</h4>
+    </bs-modal-header>
+    <bs-modal-body *ngIf="selectedApiService">
+        <div class="panel panel-default table-responsive">
+            <table class="table table-sm">
+                <colgroup>
+                   <col width="25%">
+                   <col width="75%">
+               </colgroup>
+               <tr>
+                   <td style="font-weight: bold;">Knox Service Name</td>
+                   <td>{{selectedApiService.serviceName}} <span class="small" 
*ngIf="selectedApiService.version">(v{{selectedApiService.version}})</span></td>
+               </tr>
+               <tr>
+                   <td style="font-weight: bold;">Description</td>
+                   <td>{{selectedApiService.description}}</td>
+               </tr>
+               <tr>
+                   <td style="font-weight: bold;">Sample(s)</td>
+                   <td>
+                     <table class="table table-sm">
+                       <div *ngIf="selectedApiService.samples && 
selectedApiService.samples.sample.length > 0">
+                         <ng-container *ngFor="let sample of 
selectedApiService.samples.sample">
+                           <tr><td style="font-weight: 
bold;">{{sample.description}}</td></tr>
+                           <tr style="margin-bottom: 
15px"><td>&nbsp;&nbsp;{{sample.value}}</tr>
+                         </ng-container>
+                       </div>
+                       <div *ngIf="!selectedApiService.samples || 
selectedApiService.samples.sample.length < 1">
+                         <tr><td style="font-weight: bold;">There is no any 
sample found in service metadata</td></tr>
+                         <tr>
+                           <td>&nbsp;You may check out the service's 
documentation and find out how to use its REST API. The service's URL is <a 
href="{{selectedApiService.serviceUrl}}" 
target="_blank">{{selectedApiService.serviceUrl}}</a></td>
+                         </tr>
+                       </div>
+                     </table>
+                   </td>
+               </tr>
+           </table>
+       </div>
+    </bs-modal-body>
+    <bs-modal-footer>
+        <button type="button" class="btn btn-primary btn-sm" 
(click)="apiServiceInformationModal.close()">Close</button>
+    </bs-modal-footer>
+</bs-modal>
diff --git 
a/knox-homepage-ui/home/app/topologies/topology.information.component.ts 
b/knox-homepage-ui/home/app/topologies/topology.information.component.ts
index f251a8f..c3a394c 100644
--- a/knox-homepage-ui/home/app/topologies/topology.information.component.ts
+++ b/knox-homepage-ui/home/app/topologies/topology.information.component.ts
@@ -14,8 +14,9 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-import {Component, OnInit} from '@angular/core';
+import {Component, OnInit, ViewChild} from '@angular/core';
 import {MatGridListModule} from '@angular/material/grid-list';
+import {BsModalComponent} from 'ng2-bs3-modal/ng2-bs3-modal';
 import {HomepageService} from '../homepage.service';
 import {TopologyInformation} from './topology.information';
 import {Service} from './service';
@@ -29,7 +30,11 @@ import {Service} from './service';
 
 export class TopologyInformationsComponent implements OnInit {
 
+    @ViewChild('apiServiceInformationModal')
+    apiServiceInformationModal: BsModalComponent;
+
     topologies: TopologyInformation[];
+    selectedApiService : Service;
 
     setTopologies(topologies: TopologyInformation[]) {
         this.topologies = topologies;
@@ -55,4 +60,9 @@ export class TopologyInformationsComponent implements OnInit {
         this.homepageService.getTopologies().then(topologies => 
this.setTopologies(topologies));
     }
 
+    openApiServiceInformationModal(apiService: Service) {
+        this.selectedApiService = apiService;
+        this.apiServiceInformationModal.open('lg');
+    }
+
 }
diff --git a/knox-homepage-ui/package-lock.json 
b/knox-homepage-ui/package-lock.json
index d6f75b8..0d16d41 100644
--- a/knox-homepage-ui/package-lock.json
+++ b/knox-homepage-ui/package-lock.json
@@ -390,14 +390,6 @@
       "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=",
       "dev": true
     },
-    "angular2-datatable": {
-      "version": "0.6.0",
-      "resolved": 
"https://registry.npmjs.org/angular2-datatable/-/angular2-datatable-0.6.0.tgz";,
-      "integrity": "sha1-ygCPdAh/DLh9pXCe0vLR0GF3JjI=",
-      "requires": {
-        "lodash": "^4.0.0"
-      }
-    },
     "ansi-html": {
       "version": "0.0.7",
       "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz";,
@@ -4682,7 +4674,8 @@
     "lodash": {
       "version": "4.17.15",
       "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz";,
-      "integrity": 
"sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
+      "integrity": 
"sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
+      "dev": true
     },
     "lodash.clonedeep": {
       "version": "4.5.0",
@@ -5119,6 +5112,11 @@
       "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=",
       "dev": true
     },
+    "ng2-bs3-modal": {
+      "version": "0.13.0",
+      "resolved": 
"https://registry.npmjs.org/ng2-bs3-modal/-/ng2-bs3-modal-0.13.0.tgz";,
+      "integrity": 
"sha512-rCxLpyTFXGpQOQCm32N4xGTN2roBsmIyUNQw6dFd/2yjVK+t7zmsFSO5IIuHioXAzTVGr4/LHFTOiz0JvJGnbg=="
+    },
     "no-case": {
       "version": "2.3.2",
       "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz";,
diff --git a/knox-homepage-ui/package.json b/knox-homepage-ui/package.json
index d282245..71e4e96 100644
--- a/knox-homepage-ui/package.json
+++ b/knox-homepage-ui/package.json
@@ -20,11 +20,11 @@
     "@angular/platform-browser": "^5.2.0",
     "@angular/platform-browser-dynamic": "^5.2.0",
     "@angular/router": "^5.2.0",
-    "angular2-datatable": "^0.6.0",
     "bootstrap": "^3.4.1",
     "core-js": "^2.6.11",
     "jquery": "^3.4.1",
     "js-yaml": "^3.13.1",
+    "ng2-bs3-modal": "^0.13.0",
     "popper.js": "^1.16.1",
     "rxjs": "^5.5.2",
     "sweetalert": "^2.1.2",

Reply via email to