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

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


The following commit(s) were added to refs/heads/master by this push:
     new 39e4673787c HDDS-499. Display descriptions for properties on the 
configuration page (#9152)
39e4673787c is described below

commit 39e4673787cecfbae7b4c0b160b4dc28c5a2f341
Author: Rishabh Patel <[email protected]>
AuthorDate: Wed Nov 19 05:47:48 2025 -0800

    HDDS-499. Display descriptions for properties on the configuration page 
(#9152)
---
 .../hadoop/hdds/conf/OzoneConfiguration.java       | 30 +++++--
 .../apache/hadoop/hdds/conf/HddsConfServlet.java   | 98 +++++++++++++++++++++-
 .../src/main/resources/webapps/static/ozone.js     | 10 ++-
 .../resources/webapps/static/templates/config.html |  4 +-
 4 files changed, 126 insertions(+), 16 deletions(-)

diff --git 
a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/conf/OzoneConfiguration.java
 
b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/conf/OzoneConfiguration.java
index f863f3a303e..fc09a5a5933 100644
--- 
a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/conf/OzoneConfiguration.java
+++ 
b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/conf/OzoneConfiguration.java
@@ -209,11 +209,16 @@ public boolean equals(Object obj) {
     }
   }
 
-  /** Add default resources. */
-  public static void activate() {
-    // core-default and core-site are added by parent class
-    addDefaultResource("hdfs-default.xml");
-    addDefaultResource("hdfs-site.xml");
+  public static List<String> getConfigurationResourceFiles() {
+    List<String> resourceFiles = new ArrayList<>();
+
+    // even though core-default and core-site are added by the parent 
Configuration class,
+    // we add it here for them to be a part of the resourceFiles list.
+    // addDefaultResource is idempotent so any duplicate items in this list 
will be handled accordingly
+    resourceFiles.add("hdfs-default.xml");
+    resourceFiles.add("hdfs-site.xml");
+    resourceFiles.add("core-default.xml");
+    resourceFiles.add("core-site.xml");
 
     // Modules with @Config annotations.  If new one is introduced, add it to 
this list.
     String[] modules = new String[] {
@@ -228,12 +233,21 @@ public static void activate() {
         "ozone-recon",
     };
     for (String module : modules) {
-      addDefaultResource(module + "-default.xml");
+      resourceFiles.add(module + "-default.xml");
     }
 
     // Non-generated configs
-    addDefaultResource("ozone-default.xml");
-    addDefaultResource("ozone-site.xml");
+    resourceFiles.add("ozone-default.xml");
+    resourceFiles.add("ozone-site.xml");
+
+    return resourceFiles;
+  }
+
+  /** Add default resources. */
+  public static void activate() {
+    for (String resourceFile : getConfigurationResourceFiles()) {
+      addDefaultResource(resourceFile);
+    }
   }
 
   /**
diff --git 
a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/conf/HddsConfServlet.java
 
b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/conf/HddsConfServlet.java
index 066735a0258..719ce052276 100644
--- 
a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/conf/HddsConfServlet.java
+++ 
b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/conf/HddsConfServlet.java
@@ -17,8 +17,12 @@
 
 package org.apache.hadoop.hdds.conf;
 
+import static 
org.apache.hadoop.hdds.conf.OzoneConfiguration.getConfigurationResourceFiles;
+
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.Writer;
+import java.net.URL;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Properties;
@@ -26,14 +30,22 @@
 import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import org.apache.commons.lang3.StringUtils;
 import org.apache.hadoop.conf.ConfServlet.BadFormatException;
 import org.apache.hadoop.hdds.annotation.InterfaceAudience;
 import org.apache.hadoop.hdds.annotation.InterfaceStability;
 import org.apache.hadoop.hdds.server.JsonUtils;
 import org.apache.hadoop.hdds.server.http.HttpServer2;
 import org.apache.hadoop.hdds.utils.HttpServletUtils;
+import org.apache.hadoop.util.XMLUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
 
 /**
  * A servlet to print out the running configuration data.
@@ -123,12 +135,25 @@ private void processConfigTagRequest(HttpServletRequest 
request, String cmd, Htt
         throw new IllegalArgumentException("The tags parameter should be set" +
             " when using the getPropertyByTag command.");
       }
-      Map<String, Properties> propMap = new HashMap<>();
+
+      Map<String, String> descriptionMap = buildDescriptionMap(config);
+      Map<String, Map<String, OzoneConfiguration.Property>> propMap = new 
HashMap<>();
 
       for (String tag : tags.split(",")) {
         if (config.isPropertyTag(tag)) {
           Properties properties = config.getAllPropertiesByTag(tag);
-          propMap.put(tag, properties);
+          Map<String, OzoneConfiguration.Property> metadataMap = new 
HashMap<>();
+
+          for (String propName : properties.stringPropertyNames()) {
+            String value = properties.getProperty(propName);
+            String description = descriptionMap.getOrDefault(propName, "");
+            OzoneConfiguration.Property property = new 
OzoneConfiguration.Property();
+            property.setName(propName);
+            property.setValue(value);
+            property.setDescription(description);
+            metadataMap.put(propName, property);
+          }
+          propMap.put(tag, metadataMap);
         }
       }
       out.write(JsonUtils.toJsonString(propMap));
@@ -138,6 +163,75 @@ private void processConfigTagRequest(HttpServletRequest 
request, String cmd, Htt
     }
   }
 
+  /**
+   * Build a map of property names to descriptions by reading from 
configuration resources.
+   * @param config the OzoneConfiguration to extract descriptions from
+   * @return map of property name to description
+   */
+  private Map<String, String> buildDescriptionMap(OzoneConfiguration config) {
+    Map<String, String> descriptionMap = new HashMap<>();
+
+    try {
+      DocumentBuilderFactory factory = 
XMLUtils.newSecureDocumentBuilderFactory();
+      DocumentBuilder builder = factory.newDocumentBuilder();
+
+      for (String resourceName : getConfigurationResourceFiles()) {
+        URL resourceUrl = config.getResource(resourceName);
+        if (resourceUrl != null) {
+          parseXmlDescriptions(builder, resourceUrl, descriptionMap);
+        }
+      }
+    } catch (Exception e) {
+      LOG.error("Failed to parse XML resource files", e);
+    }
+
+    return descriptionMap;
+  }
+
+  /**
+   * Parse XML configuration file and extract property descriptions using DOM 
parser.
+   * @param builder The XML parser
+   * @param resourceUrl URL of the XML resource to parse
+   * @param descriptionMap map to populate with property name -> description 
mappings
+   */
+  private void parseXmlDescriptions(DocumentBuilder builder, URL resourceUrl, 
Map<String, String> descriptionMap) {
+    try (InputStream inputStream = resourceUrl.openStream()) {
+      Document doc = builder.parse(inputStream);
+      NodeList propertyNodes = doc.getElementsByTagName("property");
+
+      for (int i = 0; i < propertyNodes.getLength(); i++) {
+        Node propertyNode = propertyNodes.item(i);
+        if (propertyNode.getNodeType() == Node.ELEMENT_NODE) {
+          Element propertyElement = (Element) propertyNode;
+
+          String name = getTextContent(propertyElement, "name");
+          String description = getTextContent(propertyElement, "description");
+
+          if (name != null && !StringUtils.isBlank(description)) {
+            descriptionMap.put(name, description.trim());
+          }
+        }
+      }
+    } catch (Exception e) {
+      LOG.error("Failed to parse XML from resource: {}", resourceUrl, e);
+    }
+  }
+
+  /**
+   * Get text content of a child element by tag name.
+   * @param parent parent element
+   * @param tagName tag name of child element
+   * @return text content of the child element, or null if not found
+   */
+  private String getTextContent(Element parent, String tagName) {
+    NodeList nodeList = parent.getElementsByTagName(tagName);
+    if (nodeList.getLength() > 0) {
+      Node node = nodeList.item(0);
+      return node.getTextContent();
+    }
+    return null;
+  }
+
   private static OzoneConfiguration getOzoneConfig() {
     return OZONE_CONFIG;
   }
diff --git a/hadoop-hdds/framework/src/main/resources/webapps/static/ozone.js 
b/hadoop-hdds/framework/src/main/resources/webapps/static/ozone.js
index 7bb93106284..aac641e625e 100644
--- a/hadoop-hdds/framework/src/main/resources/webapps/static/ozone.js
+++ b/hadoop-hdds/framework/src/main/resources/webapps/static/ozone.js
@@ -296,13 +296,15 @@
         for (var idx in srcObj) {
           //console.log("Adding keys for "+idx)
           for (var key in srcObj[idx]) {
-
+            var propMetadata = srcObj[idx][key];
+            
             if (ctrl.keyTagMap.hasOwnProperty(key)) {
               ctrl.keyTagMap[key]['tag'].push(idx);
             } else {
               var newProp = {};
-              newProp['name'] = key;
-              newProp['value'] = srcObj[idx][key];
+              newProp['name'] = propMetadata.name || key;
+              newProp['value'] = propMetadata.value;
+              newProp['description'] = propMetadata.description || '';
               newProp['tag'] = [];
               newProp['tag'].push(idx);
               ctrl.keyTagMap[key] = newProp;
@@ -392,4 +394,4 @@
     }
   });
 
-})();
\ No newline at end of file
+})();
diff --git 
a/hadoop-hdds/framework/src/main/resources/webapps/static/templates/config.html 
b/hadoop-hdds/framework/src/main/resources/webapps/static/templates/config.html
index b52f6533fc9..9d3bc90915d 100644
--- 
a/hadoop-hdds/framework/src/main/resources/webapps/static/templates/config.html
+++ 
b/hadoop-hdds/framework/src/main/resources/webapps/static/templates/config.html
@@ -81,8 +81,8 @@
       <tbody>
       <tr
           ng-repeat="config in $ctrl.configs | filter:search | 
orderBy:$ctrl.propertyName:$ctrl.reverse">
-        <td style="word-wrap: break-word;">{{config.name}}</td>
-        <td style="word-wrap: break-word;">{{config.value}}</td>
+        <td style="word-wrap: break-word; font-family: 
monospace;">{{config.name}}</td>
+        <td style="word-wrap: break-word; font-family: 
monospace;">{{config.value}}</td>
         <td style="word-wrap: break-word;">{{config.description}}</td>
       </tr>
       </tbody>


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to